summaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/abilitieswindow.cpp (renamed from src/gui/specialswindow.cpp)88
-rw-r--r--src/gui/abilitieswindow.h (renamed from src/gui/specialswindow.h)23
-rw-r--r--src/gui/beingpopup.h5
-rw-r--r--src/gui/buydialog.h5
-rw-r--r--src/gui/buyselldialog.h5
-rw-r--r--src/gui/changeemaildialog.h5
-rw-r--r--src/gui/changepassworddialog.h5
-rw-r--r--src/gui/charcreatedialog.cpp67
-rw-r--r--src/gui/charcreatedialog.h11
-rw-r--r--src/gui/charselectdialog.cpp4
-rw-r--r--src/gui/charselectdialog.h5
-rw-r--r--src/gui/chatwindow.cpp38
-rw-r--r--src/gui/chatwindow.h21
-rw-r--r--src/gui/confirmdialog.h5
-rw-r--r--src/gui/connectiondialog.h5
-rw-r--r--src/gui/customserverdialog.cpp67
-rw-r--r--src/gui/customserverdialog.h25
-rw-r--r--src/gui/debugwindow.cpp18
-rw-r--r--src/gui/debugwindow.h16
-rw-r--r--src/gui/emotepopup.cpp65
-rw-r--r--src/gui/emotepopup.h9
-rw-r--r--src/gui/equipmentwindow.cpp121
-rw-r--r--src/gui/equipmentwindow.h28
-rw-r--r--src/gui/focushandler.h5
-rw-r--r--src/gui/gui.cpp72
-rw-r--r--src/gui/gui.h63
-rw-r--r--src/gui/helpwindow.cpp20
-rw-r--r--src/gui/helpwindow.h5
-rw-r--r--src/gui/inventorywindow.cpp124
-rw-r--r--src/gui/inventorywindow.h39
-rw-r--r--src/gui/itemamountwindow.cpp13
-rw-r--r--src/gui/itemamountwindow.h8
-rw-r--r--src/gui/itempopup.cpp51
-rw-r--r--src/gui/itempopup.h8
-rw-r--r--src/gui/logindialog.cpp4
-rw-r--r--src/gui/logindialog.h5
-rw-r--r--src/gui/minimap.cpp61
-rw-r--r--src/gui/minimap.h5
-rw-r--r--src/gui/ministatuswindow.cpp208
-rw-r--r--src/gui/ministatuswindow.h33
-rw-r--r--src/gui/npcdialog.cpp40
-rw-r--r--src/gui/npcdialog.h5
-rw-r--r--src/gui/npcpostdialog.h5
-rw-r--r--src/gui/okdialog.h5
-rw-r--r--src/gui/outfitwindow.cpp26
-rw-r--r--src/gui/outfitwindow.h9
-rw-r--r--src/gui/palette.cpp51
-rw-r--r--src/gui/palette.h70
-rw-r--r--src/gui/popupmenu.cpp39
-rw-r--r--src/gui/popupmenu.h5
-rw-r--r--src/gui/quitdialog.cpp10
-rw-r--r--src/gui/quitdialog.h5
-rw-r--r--src/gui/recorder.cpp15
-rw-r--r--src/gui/recorder.h5
-rw-r--r--src/gui/register.cpp4
-rw-r--r--src/gui/register.h5
-rw-r--r--src/gui/sdlinput.h5
-rw-r--r--src/gui/selldialog.cpp2
-rw-r--r--src/gui/selldialog.h5
-rw-r--r--src/gui/serverdialog.cpp288
-rw-r--r--src/gui/serverdialog.h40
-rw-r--r--src/gui/setup.h5
-rw-r--r--src/gui/setup_audio.cpp7
-rw-r--r--src/gui/setup_audio.h5
-rw-r--r--src/gui/setup_colors.cpp45
-rw-r--r--src/gui/setup_colors.h5
-rw-r--r--src/gui/setup_interface.cpp92
-rw-r--r--src/gui/setup_interface.h16
-rw-r--r--src/gui/setup_joystick.h5
-rw-r--r--src/gui/setup_keyboard.h5
-rw-r--r--src/gui/setup_players.cpp8
-rw-r--r--src/gui/setup_players.h5
-rw-r--r--src/gui/setup_video.cpp10
-rw-r--r--src/gui/setup_video.h8
-rw-r--r--src/gui/shortcutwindow.cpp11
-rw-r--r--src/gui/shortcutwindow.h5
-rw-r--r--src/gui/skilldialog.cpp148
-rw-r--r--src/gui/skilldialog.h16
-rw-r--r--src/gui/socialwindow.cpp31
-rw-r--r--src/gui/socialwindow.h5
-rw-r--r--src/gui/speechbubble.cpp13
-rw-r--r--src/gui/speechbubble.h5
-rw-r--r--src/gui/statuswindow.cpp2
-rw-r--r--src/gui/statuswindow.h5
-rw-r--r--src/gui/textdialog.h5
-rw-r--r--src/gui/textpopup.h5
-rw-r--r--src/gui/tradewindow.cpp24
-rw-r--r--src/gui/tradewindow.h10
-rw-r--r--src/gui/truetypefont.cpp25
-rw-r--r--src/gui/truetypefont.h5
-rw-r--r--src/gui/unregisterdialog.h5
-rw-r--r--src/gui/updaterwindow.cpp406
-rw-r--r--src/gui/updaterwindow.h97
-rw-r--r--src/gui/viewport.cpp14
-rw-r--r--src/gui/viewport.h5
-rw-r--r--src/gui/widgets/avatarlistbox.cpp64
-rw-r--r--src/gui/widgets/avatarlistbox.h12
-rw-r--r--src/gui/widgets/browserbox.cpp259
-rw-r--r--src/gui/widgets/browserbox.h45
-rw-r--r--src/gui/widgets/button.cpp205
-rw-r--r--src/gui/widgets/button.h23
-rw-r--r--src/gui/widgets/channeltab.h5
-rw-r--r--src/gui/widgets/chattab.cpp2
-rw-r--r--src/gui/widgets/chattab.h5
-rw-r--r--src/gui/widgets/checkbox.cpp126
-rw-r--r--src/gui/widgets/checkbox.h32
-rw-r--r--src/gui/widgets/container.h10
-rw-r--r--src/gui/widgets/desktop.cpp2
-rw-r--r--src/gui/widgets/desktop.h5
-rw-r--r--src/gui/widgets/dropdown.cpp201
-rw-r--r--src/gui/widgets/dropdown.h25
-rw-r--r--src/gui/widgets/emoteshortcutcontainer.cpp57
-rw-r--r--src/gui/widgets/emoteshortcutcontainer.h7
-rw-r--r--src/gui/widgets/flowcontainer.h5
-rw-r--r--src/gui/widgets/icon.cpp2
-rw-r--r--src/gui/widgets/icon.h5
-rw-r--r--src/gui/widgets/inttextfield.h5
-rw-r--r--src/gui/widgets/itemcontainer.cpp97
-rw-r--r--src/gui/widgets/itemcontainer.h9
-rw-r--r--src/gui/widgets/itemlinkhandler.h5
-rw-r--r--src/gui/widgets/itemshortcutcontainer.cpp96
-rw-r--r--src/gui/widgets/itemshortcutcontainer.h11
-rw-r--r--src/gui/widgets/label.cpp35
-rw-r--r--src/gui/widgets/label.h30
-rw-r--r--src/gui/widgets/layout.h14
-rw-r--r--src/gui/widgets/layouthelper.h5
-rw-r--r--src/gui/widgets/linkhandler.h5
-rw-r--r--src/gui/widgets/listbox.cpp23
-rw-r--r--src/gui/widgets/listbox.h14
-rw-r--r--src/gui/widgets/passwordfield.h5
-rw-r--r--src/gui/widgets/playerbox.cpp76
-rw-r--r--src/gui/widgets/playerbox.h23
-rw-r--r--src/gui/widgets/popup.cpp82
-rw-r--r--src/gui/widgets/popup.h44
-rw-r--r--src/gui/widgets/progressbar.cpp100
-rw-r--r--src/gui/widgets/progressbar.h28
-rw-r--r--src/gui/widgets/progressindicator.cpp10
-rw-r--r--src/gui/widgets/progressindicator.h8
-rw-r--r--src/gui/widgets/radiobutton.cpp118
-rw-r--r--src/gui/widgets/radiobutton.h35
-rw-r--r--src/gui/widgets/resizegrip.cpp40
-rw-r--r--src/gui/widgets/resizegrip.h16
-rw-r--r--src/gui/widgets/scrollarea.cpp692
-rw-r--r--src/gui/widgets/scrollarea.h76
-rw-r--r--src/gui/widgets/setuptab.h5
-rw-r--r--src/gui/widgets/shopitems.h5
-rw-r--r--src/gui/widgets/shoplistbox.cpp18
-rw-r--r--src/gui/widgets/shoplistbox.h5
-rw-r--r--src/gui/widgets/shortcutcontainer.cpp10
-rw-r--r--src/gui/widgets/shortcutcontainer.h25
-rw-r--r--src/gui/widgets/slider.cpp167
-rw-r--r--src/gui/widgets/slider.h29
-rw-r--r--src/gui/widgets/spacer.h5
-rw-r--r--src/gui/widgets/tab.cpp169
-rw-r--r--src/gui/widgets/tab.h32
-rw-r--r--src/gui/widgets/tabbedarea.cpp59
-rw-r--r--src/gui/widgets/tabbedarea.h16
-rw-r--r--src/gui/widgets/table.cpp73
-rw-r--r--src/gui/widgets/table.h53
-rw-r--r--src/gui/widgets/tablemodel.h5
-rw-r--r--src/gui/widgets/textbox.cpp48
-rw-r--r--src/gui/widgets/textbox.h17
-rw-r--r--src/gui/widgets/textfield.cpp98
-rw-r--r--src/gui/widgets/textfield.h46
-rw-r--r--src/gui/widgets/textpreview.cpp42
-rw-r--r--src/gui/widgets/textpreview.h55
-rw-r--r--src/gui/widgets/vertcontainer.h5
-rw-r--r--src/gui/widgets/whispertab.cpp2
-rw-r--r--src/gui/widgets/whispertab.h5
-rw-r--r--src/gui/widgets/window.cpp234
-rw-r--r--src/gui/widgets/window.h53
-rw-r--r--src/gui/widgets/windowcontainer.cpp9
-rw-r--r--src/gui/widgets/windowcontainer.h11
-rw-r--r--src/gui/windowmenu.cpp10
-rw-r--r--src/gui/windowmenu.h5
-rw-r--r--src/gui/worldselectdialog.h5
176 files changed, 3075 insertions, 4107 deletions
diff --git a/src/gui/specialswindow.cpp b/src/gui/abilitieswindow.cpp
index 340a1e41..700fa7ff 100644
--- a/src/gui/specialswindow.cpp
+++ b/src/gui/abilitieswindow.cpp
@@ -18,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "gui/specialswindow.h"
+#include "gui/abilitieswindow.h"
#include "log.h"
@@ -32,9 +32,9 @@
#include "gui/widgets/windowcontainer.h"
#include "net/net.h"
-#include "net/specialhandler.h"
+#include "net/abilityhandler.h"
-#include "resources/specialdb.h"
+#include "resources/abilitydb.h"
#include "resources/theme.h"
#include "utils/dtor.h"
@@ -44,19 +44,19 @@
#include <string>
-#define SPECIALS_WIDTH 200
-#define SPECIALS_HEIGHT 32
+#define ABILITIES_WIDTH 200
+#define ABILITIES_HEIGHT 32
-class SpecialEntry : public Container
+class AbilityEntry : public Container
{
public:
- SpecialEntry(SpecialInfo *info);
+ AbilityEntry(AbilityInfo *info);
void update(int current, int needed);
protected:
- friend class SpecialsWindow;
- SpecialInfo *mInfo;
+ friend class AbilitiesWindow;
+ AbilityInfo *mInfo;
private:
Icon *mIcon = nullptr; // icon to display
@@ -65,46 +65,46 @@ class SpecialEntry : public Container
ProgressBar *mRechargeBar = nullptr; // recharge bar (only shown when applicable)
};
-SpecialsWindow::SpecialsWindow():
- Window(_("Specials"))
+AbilitiesWindow::AbilitiesWindow():
+ Window(_("Abilities"))
{
- setWindowName("Specials");
+ setWindowName("Abilities");
setCloseButton(true);
setResizable(true);
setSaveVisible(true);
- setDefaultSize(windowContainer->getWidth() - 280, 40, SPECIALS_WIDTH + 20, 225);
+ setDefaultSize(windowContainer->getWidth() - 280, 40, ABILITIES_WIDTH + 20, 225);
setupWindow->registerWindowForReset(this);
center();
loadWindowState();
}
-SpecialsWindow::~SpecialsWindow()
+AbilitiesWindow::~AbilitiesWindow()
{
// Clear gui
}
-void SpecialsWindow::action(const gcn::ActionEvent &event)
+void AbilitiesWindow::action(const gcn::ActionEvent &event)
{
if (event.getId() == "use")
{
- auto *disp = dynamic_cast<SpecialEntry*>(event.getSource()->getParent());
+ auto *disp = dynamic_cast<AbilityEntry*>(event.getSource()->getParent());
if (disp)
{
- if (disp->mInfo->targetMode == SpecialInfo::TARGET_BEING)
+ if (disp->mInfo->targetMode == AbilityInfo::TARGET_BEING)
{
Being *target = local_player->getTarget();
if (target)
- Net::getSpecialHandler()->use(disp->mInfo->id, 1, target->getId());
+ Net::getAbilityHandler()->useOn(disp->mInfo->id, target->getId());
else
- Net::getSpecialHandler()->use(disp->mInfo->id);
+ Net::getAbilityHandler()->use(disp->mInfo->id);
}
else
{
// TODO: Allow the player to aim at a position on the map and
- // Use special on the map position.
+ // Use abilities on the map position.
}
}
}
@@ -114,73 +114,73 @@ void SpecialsWindow::action(const gcn::ActionEvent &event)
}
}
-void SpecialsWindow::draw(gcn::Graphics *graphics)
+void AbilitiesWindow::draw(gcn::Graphics *graphics)
{
// update the progress bars
- std::map<int, Special> specialData = PlayerInfo::getSpecialStatus();
+ const std::map<int, Ability> &abilityData = PlayerInfo::getAbilityStatus();
bool foundNew = false;
- unsigned int found = 0; // number of entries in specialData which match mEntries
+ unsigned int found = 0; // number of entries in abilityData which match mEntries
- for (auto &special : specialData)
+ for (auto &[id, ability] : abilityData)
{
- auto e = mEntries.find(special.first);
+ auto e = mEntries.find(id);
if (e == mEntries.end())
{
- // found a new special - abort update and rebuild from scratch
+ // found a new ability - abort update and rebuild from scratch
foundNew = true;
break;
}
- // update progress bar of special
- e->second->update(special.second.currentMana, special.second.neededMana);
+ // update progress bar of ability
+ e->second->update(ability.currentMana, ability.neededMana);
found++;
}
- // a rebuild is needed when a) the number of specials changed or b) an existing entry isn't found anymore
+ // a rebuild is needed when a) the number of abilities changed or b) an existing entry isn't found anymore
if (foundNew || found != mEntries.size())
- rebuild(specialData);
+ rebuild(abilityData);
Window::draw(graphics);
}
-void SpecialsWindow::rebuild(const std::map<int, Special> &specialData)
+void AbilitiesWindow::rebuild(const std::map<int, Ability> &abilityData)
{
delete_all(mEntries);
mEntries.clear();
int vPos = 0; //vertical position of next placed element
- for (auto special : specialData)
+ for (auto &[id, ability] : abilityData)
{
- logger->log("Updating special GUI for %d", special.first);
+ logger->log("Updating ability GUI for %d", id);
- SpecialInfo *info = SpecialDB::get(special.first);
+ AbilityInfo *info = AbilityDB::get(id);
if (info)
{
- info->rechargeCurrent = special.second.currentMana;
- info->rechargeNeeded = special.second.neededMana;
- auto* entry = new SpecialEntry(info);
+ info->rechargeCurrent = ability.currentMana;
+ info->rechargeNeeded = ability.neededMana;
+ auto *entry = new AbilityEntry(info);
entry->setPosition(0, vPos);
vPos += entry->getHeight() + 3;
add(entry);
- mEntries[special.first] = entry;
+ mEntries[id] = entry;
}
else
{
- logger->log("Warning: No info available of special %d", special.first);
+ logger->log("Warning: No info available of ability %d", id);
}
}
}
-SpecialEntry::SpecialEntry(SpecialInfo *info) :
+AbilityEntry::AbilityEntry(AbilityInfo *info) :
mInfo(info)
{
- setSize(SPECIALS_WIDTH, SPECIALS_HEIGHT);
+ setSize(ABILITIES_WIDTH, ABILITIES_HEIGHT);
if (!info->icon.empty())
mIcon = new Icon(info->icon);
else
- mIcon = new Icon(Theme::resolveThemePath("unknown-item.png"));
+ mIcon = new Icon(Theme::getImageFromTheme("unknown-item.png"));
mIcon->setPosition(1, 0);
add(mIcon);
@@ -189,7 +189,7 @@ SpecialEntry::SpecialEntry(SpecialInfo *info) :
mNameLabel->setPosition(35, 0);
add(mNameLabel);
- mUse = new Button("Use", "use", specialsWindow);
+ mUse = new Button("Use", "use", abilitiesWindow);
mUse->setPosition(getWidth() - mUse->getWidth(), 5);
add(mUse);
@@ -203,7 +203,7 @@ SpecialEntry::SpecialEntry(SpecialInfo *info) :
}
}
-void SpecialEntry::update(int current, int needed)
+void AbilityEntry::update(int current, int needed)
{
if (mRechargeBar)
{
diff --git a/src/gui/specialswindow.h b/src/gui/abilitieswindow.h
index 4ed4db3e..ddc5a9e4 100644
--- a/src/gui/specialswindow.h
+++ b/src/gui/abilitieswindow.h
@@ -18,8 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SPECIALSWINDOW_H
-#define SPECIALSWINDOW_H
+#pragma once
#include "playerinfo.h"
@@ -29,14 +28,14 @@
#include <map>
-class SpecialEntry;
+class AbilityEntry;
-class SpecialsWindow : public Window, public gcn::ActionListener
+class AbilitiesWindow : public Window, public gcn::ActionListener
{
public:
- SpecialsWindow();
+ AbilitiesWindow();
- ~SpecialsWindow() override;
+ ~AbilitiesWindow() override;
/**
* Called when receiving actions from widget.
@@ -45,16 +44,14 @@ class SpecialsWindow : public Window, public gcn::ActionListener
void draw(gcn::Graphics *graphics) override;
- bool hasSpecials() const
+ bool hasAbilities() const
{ return !mEntries.empty(); }
private:
- // (re)constructs the list of specials
- void rebuild(const std::map<int, Special> &specialData);
+ // (re)constructs the list of abilities
+ void rebuild(const std::map<int, Ability> &abilityData);
- std::map<int, SpecialEntry *> mEntries;
+ std::map<int, AbilityEntry *> mEntries;
};
-extern SpecialsWindow *specialsWindow;
-
-#endif // SPECIALSWINDOW_H
+extern AbilitiesWindow *abilitiesWindow;
diff --git a/src/gui/beingpopup.h b/src/gui/beingpopup.h
index 45169464..377b1b4e 100644
--- a/src/gui/beingpopup.h
+++ b/src/gui/beingpopup.h
@@ -18,8 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef BEINGPOPUP_H
-#define BEINGPOPUP_H
+#pragma once
#include "gui/widgets/popup.h"
@@ -47,5 +46,3 @@ class BeingPopup : public Popup
Label *mBeingName;
Label *mBeingParty;
};
-
-#endif // BEINGPOPUP_H
diff --git a/src/gui/buydialog.h b/src/gui/buydialog.h
index b1126225..4c67ef0d 100644
--- a/src/gui/buydialog.h
+++ b/src/gui/buydialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef BUY_H
-#define BUY_H
+#pragma once
#include "guichanfwd.h"
@@ -124,5 +123,3 @@ class BuyDialog : public Window, public gcn::ActionListener,
int mAmountItems;
int mMaxItems;
};
-
-#endif
diff --git a/src/gui/buyselldialog.h b/src/gui/buyselldialog.h
index 2e324d42..be382ffa 100644
--- a/src/gui/buyselldialog.h
+++ b/src/gui/buyselldialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef BUYSELL_H
-#define BUYSELL_H
+#pragma once
#include "gui/widgets/window.h"
@@ -63,5 +62,3 @@ class BuySellDialog : public Window, public gcn::ActionListener
int mNpcId;
gcn::Button *mBuyButton;
};
-
-#endif
diff --git a/src/gui/changeemaildialog.h b/src/gui/changeemaildialog.h
index 37d3ce01..cdf5664c 100644
--- a/src/gui/changeemaildialog.h
+++ b/src/gui/changeemaildialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GUI_CHANGEEMAIL_H
-#define GUI_CHANGEEMAIL_H
+#pragma once
#include "gui/widgets/window.h"
@@ -64,5 +63,3 @@ class ChangeEmailDialog : public Window, public gcn::ActionListener
LoginData *mLoginData;
};
-
-#endif // GUI_CHANGEEMAIL_H
diff --git a/src/gui/changepassworddialog.h b/src/gui/changepassworddialog.h
index 22d449d1..541e0444 100644
--- a/src/gui/changepassworddialog.h
+++ b/src/gui/changepassworddialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef CHANGEPASSWORDDIALOG_H
-#define CHANGEPASSWORDDIALOG_H
+#pragma once
#include "gui/widgets/window.h"
@@ -59,5 +58,3 @@ class ChangePasswordDialog : public Window, public gcn::ActionListener
LoginData *mLoginData;
};
-
-#endif
diff --git a/src/gui/charcreatedialog.cpp b/src/gui/charcreatedialog.cpp
index fa1144b6..cff7d822 100644
--- a/src/gui/charcreatedialog.cpp
+++ b/src/gui/charcreatedialog.cpp
@@ -50,7 +50,7 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot):
mSlot(slot)
{
mPlayer = new Being(0, ActorSprite::PLAYER, 0, nullptr);
- mPlayer->setGender(Gender::MALE);
+ mPlayer->setGender(Gender::Male);
const std::vector<int> &items = CharDB::getDefaultItems();
for (size_t i = 0; i < items.size(); ++i)
@@ -70,18 +70,6 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot):
mNameField = new TextField(std::string());
mNameLabel = new Label(_("Name:"));
- mNextHairColorButton = new Button("", "nextcolor", this);
- mPrevHairColorButton = new Button("", "prevcolor", this);
- mPrevHairColorButton->setButtonIcon("tab_arrows_left.png");
- mNextHairColorButton->setButtonIcon("tab_arrows_right.png");
-
- mHairColorLabel = new Label(_("Hair color:"));
- mNextHairStyleButton = new Button("", "nextstyle", this);
- mPrevHairStyleButton = new Button("", "prevstyle", this);
- mPrevHairStyleButton->setButtonIcon("tab_arrows_left.png");
- mNextHairStyleButton->setButtonIcon("tab_arrows_right.png");
-
- mHairStyleLabel = new Label(_("Hair style:"));
mCreateButton = new Button(_("Create"), "create", this);
mCancelButton = new Button(_("Cancel"), "cancel", this);
mMale = new RadioButton(_("Male"), "gender");
@@ -112,12 +100,6 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot):
mNameLabel->setPosition(5, 5);
mNameField->setDimension(
gcn::Rectangle(45, 5, w - 45 - 7, mNameField->getHeight()));
- mPrevHairColorButton->setPosition(90, 35);
- mNextHairColorButton->setPosition(165, 35);
- mHairColorLabel->setPosition(5, 40);
- mPrevHairStyleButton->setPosition(90, 64);
- mNextHairStyleButton->setPosition(165, 64);
- mHairStyleLabel->setPosition(5, 70);
mAttributesLeft->setPosition(15, 280);
updateSliders();
mCancelButton->setPosition(
@@ -136,16 +118,36 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot):
if (mHairColorsIds.size() > 1)
{
- add(mNextHairColorButton);
- add(mPrevHairColorButton);
- add(mHairColorLabel);
+ auto hairColorLabel = new Label(_("Hair color:"));
+ auto nextHairColorButton = new Button("", "nextcolor", this);
+ auto prevHairColorButton = new Button("", "prevcolor", this);
+ prevHairColorButton->setButtonIcon("tab_arrows_left.png");
+ nextHairColorButton->setButtonIcon("tab_arrows_right.png");
+
+ hairColorLabel->setPosition(5, 40);
+ prevHairColorButton->setPosition(90, 35);
+ nextHairColorButton->setPosition(165, 35);
+
+ add(nextHairColorButton);
+ add(prevHairColorButton);
+ add(hairColorLabel);
}
if (mHairStylesIds.size() > 1)
{
- add(mNextHairStyleButton);
- add(mPrevHairStyleButton);
- add(mHairStyleLabel);
+ auto hairStyleLabel = new Label(_("Hair style:"));
+ auto nextHairStyleButton = new Button("", "nextstyle", this);
+ auto prevHairStyleButton = new Button("", "prevstyle", this);
+ prevHairStyleButton->setButtonIcon("tab_arrows_left.png");
+ nextHairStyleButton->setButtonIcon("tab_arrows_right.png");
+
+ hairStyleLabel->setPosition(5, 70);
+ prevHairStyleButton->setPosition(90, 64);
+ nextHairStyleButton->setPosition(165, 64);
+
+ add(nextHairStyleButton);
+ add(prevHairStyleButton);
+ add(hairStyleLabel);
}
add(mAttributesLeft);
@@ -165,14 +167,15 @@ CharCreateDialog::~CharCreateDialog()
delete mPlayer;
// Make sure the char server handler knows that we're gone
- Net::getCharHandler()->setCharCreateDialog(nullptr);
+ if (auto charHandler = Net::getCharHandler())
+ charHandler->setCharCreateDialog(nullptr);
}
void CharCreateDialog::action(const gcn::ActionEvent &event)
{
if (event.getId() == "create")
{
- if (Net::getNetworkType() == ServerType::MANASERV
+ if (Net::getNetworkType() == ServerType::ManaServ
|| getName().length() >= 4)
{
// Attempt to create the character
@@ -180,7 +183,7 @@ void CharCreateDialog::action(const gcn::ActionEvent &event)
int characterSlot = mSlot;
// On Manaserv, the slots start at 1, so we offset them.
- if (Net::getNetworkType() == ServerType::MANASERV)
+ if (Net::getNetworkType() == ServerType::ManaServ)
++characterSlot;
// Should avoid the most common crash case
@@ -231,9 +234,9 @@ void CharCreateDialog::action(const gcn::ActionEvent &event)
else if (event.getId() == "gender")
{
if (mMale->isSelected())
- mPlayer->setGender(Gender::MALE);
+ mPlayer->setGender(Gender::Male);
else
- mPlayer->setGender(Gender::FEMALE);
+ mPlayer->setGender(Gender::Female);
}
}
@@ -341,7 +344,7 @@ void CharCreateDialog::setAttributes(const std::vector<std::string> &labels,
add(attributeLabel);
auto *attributeSlider = new Slider(min, max);
- attributeSlider->setDimension(gcn::Rectangle(75, y, 100, 10));
+ attributeSlider->setDimension(gcn::Rectangle(75, y, 100, attributeSlider->getHeight()));
attributeSlider->setActionEventId("statslider");
attributeSlider->addActionListener(this);
add(attributeSlider);
@@ -373,7 +376,7 @@ void CharCreateDialog::setAttributes(const std::vector<std::string> &labels,
void CharCreateDialog::setDefaultGender(Gender gender)
{
- if (gender == Gender::FEMALE)
+ if (gender == Gender::Female)
{
mFemale->setSelected(true);
mMale->setSelected(false);
diff --git a/src/gui/charcreatedialog.h b/src/gui/charcreatedialog.h
index 46db6229..f1759650 100644
--- a/src/gui/charcreatedialog.h
+++ b/src/gui/charcreatedialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef CHAR_CREATE_DIALOG_H
-#define CHAR_CREATE_DIALOG_H
+#pragma once
#include "being.h"
#include "guichanfwd.h"
@@ -82,12 +81,6 @@ class CharCreateDialog : public Window, public gcn::ActionListener
gcn::TextField *mNameField;
gcn::Label *mNameLabel;
- Button *mNextHairColorButton;
- Button *mPrevHairColorButton;
- gcn::Label *mHairColorLabel;
- Button *mNextHairStyleButton;
- Button *mPrevHairStyleButton;
- gcn::Label *mHairStyleLabel;
gcn::RadioButton *mMale;
gcn::RadioButton *mFemale;
@@ -114,5 +107,3 @@ class CharCreateDialog : public Window, public gcn::ActionListener
int mSlot;
};
-
-#endif // CHAR_CREATE_DIALOG_H
diff --git a/src/gui/charselectdialog.cpp b/src/gui/charselectdialog.cpp
index 7792813c..2485be69 100644
--- a/src/gui/charselectdialog.cpp
+++ b/src/gui/charselectdialog.cpp
@@ -150,7 +150,7 @@ CharSelectDialog::CharSelectDialog(LoginData *loginData):
for (int i = 0; i < (int)mLoginData->characterSlots; i++)
{
mCharacterEntries.push_back(new CharacterDisplay(this));
- place(i % SLOTS_PER_ROW, (int)i / SLOTS_PER_ROW, mCharacterEntries[i]);
+ place(i % SLOTS_PER_ROW, i / SLOTS_PER_ROW, mCharacterEntries[i]);
}
reflowLayout();
@@ -266,7 +266,7 @@ void CharSelectDialog::setCharacters(const Net::Characters &characters)
{
// Slots Number start at 1 for Manaserv, so we offset them by one.
int characterSlot = character->slot;
- if (Net::getNetworkType() == ServerType::MANASERV && characterSlot > 0)
+ if (Net::getNetworkType() == ServerType::ManaServ && characterSlot > 0)
--characterSlot;
if (characterSlot >= (int)mCharacterEntries.size())
diff --git a/src/gui/charselectdialog.h b/src/gui/charselectdialog.h
index 2deb5a7d..e5e558c9 100644
--- a/src/gui/charselectdialog.h
+++ b/src/gui/charselectdialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef CHAR_SELECT_H
-#define CHAR_SELECT_H
+#pragma once
#include "gui/widgets/window.h"
@@ -100,5 +99,3 @@ class CharSelectDialog : public Window, public gcn::ActionListener,
Net::CharHandler *mCharHandler;
};
-
-#endif
diff --git a/src/gui/chatwindow.cpp b/src/gui/chatwindow.cpp
index 453baea2..d006097c 100644
--- a/src/gui/chatwindow.cpp
+++ b/src/gui/chatwindow.cpp
@@ -30,6 +30,7 @@
#include "gui/recorder.h"
#include "gui/setup.h"
+#include "gui/widgets/browserbox.h"
#include "gui/widgets/chattab.h"
#include "gui/widgets/itemlinkhandler.h"
#include "gui/widgets/layout.h"
@@ -76,18 +77,17 @@ class ChatAutoComplete : public AutoCompleteLister
{
void getAutoCompleteList(std::vector<std::string> &list) const override
{
- auto *tab = static_cast<ChatTab*>(chatWindow->mChatTabs
- ->getSelectedTab());
-
- return tab->getAutoCompleteList(list);
+ auto tab = static_cast<ChatTab *>(chatWindow->mChatTabs->getSelectedTab());
+ tab->getAutoCompleteList(list);
}
};
ChatWindow::ChatWindow():
- Window(_("Chat")),
- mHistory(new TextHistory()),
+ Window(SkinType::Popup, _("Chat")),
+ mItemLinkHandler(new ItemLinkHandler(this)),
+ mChatInput(new ChatInput),
mAutoComplete(new ChatAutoComplete),
- mTmpVisible(false)
+ mChatTabs(new TabbedArea)
{
listen(Event::ChatChannel);
listen(Event::NoticesChannel);
@@ -106,21 +106,20 @@ ChatWindow::ChatWindow():
setMinWidth(150);
setMinHeight(90);
- mItemLinkHandler = new ItemLinkHandler(this);
-
- mChatInput = new ChatInput;
mChatInput->setActionEventId("chatinput");
mChatInput->addActionListener(this);
- mChatTabs = new TabbedArea;
+ // Override the padding from the theme since we want the content very close
+ // to the border on this window.
+ setPadding(std::min<unsigned>(getPadding(), 6));
+ getLayout().setPadding(0);
- getLayout().setPadding(3);
place(0, 0, mChatTabs, 3, 3);
- place(0, 3, mChatInput, 3);
+ place(0, 3, mChatInput, 3).setPadding(mChatInput->getFrameSize());
loadWindowState();
- mChatInput->setHistory(mHistory);
+ mChatInput->setHistory(&mHistory);
mChatInput->setAutoComplete(mAutoComplete);
mRecorder = new Recorder(this);
@@ -131,7 +130,6 @@ ChatWindow::~ChatWindow()
delete mRecorder;
removeAllWhispers();
delete mItemLinkHandler;
- delete mHistory;
delete mAutoComplete;
}
@@ -146,15 +144,10 @@ ChatTab *ChatWindow::getFocused() const
return static_cast<ChatTab*>(mChatTabs->getSelectedTab());
}
-void ChatWindow::clearTab(ChatTab *tab)
-{
- if (tab)
- tab->clearText();
-}
-
void ChatWindow::clearTab()
{
- clearTab(getFocused());
+ if (auto tab = getFocused())
+ tab->clearText();
}
void ChatWindow::prevTab()
@@ -247,6 +240,7 @@ void ChatWindow::addTab(ChatTab *tab)
// Make sure we don't end up with duplicates in the gui
// TODO
+ tab->mTextOutput->setPalette(getSkin().palette);
mChatTabs->addTab(tab, tab->mScrollArea);
// Update UI
diff --git a/src/gui/chatwindow.h b/src/gui/chatwindow.h
index 59ab6d99..6cac6f8e 100644
--- a/src/gui/chatwindow.h
+++ b/src/gui/chatwindow.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef CHAT_H
-#define CHAT_H
+#pragma once
#include "eventlistener.h"
@@ -32,21 +31,14 @@
#include <guichan/widget.hpp>
#include <guichan/widgetlistener.hpp>
-#include <list>
#include <string>
#include <map>
-#include <vector>
-class BrowserBox;
class ChatTab;
-class Channel;
class ChatInput;
class Recorder;
-class ScrollArea;
class TabbedArea;
class ItemLinkHandler;
-class Tab;
-class WhisperTab;
#define DEFAULT_CHAT_WINDOW_SCROLL 7 // 1 means `1/8th of the window size'.
@@ -99,11 +91,6 @@ class ChatWindow : public Window,
ChatTab *getFocused() const;
/**
- * Clear the given tab.
- */
- void clearTab(ChatTab *tab);
-
- /**
* Clear the current tab.
*/
void clearTab();
@@ -202,11 +189,11 @@ class ChatWindow : public Window,
/** Input box for typing chat messages. */
ChatInput *mChatInput;
- TextHistory *mHistory;
+ TextHistory mHistory;
AutoCompleteLister *mAutoComplete;
private:
- bool mTmpVisible;
+ bool mTmpVisible = false;
/** Tabbed area for holding each channel. */
TabbedArea *mChatTabs;
@@ -216,5 +203,3 @@ class ChatWindow : public Window,
};
extern ChatWindow *chatWindow;
-
-#endif
diff --git a/src/gui/confirmdialog.h b/src/gui/confirmdialog.h
index 8eb3f46b..ba51558e 100644
--- a/src/gui/confirmdialog.h
+++ b/src/gui/confirmdialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef OPTION_DIALOG_H
-#define OPTION_DIALOG_H
+#pragma once
#include "gui/widgets/window.h"
@@ -47,5 +46,3 @@ class ConfirmDialog : public Window, public gcn::ActionListener
private:
TextBox *mTextBox;
};
-
-#endif
diff --git a/src/gui/connectiondialog.h b/src/gui/connectiondialog.h
index e76a0a3e..6e477435 100644
--- a/src/gui/connectiondialog.h
+++ b/src/gui/connectiondialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef CONNECTION_H
-#define CONNECTION_H
+#pragma once
#include "client.h"
@@ -58,5 +57,3 @@ class ConnectionDialog : public Window, gcn::ActionListener
gcn::Label *mLabel;
State mCancelState;
};
-
-#endif
diff --git a/src/gui/customserverdialog.cpp b/src/gui/customserverdialog.cpp
index c7c03b1a..9a589671 100644
--- a/src/gui/customserverdialog.cpp
+++ b/src/gui/customserverdialog.cpp
@@ -37,11 +37,10 @@ std::string TypeListModel::getElementAt(int elementIndex)
if (elementIndex == 0)
return "TmwAthena";
#ifdef MANASERV_SUPPORT
- else if (elementIndex == 1)
+ if (elementIndex == 1)
return "ManaServ";
#endif
- else
- return "Unknown";
+ return "Unknown";
}
CustomServerDialog::CustomServerDialog(ServerDialog *parent, int index):
@@ -62,8 +61,8 @@ CustomServerDialog::CustomServerDialog(ServerDialog *parent, int index):
mPortField = new TextField(std::string());
#ifdef MANASERV_SUPPORT
- mTypeListModel = new TypeListModel();
- mTypeField = new DropDown(mTypeListModel);
+ mTypeListModel = std::make_unique<TypeListModel>();
+ mTypeField = new DropDown(mTypeListModel.get());
mTypeField->setSelected(0); // TmwAthena by default for now.
#endif
@@ -77,46 +76,25 @@ CustomServerDialog::CustomServerDialog(ServerDialog *parent, int index):
mPortField->addActionListener(this);
place(0, 0, nameLabel);
- place(1, 0, mNameField, 4).setPadding(3);
+ place(1, 0, mNameField, 4).setPadding(2);
place(0, 1, serverAdressLabel);
- place(1, 1, mServerAddressField, 4).setPadding(3);
+ place(1, 1, mServerAddressField, 4).setPadding(2);
place(0, 2, portLabel);
- place(1, 2, mPortField, 4).setPadding(3);
+ place(1, 2, mPortField, 4).setPadding(2);
#ifdef MANASERV_SUPPORT
place(0, 3, typeLabel);
- place(1, 3, mTypeField).setPadding(3);
+ place(1, 3, mTypeField).setPadding(2);
#endif
place(0, 4, descriptionLabel);
- place(1, 4, mDescriptionField, 4).setPadding(3);
+ place(1, 4, mDescriptionField, 4).setPadding(2);
place(4, 5, mOkButton);
place(3, 5, mCancelButton);
- // Do this manually instead of calling reflowLayout so we can enforce a
- // minimum width.
- int width = 0, height = 0;
- getLayout().reflow(width, height);
- if (width < 300)
- {
- width = 300;
- getLayout().reflow(width, height);
- }
- if (height < 120)
- {
- height = 120;
- getLayout().reflow(width, height);
- }
-
- setContentSize(width, height);
-
- setMinWidth(getWidth());
- setMinHeight(getHeight());
- setDefaultSize(getWidth(), getHeight(), ImageRect::CENTER);
+ reflowLayout();
+ setLocationRelativeTo(getParentWindow());
- setResizable(false);
addKeyListener(this);
- loadWindowState();
-
// Add the entry's info when in modify mode.
if (index > -1)
{
@@ -126,28 +104,17 @@ CustomServerDialog::CustomServerDialog(ServerDialog *parent, int index):
mServerAddressField->setText(serverInfo.hostname);
mPortField->setText(toString(serverInfo.port));
#ifdef MANASERV_SUPPORT
- mTypeField->setSelected(serverInfo.type == ServerType::TMWATHENA ?
+ mTypeField->setSelected(serverInfo.type == ServerType::TmwAthena ?
0 : 1);
#endif
}
- setLocationRelativeTo(getParentWindow());
setVisible(true);
mNameField->requestFocus();
}
-CustomServerDialog::~CustomServerDialog()
-{
-#ifdef MANASERV_SUPPORT
- delete mTypeListModel;
-#endif
-}
-
-void CustomServerDialog::logic()
-{
- Window::logic();
-}
+CustomServerDialog::~CustomServerDialog() = default;
void CustomServerDialog::action(const gcn::ActionEvent &event)
{
@@ -178,16 +145,16 @@ void CustomServerDialog::action(const gcn::ActionEvent &event)
switch (mTypeField->getSelected())
{
case 0:
- serverInfo.type = ServerType::TMWATHENA;
+ serverInfo.type = ServerType::TmwAthena;
break;
case 1:
- serverInfo.type = ServerType::MANASERV;
+ serverInfo.type = ServerType::ManaServ;
break;
default:
- serverInfo.type = ServerType::UNKNOWN;
+ serverInfo.type = ServerType::Unknown;
}
#else
- serverInfo.type = ServerType::TMWATHENA;
+ serverInfo.type = ServerType::TmwAthena;
#endif
if (mPortField->getText().empty())
serverInfo.port = ServerInfo::defaultPortForServerType(serverInfo.type);
diff --git a/src/gui/customserverdialog.h b/src/gui/customserverdialog.h
index 8b0af4c8..e523260c 100644
--- a/src/gui/customserverdialog.h
+++ b/src/gui/customserverdialog.h
@@ -18,15 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef CUSTOMSERVERDIALOG_H
-#define CUSTOMSERVERDIALOG_H
-
-class Button;
-class Label;
-class TextField;
-class DropDown;
-class ServerDialog;
-class TypeListModel;
+#pragma once
#include "gui/widgets/window.h"
@@ -34,6 +26,12 @@ class TypeListModel;
#include <guichan/keylistener.hpp>
#include <guichan/listmodel.hpp>
+#include <memory>
+
+class Button;
+class DropDown;
+class ServerDialog;
+class TextField;
/**
* Server Type List Model
@@ -65,7 +63,6 @@ class CustomServerDialog : public Window,
{
public:
CustomServerDialog(ServerDialog *parent, int index = -1);
-
~CustomServerDialog() override;
/**
@@ -75,22 +72,18 @@ class CustomServerDialog : public Window,
void keyPressed(gcn::KeyEvent &keyEvent) override;
- void logic() override;
-
private:
TextField *mServerAddressField;
TextField *mPortField;
- TextField *mNameField;
+ TextField *mNameField;
TextField *mDescriptionField;
Button *mOkButton;
Button *mCancelButton;
#ifdef MANASERV_SUPPORT
DropDown *mTypeField;
- TypeListModel *mTypeListModel;
+ std::unique_ptr<TypeListModel> mTypeListModel;
#endif
ServerDialog *mServerDialog;
// The index of the entry to modify, -1 when only adding a new entry.
int mIndex;
};
-
-#endif // CUSTOMSERVERDIALOG_H
diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp
index 3c514191..17020062 100644
--- a/src/gui/debugwindow.cpp
+++ b/src/gui/debugwindow.cpp
@@ -244,11 +244,15 @@ DebugWindow::DebugWindow()
place(0, 0, tabs, 2, 2);
loadWindowState();
- Tab *tabInfo = new Tab;
- tabInfo->setCaption(_("Info"));
- tabs->addTab(tabInfo, new DebugInfo);
-
- Tab *tabSwitches = new Tab;
- tabSwitches->setCaption(_("Switches"));
- tabs->addTab(tabSwitches, new DebugSwitches);
+ mInfoTab = std::make_unique<Tab>();
+ mInfoTab->setCaption(_("Info"));
+ mInfoWidget = std::make_unique<DebugInfo>();
+ tabs->addTab(mInfoTab.get(), mInfoWidget.get());
+
+ mSwitchesTab = std::make_unique<Tab>();
+ mSwitchesTab->setCaption(_("Switches"));
+ mSwitchesWidget = std::make_unique<DebugSwitches>();
+ tabs->addTab(mSwitchesTab.get(), mSwitchesWidget.get());
}
+
+DebugWindow::~DebugWindow() = default;
diff --git a/src/gui/debugwindow.h b/src/gui/debugwindow.h
index 3376ae18..807f0d0f 100644
--- a/src/gui/debugwindow.h
+++ b/src/gui/debugwindow.h
@@ -19,11 +19,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef DEBUGWINDOW_H
-#define DEBUGWINDOW_H
+#pragma once
#include "gui/widgets/window.h"
+#include <memory>
+
+class Tab;
+
/**
* The debug window.
*
@@ -33,8 +36,13 @@ class DebugWindow : public Window
{
public:
DebugWindow();
+ ~DebugWindow() override;
+
+ private:
+ std::unique_ptr<Tab> mInfoTab;
+ std::unique_ptr<Tab> mSwitchesTab;
+ std::unique_ptr<gcn::Widget> mInfoWidget;
+ std::unique_ptr<gcn::Widget> mSwitchesWidget;
};
extern DebugWindow *debugWindow;
-
-#endif
diff --git a/src/gui/emotepopup.cpp b/src/gui/emotepopup.cpp
index 589d5087..4df6b995 100644
--- a/src/gui/emotepopup.cpp
+++ b/src/gui/emotepopup.cpp
@@ -22,12 +22,10 @@
#include "gui/emotepopup.h"
-#include "configuration.h"
#include "emoteshortcut.h"
#include "graphics.h"
-#include "imagesprite.h"
-#include "log.h"
+#include "gui/gui.h"
#include "resources/emotedb.h"
#include "resources/image.h"
#include "resources/theme.h"
@@ -35,59 +33,61 @@
#include <guichan/mouseinput.hpp>
#include <guichan/selectionlistener.hpp>
-const int EmotePopup::gridWidth = 34; // emote icon width + 4
-const int EmotePopup::gridHeight = 36; // emote icon height + 4
-
static const int MAX_COLUMNS = 6;
EmotePopup::EmotePopup()
{
- mSelectionImage = Theme::getImageFromTheme("selection.png");
- if (!mSelectionImage)
- logger->error("Unable to load selection.png");
-
- mSelectionImage->setAlpha(config.guiAlpha);
-
addMouseListener(this);
recalculateSize();
setVisible(true);
}
-EmotePopup::~EmotePopup()
-{
- mSelectionImage->decRef();
-}
+EmotePopup::~EmotePopup() = default;
void EmotePopup::draw(gcn::Graphics *graphics)
{
+ auto *g = static_cast<Graphics*>(graphics);
+
Popup::draw(graphics);
const int emoteCount = EmoteDB::getEmoteCount();
+ auto &slotSkin = gui->getTheme()->getSkin(SkinType::EmoteSlot);
+ WidgetState slotState;
+ slotState.width = slotSkin.width;
+ slotState.height = slotSkin.height;
+
for (int i = 0; i < emoteCount ; i++)
{
int row = i / mColumnCount;
int column = i % mColumnCount;
- int emoteX = getPadding() + column * gridWidth;
- int emoteY = getPadding() + row * gridHeight;
+ slotState.x = getPadding() + column * slotSkin.width;
+ slotState.y = getPadding() + row * slotSkin.height;
// Center the last row when there are less emotes than columns
if (row == mRowCount - 1)
{
const int emotesLeft = emoteCount % mColumnCount;
- emoteX += (mColumnCount - emotesLeft) * gridWidth / 2;
+ slotState.x += (mColumnCount - emotesLeft) * slotSkin.width / 2;
}
+ slotState.flags = 0;
+
// Draw selection image below hovered item
if (i == mHoveredEmoteIndex)
- {
- static_cast<Graphics*>(graphics)->drawImage(
- mSelectionImage, emoteX, emoteY + 4);
- }
+ slotState.flags |= STATE_HOVERED;
+
+ slotSkin.draw(g, slotState);
// Draw emote icon
- EmoteDB::getByIndex(i).sprite->draw(static_cast<Graphics*>(graphics), emoteX, emoteY);
+ if (auto image = EmoteDB::getByIndex(i).image)
+ {
+ image->setAlpha(1.0f);
+ g->drawImage(image,
+ slotState.x + (slotSkin.width - image->getWidth()) / 2,
+ slotState.y + (slotSkin.height - image->getHeight()) / 2);
+ }
}
}
@@ -140,22 +140,24 @@ int EmotePopup::getIndexAt(int x, int y) const
return -1;
// Take into account the border
- x -= 2;
- y -= 4;
+ x -= getPadding();
+ y -= getPadding();
+
+ auto &slotSkin = gui->getTheme()->getSkin(SkinType::EmoteSlot);
- const int row = y / gridHeight;
+ const int row = y / slotSkin.height;
// Take into account that the last row is centered
if (row == mRowCount - 1)
{
const int emotesLeft = EmoteDB::getEmoteCount() % mColumnCount;
const int emotesMissing = mColumnCount - emotesLeft;
- x -= emotesMissing * gridWidth / 2;
+ x -= emotesMissing * slotSkin.width / 2;
if (x < 0)
return -1;
}
- const int column = std::min(x / gridWidth, mColumnCount - 1);
+ const int column = std::min(x / slotSkin.width, mColumnCount - 1);
const int index = column + (row * mColumnCount);
if (index >= 0 && index < EmoteDB::getEmoteCount())
@@ -179,7 +181,8 @@ void EmotePopup::recalculateSize()
mColumnCount = 0;
}
- setContentSize(mColumnCount * gridWidth, mRowCount * gridHeight);
+ auto &slotSkin = gui->getTheme()->getSkin(SkinType::EmoteSlot);
+ setContentSize(mColumnCount * slotSkin.width, mRowCount * slotSkin.height);
}
void EmotePopup::distributeValueChangedEvent()
@@ -187,7 +190,5 @@ void EmotePopup::distributeValueChangedEvent()
const gcn::SelectionEvent event(this);
for (auto &listener : mListeners)
- {
listener->valueChanged(event);
- }
}
diff --git a/src/gui/emotepopup.h b/src/gui/emotepopup.h
index ef3fffed..664eef27 100644
--- a/src/gui/emotepopup.h
+++ b/src/gui/emotepopup.h
@@ -20,8 +20,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef EMOTEPOPUP_H
-#define EMOTEPOPUP_H
+#pragma once
#include "gui/widgets/popup.h"
@@ -104,7 +103,6 @@ class EmotePopup : public Popup
*/
void distributeValueChangedEvent();
- Image *mSelectionImage;
int mSelectedEmoteId = -1;
int mHoveredEmoteIndex = -1;
@@ -112,9 +110,4 @@ class EmotePopup : public Popup
int mColumnCount = 1;
std::list<gcn::SelectionListener *> mListeners;
-
- static const int gridWidth;
- static const int gridHeight;
};
-
-#endif
diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp
index e7eeb048..b9d3b0fd 100644
--- a/src/gui/equipmentwindow.cpp
+++ b/src/gui/equipmentwindow.cpp
@@ -47,9 +47,6 @@
#include <guichan/font.hpp>
-static const int BOX_WIDTH = 36;
-static const int BOX_HEIGHT = 36;
-
EquipmentWindow::EquipmentWindow(Equipment *equipment):
Window(_("Equipment")),
mEquipment(equipment)
@@ -65,42 +62,18 @@ EquipmentWindow::EquipmentWindow(Equipment *equipment):
setWindowName("Equipment");
setCloseButton(true);
setSaveVisible(true);
- setDefaultSize(180, 300, ImageRect::CENTER);
+ setContentSize(175, 290);
+ setDefaultSize(getWidth(), getHeight(), ImageRect::CENTER);
loadWindowState();
mUnequip = new Button(_("Unequip"), "unequip", this);
const gcn::Rectangle &area = getChildrenArea();
- mUnequip->setPosition(area.width - mUnequip->getWidth() - 5,
- area.height - mUnequip->getHeight() - 5);
+ mUnequip->setPosition(area.width - mUnequip->getWidth() - getPadding(),
+ area.height - mUnequip->getHeight() - getPadding());
mUnequip->setEnabled(false);
add(playerBox);
add(mUnequip);
-
- loadEquipBoxes();
-}
-
-void EquipmentWindow::loadEquipBoxes()
-{
- mBoxes.resize(mEquipment->getSlotNumber());
-
- for (size_t i = 0; i < mBoxes.size(); ++i)
- {
- auto &box = mBoxes[i];
-
- Position boxPosition = Net::getInventoryHandler()->getBoxPosition(i);
- box.posX = boxPosition.x + getPadding();
- box.posY = boxPosition.y + getTitleBarHeight();
-
- const std::string &backgroundFile =
- Net::getInventoryHandler()->getBoxBackground(i);
-
- if (!backgroundFile.empty())
- {
- box.backgroundImage =
- Theme::instance()->getImageFromTheme(backgroundFile);
- }
- }
}
EquipmentWindow::~EquipmentWindow()
@@ -111,60 +84,52 @@ EquipmentWindow::~EquipmentWindow()
void EquipmentWindow::draw(gcn::Graphics *graphics)
{
Window::draw(graphics);
- Window::drawChildren(graphics);
- // Draw equipment boxes
auto *g = static_cast<Graphics*>(graphics);
- for (size_t i = 0; i < mBoxes.size(); i++)
- {
- const auto &box = mBoxes[i];
+ auto theme = gui->getTheme();
+ auto &boxSkin = theme->getSkin(SkinType::EquipmentBox);
- // When there is a background image, draw it centered in the box:
- if (box.backgroundImage)
- {
- int posX = box.posX
- + (BOX_WIDTH - box.backgroundImage->getWidth()) / 2;
- int posY = box.posY
- + (BOX_HEIGHT - box.backgroundImage->getHeight()) / 2;
- g->drawImage(box.backgroundImage, posX, posY);
- }
-
- const gcn::Rectangle tRect(box.posX, box.posY,
- BOX_WIDTH, BOX_HEIGHT);
-
- if (static_cast<int>(i) == mSelected)
- {
- const gcn::Color color = Theme::getThemeColor(Theme::HIGHLIGHT);
+ // Draw equipment boxes
+ const int boxCount = mEquipment->getSlotNumber();
+ for (int i = 0; i < boxCount; ++i)
+ {
+ Position boxPos = Net::getInventoryHandler()->getBoxPosition(i);
+ boxPos.x += getPadding();
+ boxPos.y += getTitleBarHeight();
- // Set color to the highlight color
- g->setColor(gcn::Color(color.r, color.g, color.b, getGuiAlpha()));
- g->fillRectangle(tRect);
- }
+ WidgetState boxState(gcn::Rectangle(boxPos.x, boxPos.y, boxSkin.width, boxSkin.height));
+ if (i == mSelected)
+ boxState.flags |= STATE_SELECTED;
- // Draw black box border
- g->setColor(gcn::Color(0, 0, 0));
- g->drawRectangle(tRect);
+ boxSkin.draw(g, boxState);
if (Item *item = mEquipment->getEquipment(i))
{
- // Draw Item.
- Image *image = item->getImage();
- // Ensure the image is drawn with maximum opacity
- image->setAlpha(1.0f);
- g->drawImage(image,
- box.posX + 2,
- box.posY + 2);
+ if (Image *image = item->getImage())
+ {
+ image->setAlpha(1.0f);
+ g->drawImage(image,
+ boxPos.x + boxSkin.padding,
+ boxPos.y + boxSkin.padding);
+ }
if (i == TmwAthena::EQUIP_PROJECTILE_SLOT)
{
g->setColor(Theme::getThemeColor(Theme::TEXT));
graphics->drawText(toString(item->getQuantity()),
- box.posX + (BOX_WIDTH / 2),
- box.posY - getFont()->getHeight(),
+ boxPos.x + boxSkin.width / 2,
+ boxPos.y - getFont()->getHeight(),
gcn::Graphics::CENTER);
}
}
+ else
+ {
+ auto &icon = Net::getInventoryHandler()->getBoxIcon(i);
+ if (!icon.empty())
+ if (auto image = theme->getIcon(icon))
+ g->drawImage(image, boxPos.x + boxSkin.padding, boxPos.y + boxSkin.padding);
+ }
}
}
@@ -183,12 +148,18 @@ void EquipmentWindow::action(const gcn::ActionEvent &event)
*/
int EquipmentWindow::getBoxIndex(int x, int y) const
{
- for (size_t i = 0; i < mBoxes.size(); ++i)
- {
- const auto &box = mBoxes[i];
- const gcn::Rectangle tRect(box.posX, box.posY,
- BOX_WIDTH, BOX_HEIGHT);
+ auto &boxSkin = gui->getTheme()->getSkin(SkinType::EquipmentBox);
+ // Translate coordinates to content area
+ const auto childrenArea = const_cast<EquipmentWindow*>(this)->getChildrenArea();
+ x -= childrenArea.x;
+ y -= childrenArea.y;
+
+ const int boxCount = mEquipment->getSlotNumber();
+ for (int i = 0; i < boxCount; ++i)
+ {
+ const Position boxPos = Net::getInventoryHandler()->getBoxPosition(i);
+ const gcn::Rectangle tRect(boxPos.x, boxPos.y, boxSkin.width, boxSkin.height);
if (tRect.isPointInRect(x, y))
return i;
}
@@ -240,6 +211,8 @@ void EquipmentWindow::mousePressed(gcn::MouseEvent& mouseEvent)
void EquipmentWindow::mouseMoved(gcn::MouseEvent &event)
{
+ Window::mouseMoved(event);
+
const int x = event.getX();
const int y = event.getY();
@@ -264,6 +237,8 @@ void EquipmentWindow::mouseMoved(gcn::MouseEvent &event)
void EquipmentWindow::mouseExited(gcn::MouseEvent &event)
{
+ Window::mouseExited(event);
+
mItemPopup->setVisible(false);
}
diff --git a/src/gui/equipmentwindow.h b/src/gui/equipmentwindow.h
index 1b63c866..944ae99e 100644
--- a/src/gui/equipmentwindow.h
+++ b/src/gui/equipmentwindow.h
@@ -19,11 +19,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef EQUIPMENTWINDOW_H
-#define EQUIPMENTWINDOW_H
+#pragma once
#include "equipment.h"
-#include "resources/image.h"
#include "gui/widgets/window.h"
@@ -53,11 +51,8 @@ class EquipmentWindow : public Window, public gcn::ActionListener
void action(const gcn::ActionEvent &event) override;
void mousePressed(gcn::MouseEvent& mouseEvent) override;
-
- /**
- * Loads the correct amount of displayed equip boxes.
- */
- void loadEquipBoxes();
+ void mouseMoved(gcn::MouseEvent &event) override;
+ void mouseExited(gcn::MouseEvent &event) override;
/**
* Returns the current selected slot or -1 if none.
@@ -66,25 +61,10 @@ class EquipmentWindow : public Window, public gcn::ActionListener
{ return mSelected; }
protected:
- /**
- * Equipment box.
- */
- struct EquipBox
- {
- int posX = 0;
- int posY = 0;
- Image *backgroundImage = nullptr;
- };
-
- std::vector<EquipBox> mBoxes; /**< Equipment boxes. */
-
int mSelected = -1; /**< Index of selected item. */
Equipment *mEquipment;
private:
- void mouseExited(gcn::MouseEvent &event) override;
- void mouseMoved(gcn::MouseEvent &event) override;
-
int getBoxIndex(int x, int y) const;
Item *getItem(int x, int y) const;
std::string getSlotName(int x, int y) const;
@@ -96,5 +76,3 @@ class EquipmentWindow : public Window, public gcn::ActionListener
};
extern EquipmentWindow *equipmentWindow;
-
-#endif // EQUIPMENTWINDOW_H
diff --git a/src/gui/focushandler.h b/src/gui/focushandler.h
index eb59bcf3..d90898bd 100644
--- a/src/gui/focushandler.h
+++ b/src/gui/focushandler.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef FOCUSHANDLER_H
-#define FOCUSHANDLER_H
+#pragma once
#include <guichan/focushandler.hpp>
@@ -73,5 +72,3 @@ class FocusHandler : public gcn::FocusHandler
*/
std::list<gcn::Widget*> mModalStack;
};
-
-#endif
diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp
index a59242dc..0c3d78eb 100644
--- a/src/gui/gui.cpp
+++ b/src/gui/gui.cpp
@@ -37,10 +37,13 @@
#include "resources/resourcemanager.h"
#include "resources/theme.h"
+#include "utils/filesystem.h"
#include <guichan/exception.hpp>
#include <guichan/image.hpp>
+#include <algorithm>
+
#include <SDL_image.h>
// Guichan stuff
@@ -55,9 +58,19 @@ gcn::Font *monoFont = nullptr;
bool Gui::debugDraw;
-Gui::Gui(Graphics *graphics)
- : mCustomCursorScale(Client::getVideo().settings().scale())
+Gui::Gui(Graphics *graphics, const std::string &themePath)
+ : mAvailableThemes(Theme::getAvailableThemes())
+ , mCustomCursorScale(Client::getVideo().settings().scale())
{
+ // Try to find the requested theme, using the first one as fallback
+ auto themeIt = std::find_if(mAvailableThemes.begin(),
+ mAvailableThemes.end(),
+ [&themePath](const ThemeInfo &theme) {
+ return theme.getPath() == themePath;
+ });
+
+ setTheme(themeIt != mAvailableThemes.end() ? *themeIt : mAvailableThemes.front());
+
logger->log("Initializing GUI...");
// Set graphics
setGraphics(graphics);
@@ -66,7 +79,7 @@ Gui::Gui(Graphics *graphics)
guiInput = new SDLInput;
setInput(guiInput);
- // Set focus handler
+ // Replace focus handler
delete mFocusHandler;
mFocusHandler = new FocusHandler;
@@ -78,12 +91,10 @@ Gui::Gui(Graphics *graphics)
Window::setWindowContainer(guiTop);
setTop(guiTop);
- ResourceManager *resman = ResourceManager::getInstance();
-
// Set global font
const int fontSize = config.fontSize;
std::string fontFile = branding.getValue("font", "fonts/dejavusans.ttf");
- std::string path = resman->getPath(fontFile);
+ std::string path = ResourceManager::getPath(fontFile);
// Initialize the font scale before creating the fonts
TrueTypeFont::updateFontScale(graphics->getScale());
@@ -101,7 +112,7 @@ Gui::Gui(Graphics *graphics)
// Set bold font
fontFile = branding.getValue("boldFont", "fonts/dejavusans-bold.ttf");
- path = resman->getPath(fontFile);
+ path = ResourceManager::getPath(fontFile);
try
{
boldFont = new TrueTypeFont(path, fontSize);
@@ -114,7 +125,7 @@ Gui::Gui(Graphics *graphics)
// Set mono font
fontFile = branding.getValue("monoFont", "fonts/dejavusans-mono.ttf");
- path = resman->getPath(fontFile);
+ path = ResourceManager::getPath(fontFile);
try
{
monoFont = new TrueTypeFont(path, fontSize);
@@ -151,8 +162,6 @@ Gui::~Gui()
delete getTop();
delete guiInput;
-
- Theme::deleteInstance();
}
void Gui::logic()
@@ -228,6 +237,11 @@ void Gui::setCursorType(Cursor cursor)
updateCursor();
}
+void Gui::setTheme(const ThemeInfo &theme)
+{
+ mTheme = std::make_unique<Theme>(theme);
+}
+
void Gui::updateCursor()
{
if (mCustomCursor && !mCustomMouseCursors.empty())
@@ -258,7 +272,7 @@ void Gui::handleTextInput(const TextInput &textInput)
static SDL_Surface *loadSurface(const std::string &path)
{
- if (SDL_RWops *file = ResourceManager::getInstance()->open(path))
+ if (SDL_RWops *file = FS::openRWops(path))
return IMG_Load_RW(file, 1);
return nullptr;
}
@@ -270,7 +284,7 @@ void Gui::loadCustomCursors()
mCustomMouseCursors.clear();
- const std::string cursorPath = Theme::resolveThemePath("mouse.png");
+ const std::string cursorPath = mTheme->resolvePath("mouse.png");
SDL_Surface *mouseSurface = loadSurface(cursorPath);
if (!mouseSurface)
{
@@ -301,7 +315,7 @@ void Gui::loadCustomCursors()
0, targetCursorSize, targetCursorSize, 32,
rmask, gmask, bmask, amask);
- for (int i = 0; i <= static_cast<int>(Cursor::LAST); ++i)
+ for (int i = 0; i < static_cast<int>(Cursor::Count); ++i)
{
int x = i % columns * cursorSize;
int y = i / columns * cursorSize;
@@ -330,22 +344,22 @@ void Gui::loadSystemCursors()
constexpr struct {
Cursor cursor;
SDL_SystemCursor systemCursor;
- } cursors[static_cast<int>(Cursor::LAST) + 1] = {
- { Cursor::POINTER, SDL_SYSTEM_CURSOR_ARROW },
- { Cursor::RESIZE_ACROSS, SDL_SYSTEM_CURSOR_SIZEWE },
- { Cursor::RESIZE_DOWN, SDL_SYSTEM_CURSOR_SIZENS },
- { Cursor::RESIZE_DOWN_LEFT, SDL_SYSTEM_CURSOR_SIZENESW },
- { Cursor::RESIZE_DOWN_RIGHT, SDL_SYSTEM_CURSOR_SIZENWSE },
- { Cursor::FIGHT, SDL_SYSTEM_CURSOR_HAND },
- { Cursor::PICKUP, SDL_SYSTEM_CURSOR_HAND },
- { Cursor::TALK, SDL_SYSTEM_CURSOR_HAND },
- { Cursor::ACTION, SDL_SYSTEM_CURSOR_HAND },
- { Cursor::LEFT, SDL_SYSTEM_CURSOR_ARROW },
- { Cursor::UP, SDL_SYSTEM_CURSOR_ARROW },
- { Cursor::RIGHT, SDL_SYSTEM_CURSOR_ARROW },
- { Cursor::DOWN, SDL_SYSTEM_CURSOR_ARROW },
- { Cursor::DRAG, SDL_SYSTEM_CURSOR_SIZEALL },
- { Cursor::HAND, SDL_SYSTEM_CURSOR_HAND },
+ } cursors[static_cast<int>(Cursor::Count)] = {
+ { Cursor::Pointer, SDL_SYSTEM_CURSOR_ARROW },
+ { Cursor::ResizeAcross, SDL_SYSTEM_CURSOR_SIZEWE },
+ { Cursor::ResizeDown, SDL_SYSTEM_CURSOR_SIZENS },
+ { Cursor::ResizeDownLeft, SDL_SYSTEM_CURSOR_SIZENESW },
+ { Cursor::ResizeDownRight, SDL_SYSTEM_CURSOR_SIZENWSE },
+ { Cursor::Fight, SDL_SYSTEM_CURSOR_HAND },
+ { Cursor::PickUp, SDL_SYSTEM_CURSOR_HAND },
+ { Cursor::Talk, SDL_SYSTEM_CURSOR_HAND },
+ { Cursor::Action, SDL_SYSTEM_CURSOR_HAND },
+ { Cursor::Left, SDL_SYSTEM_CURSOR_ARROW },
+ { Cursor::Up, SDL_SYSTEM_CURSOR_ARROW },
+ { Cursor::Right, SDL_SYSTEM_CURSOR_ARROW },
+ { Cursor::Down, SDL_SYSTEM_CURSOR_ARROW },
+ { Cursor::Drag, SDL_SYSTEM_CURSOR_SIZEALL },
+ { Cursor::Hand, SDL_SYSTEM_CURSOR_HAND },
};
for (auto cursor : cursors)
diff --git a/src/gui/gui.h b/src/gui/gui.h
index fd1dcf94..2584b780 100644
--- a/src/gui/gui.h
+++ b/src/gui/gui.h
@@ -19,18 +19,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GUI_H
-#define GUI_H
+#pragma once
#include "eventlistener.h"
#include "guichanfwd.h"
+#include "resources/theme.h"
+
#include "utils/time.h"
#include <guichan/gui.hpp>
#include <SDL.h>
+#include <memory>
#include <vector>
class TextInput;
@@ -49,23 +51,24 @@ class SDLInput;
* Cursors are in graphic order from left to right.
* CURSOR_POINTER should be left untouched.
*/
-enum class Cursor {
- POINTER = 0,
- RESIZE_ACROSS,
- RESIZE_DOWN,
- RESIZE_DOWN_LEFT,
- RESIZE_DOWN_RIGHT,
- FIGHT,
- PICKUP,
- TALK,
- ACTION,
- LEFT,
- UP,
- RIGHT,
- DOWN,
- DRAG,
- HAND,
- LAST = HAND,
+enum class Cursor
+{
+ Pointer = 0,
+ ResizeAcross,
+ ResizeDown,
+ ResizeDownLeft,
+ ResizeDownRight,
+ Fight,
+ PickUp,
+ Talk,
+ Action,
+ Left,
+ Up,
+ Right,
+ Down,
+ Drag,
+ Hand,
+ Count,
};
/**
@@ -76,7 +79,7 @@ enum class Cursor {
class Gui final : public gcn::Gui, public EventListener
{
public:
- Gui(Graphics *screen);
+ Gui(Graphics *screen, const std::string &themePath);
~Gui() override;
@@ -121,6 +124,20 @@ class Gui final : public gcn::Gui, public EventListener
*/
void setCursorType(Cursor cursor);
+ const std::vector<ThemeInfo> &getAvailableThemes() const
+ { return mAvailableThemes; }
+
+ /**
+ * Sets the global GUI theme.
+ */
+ void setTheme(const ThemeInfo &theme);
+
+ /**
+ * The global GUI theme.
+ */
+ Theme *getTheme() const
+ { return mTheme.get(); }
+
static bool debugDraw;
protected:
@@ -133,6 +150,8 @@ class Gui final : public gcn::Gui, public EventListener
void loadCustomCursors();
void loadSystemCursors();
+ std::vector<ThemeInfo> mAvailableThemes;
+ std::unique_ptr<Theme> mTheme; /**< The global GUI theme */
gcn::Font *mGuiFont; /**< The global GUI font */
gcn::Font *mInfoParticleFont; /**< Font for Info Particles*/
bool mCustomCursor = false; /**< Show custom cursor */
@@ -140,7 +159,7 @@ class Gui final : public gcn::Gui, public EventListener
std::vector<SDL_Cursor *> mSystemMouseCursors;
std::vector<SDL_Cursor *> mCustomMouseCursors;
Timer mMouseActivityTimer;
- Cursor mCursorType = Cursor::POINTER;
+ Cursor mCursorType = Cursor::Pointer;
};
extern Gui *gui; /**< The GUI system */
@@ -155,5 +174,3 @@ extern gcn::Font *boldFont;
* Monospaced text font
*/
extern gcn::Font *monoFont;
-
-#endif // GUI_H
diff --git a/src/gui/helpwindow.cpp b/src/gui/helpwindow.cpp
index 7bb31188..e0e21610 100644
--- a/src/gui/helpwindow.cpp
+++ b/src/gui/helpwindow.cpp
@@ -29,9 +29,10 @@
#include "gui/widgets/layout.h"
#include "gui/widgets/scrollarea.h"
-#include "resources/resourcemanager.h"
#include "configuration.h"
+#include "log.h"
+#include "utils/filesystem.h"
#include "utils/gettext.h"
HelpWindow::HelpWindow():
@@ -47,7 +48,6 @@ HelpWindow::HelpWindow():
setDefaultSize(500, 400, ImageRect::CENTER);
mBrowserBox = new BrowserBox;
- mBrowserBox->setFrameSize(4);
mScrollArea = new ScrollArea(mBrowserBox);
auto *okButton = new Button(_("Close"), "close", this);
@@ -88,12 +88,20 @@ void HelpWindow::loadHelp(const std::string &helpFile)
void HelpWindow::loadFile(const std::string &file)
{
- ResourceManager *resman = ResourceManager::getInstance();
std::string helpPath = branding.getStringValue("helpPath");
if (helpPath.empty())
helpPath = paths.getStringValue("help");
- const auto lines = resman->loadTextFile(helpPath + file + ".txt");
- for (auto &line : lines)
- mBrowserBox->addRow(line);
+ const std::string fileName = helpPath + file + ".txt";
+
+ size_t contentsLength;
+ char *fileContents = (char *) FS::loadFile(fileName, contentsLength);
+ if (!fileContents)
+ {
+ logger->log("Couldn't load text file: %s", fileName.c_str());
+ return;
+ }
+
+ mBrowserBox->addRows(std::string_view(fileContents, contentsLength));
+ SDL_free(fileContents);
}
diff --git a/src/gui/helpwindow.h b/src/gui/helpwindow.h
index 30fa450e..2daf2480 100644
--- a/src/gui/helpwindow.h
+++ b/src/gui/helpwindow.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef HELP_H
-#define HELP_H
+#pragma once
#include "gui/widgets/linkhandler.h"
#include "gui/widgets/window.h"
@@ -62,5 +61,3 @@ class HelpWindow : public Window, public LinkHandler,
};
extern HelpWindow *helpWindow;
-
-#endif
diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp
index 048f83f5..ab2e9c86 100644
--- a/src/gui/inventorywindow.cpp
+++ b/src/gui/inventorywindow.cpp
@@ -30,7 +30,6 @@
#include "gui/itemamountwindow.h"
#include "gui/setup.h"
-#include "gui/sdlinput.h"
#include "gui/viewport.h"
#include "gui/widgets/button.h"
@@ -40,9 +39,6 @@
#include "gui/widgets/progressbar.h"
#include "gui/widgets/scrollarea.h"
-#include "net/inventoryhandler.h"
-#include "net/net.h"
-
#include "resources/iteminfo.h"
#include "resources/theme.h"
@@ -80,7 +76,7 @@ InventoryWindow::InventoryWindow(Inventory *inventory):
mItems = new ItemContainer(mInventory);
mItems->addSelectionListener(this);
- gcn::ScrollArea *invenScroll = new ScrollArea(mItems);
+ auto invenScroll = new ScrollArea(mItems);
invenScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
mSlotsLabel = new Label(_("Slots:"));
@@ -105,7 +101,6 @@ InventoryWindow::InventoryWindow(Inventory *inventory):
mEquipButton = new Button(_("Equip"), "equip", this);
mUseButton = new Button(_("Activate"), "activate", this);
mDropButton = new Button(_("Drop..."), "drop", this);
- mSplitButton = new Button(_("Split"), "split", this);
mOutfitButton = new Button(_("Outfits"), "outfit", this);
mWeightLabel = new Label(_("Weight:"));
@@ -121,7 +116,6 @@ InventoryWindow::InventoryWindow(Inventory *inventory):
place(0, 3, mUseButton);
place(1, 3, mEquipButton);
place(3, 3, mDropButton);
- place(4, 3, mSplitButton);
place(7, 3, mOutfitButton);
updateWeight();
@@ -182,7 +176,6 @@ void InventoryWindow::action(const gcn::ActionEvent &event)
if (!inventoryWindow->isVisible()) return;
Item *item = inventoryWindow->getSelectedItem();
-
if (!item)
return;
@@ -190,12 +183,13 @@ void InventoryWindow::action(const gcn::ActionEvent &event)
}
Item *item = mItems->getSelectedItem();
-
if (!item)
return;
if (event.getId() == "activate")
+ {
item->doEvent(Event::DoUse);
+ }
else if (event.getId() == "equip")
{
if (item->isEquippable())
@@ -214,15 +208,9 @@ void InventoryWindow::action(const gcn::ActionEvent &event)
{
ItemAmountWindow::showWindow(ItemAmountWindow::ItemDrop, this, item);
}
- else if (event.getId() == "split")
- {
- ItemAmountWindow::showWindow(ItemAmountWindow::ItemSplit, this, item,
- (item->getQuantity() - 1));
- }
else if (event.getId() == "retrieve")
{
Item *item = mItems->getSelectedItem();
-
if (!item)
return;
@@ -247,26 +235,27 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event)
Window::mouseClicked(event);
Item *item = mItems->getSelectedItem();
+ if (!item)
+ return;
- if (event.getSource() == mItems && item && isDoubleClick(item->getInvIndex()))
+ if (event.getSource() == mItems && isDoubleClick(item->getInvIndex())
+ && isMainInventory())
{
- if (isMainInventory() && item->getInfo().activatable)
+ if (item->getInfo().activatable)
{
action(gcn::ActionEvent(mUseButton,
mUseButton->getActionEventId()));
}
- else if (isMainInventory() && item->isEquippable())
+ else if (item->isEquippable())
{
action(gcn::ActionEvent(mEquipButton,
mEquipButton->getActionEventId()));
}
+ return;
}
if (event.getButton() == gcn::MouseEvent::RIGHT)
{
- if (!item)
- return;
-
/* Convert relative to the window coordinates to absolute screen
* coordinates.
*/
@@ -279,10 +268,6 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event)
{
if (instances.size() > 1 && keyboard.isKeyActive(KeyboardConfig::KEY_EMOTE))
{
- Item *item = mItems->getSelectedItem();
-
- if(!item)
- return;
if (mInventory->isMainInventory())
{
Event event(Event::DoMove);
@@ -305,32 +290,10 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event)
}
}
-void InventoryWindow::keyPressed(gcn::KeyEvent &event)
-{
- switch (event.getKey().getValue())
- {
- case Key::LEFT_SHIFT:
- case Key::RIGHT_SHIFT:
- mSplit = true;
- break;
- }
-}
-
void InventoryWindow::keyReleased(gcn::KeyEvent &event)
{
if (isInputFocused())
- {
mItems->setFilter(mFilterText->getText());
- return;
- }
-
- switch (event.getKey().getValue())
- {
- case Key::LEFT_SHIFT:
- case Key::RIGHT_SHIFT:
- mSplit = false;
- break;
- }
}
void InventoryWindow::valueChanged(const gcn::SelectionEvent &event)
@@ -338,15 +301,6 @@ void InventoryWindow::valueChanged(const gcn::SelectionEvent &event)
if (!mInventory->isMainInventory())
return;
- Item *item = mItems->getSelectedItem();
-
- if (mSplit && Net::getInventoryHandler()->
- canSplit(mItems->getSelectedItem()) && item)
- {
- ItemAmountWindow::showWindow(ItemAmountWindow::ItemSplit, this, item,
- (item->getQuantity() - 1));
- }
-
updateButtons();
}
@@ -359,44 +313,19 @@ void InventoryWindow::updateButtons()
mUseButton->setEnabled(false);
mEquipButton->setEnabled(false);
mDropButton->setEnabled(false);
- mSplitButton->setEnabled(false);
-
return;
}
mDropButton->setEnabled(true);
- if (item->isEquippable())
- {
- if (item->isEquipped())
- mEquipButton->setCaption(_("Unequip"));
- else
- mEquipButton->setCaption(_("Equip"));
- mEquipButton->setEnabled(true);
- }
- else
- mEquipButton->setEnabled(false);
-
+ mEquipButton->setCaption(item->isEquipped() ? _("Unequip") : _("Equip"));
+ mEquipButton->setEnabled(item->isEquippable());
mEquipButton->adjustSize();
mUseButton->setEnabled(item->getInfo().activatable);
- if (item->getQuantity() > 1)
- mDropButton->setCaption(_("Drop..."));
- else
- mDropButton->setCaption(_("Drop"));
-
- if (Net::getInventoryHandler()->canSplit(item))
- mSplitButton->setEnabled(true);
- else
- mSplitButton->setEnabled(false);
-
- mSplitButton->adjustSize();
-}
-
-void InventoryWindow::setSplitAllowed(bool allowed)
-{
- mSplitButton->setVisible(allowed);
+ mDropButton->setCaption(item->getQuantity() > 1 ? _("Drop...") : _("Drop"));
+ mDropButton->adjustSize();
}
void InventoryWindow::close()
@@ -418,12 +347,9 @@ void InventoryWindow::event(Event::Channel channel, const Event &event)
{
if (event.getType() == Event::UpdateAttribute)
{
- int id = event.getInt("id");
- if (id == TOTAL_WEIGHT ||
- id == MAX_WEIGHT)
- {
+ const int id = event.getInt("id");
+ if (id == TOTAL_WEIGHT || id == MAX_WEIGHT)
updateWeight();
- }
}
}
@@ -432,8 +358,8 @@ void InventoryWindow::updateWeight()
if (!isMainInventory())
return;
- int total = PlayerInfo::getAttribute(TOTAL_WEIGHT);
- int max = PlayerInfo::getAttribute(MAX_WEIGHT);
+ const int total = PlayerInfo::getAttribute(TOTAL_WEIGHT);
+ const int max = PlayerInfo::getAttribute(MAX_WEIGHT);
if (max <= 0)
return;
@@ -451,21 +377,14 @@ bool InventoryWindow::isInputFocused() const
bool InventoryWindow::isAnyInputFocused()
{
- auto it = instances.begin();
- auto it_end = instances.end();
-
- for (; it != it_end; it++)
- {
- if ((*it)->isInputFocused())
- {
+ for (auto instance : instances)
+ if (instance->isInputFocused())
return true;
- }
- }
return false;
}
-void InventoryWindow::slotsChanged(Inventory* inventory)
+void InventoryWindow::slotsChanged(Inventory *inventory)
{
if (inventory == mInventory)
{
@@ -473,7 +392,6 @@ void InventoryWindow::slotsChanged(Inventory* inventory)
const int maxSlots = mInventory->getSize();
mSlotsBar->setProgress((float) usedSlots / maxSlots);
-
mSlotsBar->setText(strprintf("%d/%d", usedSlots, maxSlots));
}
}
diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h
index 048b229c..267d8dc1 100644
--- a/src/gui/inventorywindow.h
+++ b/src/gui/inventorywindow.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef INVENTORYWINDOW_H
-#define INVENTORYWINDOW_H
+#pragma once
#include "inventory.h"
#include "eventlistener.h"
@@ -28,8 +27,6 @@
#include "gui/widgets/window.h"
#include "gui/widgets/textfield.h"
-#include "net/inventoryhandler.h"
-
#include <guichan/actionlistener.hpp>
#include <guichan/keylistener.hpp>
#include <guichan/selectionlistener.hpp>
@@ -44,12 +41,12 @@ class TextBox;
*
* \ingroup Interface
*/
-class InventoryWindow : public Window,
- public gcn::ActionListener,
- public gcn::KeyListener,
- public gcn::SelectionListener,
- public InventoryListener,
- public EventListener
+class InventoryWindow final : public Window,
+ public gcn::ActionListener,
+ public gcn::KeyListener,
+ public gcn::SelectionListener,
+ public InventoryListener,
+ public EventListener
{
public:
InventoryWindow(Inventory *inventory);
@@ -64,7 +61,7 @@ class InventoryWindow : public Window,
/**
* Returns the selected item.
*/
- Item* getSelectedItem() const;
+ Item *getSelectedItem() const;
/**
* Handles closing of the window
@@ -77,11 +74,6 @@ class InventoryWindow : public Window,
void mouseClicked(gcn::MouseEvent &event) override;
/**
- * Handles the key presses.
- */
- void keyPressed(gcn::KeyEvent &event) override;
-
- /**
* Handles the key releases.
*/
void keyReleased(gcn::KeyEvent &event) override;
@@ -92,11 +84,6 @@ class InventoryWindow : public Window,
void valueChanged(const gcn::SelectionEvent &event) override;
/**
- * Sets whether the split button should be shown.
- */
- void setSplitAllowed(bool allowed);
-
- /**
* Closes the Storage Window, as well as telling the server that the
* window has been closed.
*/
@@ -111,9 +98,9 @@ class InventoryWindow : public Window,
static bool isAnyInputFocused();
- void slotsChanged(Inventory* inventory) override;
+ void slotsChanged(Inventory *inventory) override;
- bool isMainInventory() { return mInventory->isMainInventory(); }
+ bool isMainInventory() const { return mInventory->isMainInventory(); }
void event(Event::Channel channel, const Event &event) override;
@@ -134,16 +121,12 @@ class InventoryWindow : public Window,
std::string mWeight, mSlots;
- gcn::Button *mUseButton, *mEquipButton, *mDropButton, *mSplitButton,
+ gcn::Button *mUseButton, *mEquipButton, *mDropButton,
*mOutfitButton, *mStoreButton, *mRetrieveButton;
gcn::Label *mWeightLabel, *mSlotsLabel, *mFilterLabel;
ProgressBar *mWeightBar, *mSlotsBar;
-
- bool mSplit = false;
};
extern InventoryWindow *inventoryWindow;
-
-#endif
diff --git a/src/gui/itemamountwindow.cpp b/src/gui/itemamountwindow.cpp
index 947b5bdc..de204da3 100644
--- a/src/gui/itemamountwindow.cpp
+++ b/src/gui/itemamountwindow.cpp
@@ -21,6 +21,7 @@
#include "gui/itemamountwindow.h"
+#include "inventory.h"
#include "item.h"
#include "keyboardconfig.h"
@@ -34,8 +35,8 @@
#include "gui/widgets/slider.h"
#include "gui/widgets/icon.h"
-#include "net/inventoryhandler.h"
#include "net/net.h"
+#include "net/tradehandler.h"
#include "utils/gettext.h"
@@ -44,14 +45,11 @@ void ItemAmountWindow::finish(Item *item, int amount, Usage usage)
switch (usage)
{
case TradeAdd:
- tradeWindow->tradeItem(item, amount);
+ Net::getTradeHandler()->addItem(item, amount);
break;
case ItemDrop:
item->doEvent(Event::DoDrop, amount);
break;
- case ItemSplit:
- item->doEvent(Event::DoSplit, amount);
- break;
case StoreAdd:
{
Event event(Event::DoMove);
@@ -130,7 +128,7 @@ ItemAmountWindow::ItemAmountWindow(Usage usage, Window *parent, Item *item,
place(4, 2, cancelButton);
place(5, 2, okButton);
- reflowLayout(225, 0);
+ reflowLayout();
resetAmount();
@@ -148,9 +146,6 @@ ItemAmountWindow::ItemAmountWindow(Usage usage, Window *parent, Item *item,
case StoreRemove:
setCaption(_("Select amount of items to retrieve."));
break;
- case ItemSplit:
- setCaption(_("Select amount of items to split."));
- break;
}
setLocationRelativeTo(getParentWindow());
diff --git a/src/gui/itemamountwindow.h b/src/gui/itemamountwindow.h
index d0ac52d5..489fdbef 100644
--- a/src/gui/itemamountwindow.h
+++ b/src/gui/itemamountwindow.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef ITEM_AMOUNT_WINDOW_H
-#define ITEM_AMOUNT_WINDOW_H
+#pragma once
#include "gui/widgets/window.h"
@@ -33,7 +32,7 @@ class ItemPopup;
class Icon;
/**
- * Window used for selecting the amount of items to drop, trade or split.
+ * Window used for selecting the amount of items to drop, trade or store.
*
* \ingroup Interface
*/
@@ -47,7 +46,6 @@ class ItemAmountWindow : public Window,
ItemDrop,
StoreAdd,
StoreRemove,
- ItemSplit
};
/**
@@ -100,5 +98,3 @@ class ItemAmountWindow : public Window,
bool mEnabledKeyboard;
};
-
-#endif // ITEM_AMOUNT_WINDOW_H
diff --git a/src/gui/itempopup.cpp b/src/gui/itempopup.cpp
index 7f1dec3b..3e7ba15a 100644
--- a/src/gui/itempopup.cpp
+++ b/src/gui/itempopup.cpp
@@ -23,7 +23,6 @@
#include "gui/itempopup.h"
#include "configuration.h"
-#include "graphics.h"
#include "units.h"
#include "gui/gui.h"
@@ -35,7 +34,6 @@
#include "utils/gettext.h"
#include "utils/stringutils.h"
-#include "resources/image.h"
#include "resources/resourcemanager.h"
#include "resources/theme.h"
@@ -45,38 +43,38 @@
#define ITEMPOPUP_WRAP_WIDTH 196
-static const gcn::Color &getColorFromItemType(ItemType type)
+static int getColorIdFromItemType(ItemType type)
{
switch (type)
{
case ITEM_UNUSABLE:
- return Theme::getThemeColor(Theme::GENERIC);
+ return Theme::GENERIC;
case ITEM_USABLE:
- return Theme::getThemeColor(Theme::USABLE);
+ return Theme::USABLE;
case ITEM_EQUIPMENT_ONE_HAND_WEAPON:
- return Theme::getThemeColor(Theme::ONEHAND);
+ return Theme::ONEHAND;
case ITEM_EQUIPMENT_TWO_HANDS_WEAPON:
- return Theme::getThemeColor(Theme::TWOHAND);
+ return Theme::TWOHAND;
case ITEM_EQUIPMENT_TORSO:
- return Theme::getThemeColor(Theme::TORSO);
+ return Theme::TORSO;
case ITEM_EQUIPMENT_ARMS:
- return Theme::getThemeColor(Theme::ARMS);
+ return Theme::ARMS;
case ITEM_EQUIPMENT_HEAD:
- return Theme::getThemeColor(Theme::HEAD);
+ return Theme::HEAD;
case ITEM_EQUIPMENT_LEGS:
- return Theme::getThemeColor(Theme::LEGS);
+ return Theme::LEGS;
case ITEM_EQUIPMENT_SHIELD:
- return Theme::getThemeColor(Theme::SHIELD);
+ return Theme::SHIELD;
case ITEM_EQUIPMENT_RING:
- return Theme::getThemeColor(Theme::RING);
+ return Theme::RING;
case ITEM_EQUIPMENT_NECKLACE:
- return Theme::getThemeColor(Theme::NECKLACE);
+ return Theme::NECKLACE;
case ITEM_EQUIPMENT_FEET:
- return Theme::getThemeColor(Theme::FEET);
+ return Theme::FEET;
case ITEM_EQUIPMENT_AMMO:
- return Theme::getThemeColor(Theme::AMMO);
+ return Theme::AMMO;
default:
- return Theme::getThemeColor(Theme::UNKNOWN_ITEM);
+ return Theme::UNKNOWN_ITEM;
}
}
@@ -134,11 +132,16 @@ void ItemPopup::setNoItem()
mItemName->setCaption(caption);
mItemName->adjustSize();
- mItemName->setForegroundColor(Theme::getThemeColor(Theme::GENERIC));
+ auto theme = gui->getTheme();
+ auto &palette = theme->getPalette(getSkin().palette);
+
+ mItemName->setForegroundColor(palette.getColor(Theme::GENERIC));
+ mItemName->setOutlineColor(palette.getOutlineColor(Theme::GENERIC));
mItemName->setPosition(0, 0);
mItemDesc->setText(std::string());
mItemEffect->setText(std::string());
+ mItemWeight->setText(std::string());
setContentSize(mItemName->getWidth(), mItemName->getHeight());
}
@@ -153,8 +156,8 @@ void ItemPopup::setItem(const ItemInfo &item, bool showImage)
if (showImage)
{
ResourceManager *resman = ResourceManager::getInstance();
- auto image = resman->getImageRef(paths.getStringValue("itemIcons") +
- item.display.image);
+ auto image = resman->getImage(paths.getStringValue("itemIcons") +
+ item.display.image);
mIcon->setImage(image);
if (image)
@@ -174,9 +177,15 @@ void ItemPopup::setItem(const ItemInfo &item, bool showImage)
if (!mItemEquipSlot.empty())
caption += " (" + mItemEquipSlot + ")";
+ auto theme = gui->getTheme();
+ auto &palette = theme->getPalette(getSkin().palette);
+
+ const auto typeColorId = getColorIdFromItemType(mItemType);
+
mItemName->setCaption(caption);
mItemName->adjustSize();
- mItemName->setForegroundColor(getColorFromItemType(mItemType));
+ mItemName->setForegroundColor(palette.getColor(typeColorId));
+ mItemName->setOutlineColor(palette.getOutlineColor(typeColorId));
mItemName->setPosition(space, 0);
mItemDesc->setTextWrapped(item.description, ITEMPOPUP_WRAP_WIDTH);
diff --git a/src/gui/itempopup.h b/src/gui/itempopup.h
index 3b213633..c741ed64 100644
--- a/src/gui/itempopup.h
+++ b/src/gui/itempopup.h
@@ -20,8 +20,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef ITEMPOPUP_H
-#define ITEMPOPUP_H
+#pragma once
#include "gui/widgets/popup.h"
@@ -30,6 +29,7 @@
#include <guichan/mouselistener.hpp>
class Icon;
+class Label;
class TextBox;
/**
@@ -66,7 +66,7 @@ class ItemPopup : public Popup
void mouseMoved(gcn::MouseEvent &mouseEvent) override;
private:
- gcn::Label *mItemName;
+ Label *mItemName;
TextBox *mItemDesc;
TextBox *mItemEffect;
TextBox *mItemWeight;
@@ -74,5 +74,3 @@ class ItemPopup : public Popup
ItemType mItemType;
Icon *mIcon;
};
-
-#endif // ITEMPOPUP_H
diff --git a/src/gui/logindialog.cpp b/src/gui/logindialog.cpp
index 1f96e02d..42ec0842 100644
--- a/src/gui/logindialog.cpp
+++ b/src/gui/logindialog.cpp
@@ -64,8 +64,8 @@ LoginDialog::LoginDialog(LoginData *loginData):
place(0, 0, userLabel);
place(0, 1, passLabel);
- place(1, 0, mUserField, 3).setPadding(1);
- place(1, 1, mPassField, 3).setPadding(1);
+ place(1, 0, mUserField, 3).setPadding(2);
+ place(1, 1, mPassField, 3).setPadding(2);
place(0, 5, mKeepCheck, 4);
place(0, 6, mRegisterButton).setHAlign(LayoutCell::LEFT);
place(2, 6, mServerButton);
diff --git a/src/gui/logindialog.h b/src/gui/logindialog.h
index 67814cd4..fc3fa249 100644
--- a/src/gui/logindialog.h
+++ b/src/gui/logindialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef LOGIN_H
-#define LOGIN_H
+#pragma once
#include "gui/widgets/window.h"
@@ -69,5 +68,3 @@ class LoginDialog : public Window, public gcn::ActionListener,
LoginData *mLoginData;
};
-
-#endif
diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp
index f5206eda..60bfadfa 100644
--- a/src/gui/minimap.cpp
+++ b/src/gui/minimap.cpp
@@ -34,12 +34,14 @@
#include "resources/resourcemanager.h"
#include "resources/userpalette.h"
+#include "utils/filesystem.h"
#include "utils/gettext.h"
+#include <algorithm>
#include <guichan/font.hpp>
Minimap::Minimap():
- Window(_("Map"))
+ Window(SkinType::Popup, _("Map"))
{
setWindowName("Minimap");
setDefaultSize(5, 25, 100, 100);
@@ -58,8 +60,7 @@ Minimap::Minimap():
setVisible(config.showMinimap, isSticky());
}
-Minimap::~Minimap()
-{}
+Minimap::~Minimap() = default;
void Minimap::setMap(Map *map)
{
@@ -86,11 +87,11 @@ void Minimap::setMap(Map *map)
std::string minimapName = map->getProperty("minimap");
- if (minimapName.empty() && resman->exists(tempname))
+ if (minimapName.empty() && FS::exists(tempname))
minimapName = tempname;
if (!minimapName.empty())
- mMapImage = resman->getImageRef(minimapName);
+ mMapImage = resman->getImage(minimapName);
}
if (mMapImage)
@@ -136,40 +137,38 @@ void Minimap::draw(gcn::Graphics *graphics)
{
Window::draw(graphics);
+ if (!mMap)
+ return;
+
+ auto g = static_cast<Graphics*>(graphics);
const gcn::Rectangle a = getChildrenArea();
- graphics->pushClipArea(a);
+ g->pushClipRect(a); // does actual clipping
+ g->pushClipArea(a); // only applies an offset
+
+ const int tileWidth = mMap->getTileWidth();
+ const int tileHeight = mMap->getTileHeight();
int mapOriginX = 0;
int mapOriginY = 0;
- if (mMapImage && mMap)
+ if (mMapImage)
{
if (mMapImage->getWidth() > a.width ||
mMapImage->getHeight() > a.height)
{
const Vector &p = local_player->getPosition();
- mapOriginX = (int) (((a.width) / 2) - (int) (p.x * mWidthProportion)
- / mMap->getTileWidth());
- mapOriginY = (int) (((a.height) / 2)
- - (int) (p.y * mHeightProportion)
- / mMap->getTileHeight());
+ mapOriginX = (a.width / 2) - (int) (p.x * mWidthProportion) / tileWidth;
+ mapOriginY = (a.height / 2) - (int) (p.y * mHeightProportion) / tileHeight;
const int minOriginX = a.width - mMapImage->getWidth();
const int minOriginY = a.height - mMapImage->getHeight();
- if (mapOriginX < minOriginX)
- mapOriginX = minOriginX;
- if (mapOriginY < minOriginY)
- mapOriginY = minOriginY;
- if (mapOriginX > 0)
- mapOriginX = 0;
- if (mapOriginY > 0)
- mapOriginY = 0;
+ mapOriginX = std::clamp(mapOriginX, minOriginX, 0);
+ mapOriginY = std::clamp(mapOriginY, minOriginY, 0);
}
- static_cast<Graphics*>(graphics)->
- drawImage(mMapImage, mapOriginX, mapOriginY);
+ g->drawImage(mMapImage, mapOriginX, mapOriginY);
}
for (auto actor : actorSpriteManager->getAll())
@@ -218,16 +217,14 @@ void Minimap::draw(gcn::Graphics *graphics)
const int offsetWidth = (int) ((dotSize - 1) * mWidthProportion);
const Vector &pos = being->getPosition();
- if (mMap)
- {
- graphics->fillRectangle(gcn::Rectangle(
- (int) (pos.x * mWidthProportion) / mMap->getTileWidth()
- + mapOriginX - offsetWidth,
- (int) (pos.y * mHeightProportion) / mMap->getTileHeight()
- + mapOriginY - offsetHeight,
- dotSize, dotSize));
- }
+ g->fillRectangle(
+ gcn::Rectangle((int) (pos.x * mWidthProportion) / tileWidth + mapOriginX - offsetWidth,
+ (int) (pos.y * mHeightProportion) / tileHeight + mapOriginY
+ - offsetHeight,
+ dotSize,
+ dotSize));
}
- graphics->popClipArea();
+ g->popClipArea();
+ g->popClipRect();
}
diff --git a/src/gui/minimap.h b/src/gui/minimap.h
index 8212f5b7..bf6cd89d 100644
--- a/src/gui/minimap.h
+++ b/src/gui/minimap.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef MINIMAP_H
-#define MINIMAP_H
+#pragma once
#include "gui/widgets/window.h"
@@ -67,5 +66,3 @@ class Minimap : public Window
};
extern Minimap *minimap;
-
-#endif
diff --git a/src/gui/ministatuswindow.cpp b/src/gui/ministatuswindow.cpp
index 598cb722..9d695954 100644
--- a/src/gui/ministatuswindow.cpp
+++ b/src/gui/ministatuswindow.cpp
@@ -21,10 +21,11 @@
#include "gui/ministatuswindow.h"
-#include "animatedsprite.h"
#include "configuration.h"
+#include "game.h"
#include "graphics.h"
#include "playerinfo.h"
+#include "sprite.h"
#include "statuseffect.h"
#include "gui/gui.h"
@@ -39,16 +40,22 @@
#include "net/tmwa/protocol.h"
+#include "resources/statuseffectdb.h"
#include "resources/theme.h"
#include "utils/gettext.h"
#include "utils/stringutils.h"
#include "utils/time.h"
+#include <algorithm>
+
+static constexpr int ICON_SPACING = 3;
+
MiniStatusWindow::MiniStatusWindow():
Popup("MiniStatus")
{
setPadding(3);
+ setMinHeight(0);
listen(Event::AttributesChannel);
listen(Event::ActorSpriteChannel);
@@ -83,8 +90,7 @@ MiniStatusWindow::MiniStatusWindow():
add(mMpBar);
add(mXpBar);
- setContentSize(mXpBar->getX() + mXpBar->getWidth(),
- mXpBar->getY() + mXpBar->getHeight());
+ updateSize();
auto stateIt = config.windows.find(getPopupName());
setVisible(stateIt != config.windows.end() ? stateIt->second.visible.value_or(true)
@@ -95,36 +101,27 @@ MiniStatusWindow::MiniStatusWindow():
addMouseListener(this);
}
-void MiniStatusWindow::setIcon(int index, AnimatedSprite *sprite)
-{
- if (index >= (int) mIcons.size())
- mIcons.resize(index + 1);
-
- delete mIcons[index];
- mIcons[index] = sprite;
-}
-
-void MiniStatusWindow::eraseIcon(int index)
-{
- mIcons.erase(mIcons.begin() + index);
-}
+MiniStatusWindow::~MiniStatusWindow() = default;
void MiniStatusWindow::drawIcons(Graphics *graphics)
{
- // Draw icons
- int icon_x = mXpBar->getX() + mXpBar->getWidth() + 14;
- for (auto &icon : mIcons)
+ const auto game = Game::instance();
+ const int tileWidth = game->getCurrentTileWidth();
+ const int tileHeight = game->getCurrentTileHeight();
+
+ int iconX = mXpBar->getX() + mXpBar->getWidth() + ICON_SPACING + tileWidth / 2;
+ int iconY = ICON_SPACING + tileHeight;
+
+ for (auto &icon : mStatusIcons)
{
- if (icon)
- {
- icon->draw(graphics, icon_x, 3);
- icon_x += 2 + icon->getWidth();
- }
+ icon.sprite->draw(graphics,
+ iconX - icon.sprite->getWidth() / 2,
+ iconY - icon.sprite->getHeight());
+ iconX += ICON_SPACING + icon.sprite->getWidth();
}
}
-void MiniStatusWindow::event(Event::Channel channel,
- const Event &event)
+void MiniStatusWindow::event(Event::Channel channel, const Event &event)
{
if (channel == Event::AttributesChannel)
{
@@ -146,7 +143,7 @@ void MiniStatusWindow::event(Event::Channel channel,
}
if (event.getType() == Event::UpdateStat)
{
- if (Net::getNetworkType() == ServerType::TMWATHENA &&
+ if (Net::getNetworkType() == ServerType::TmwAthena &&
event.getInt("id") == TmwAthena::MATK)
{
StatusWindow::updateMPBar(mMpBar);
@@ -157,54 +154,28 @@ void MiniStatusWindow::event(Event::Channel channel,
{
if (event.getType() == Event::UpdateStatusEffect)
{
- int index = event.getInt("index");
- bool newStatus = event.getBool("newStatus");
+ const int id = event.getInt("index");
+ const bool newStatus = event.getBool("newStatus");
- StatusEffect *effect = StatusEffect::getStatusEffect(index,
- newStatus);
+ auto effect = StatusEffectDB::getStatusEffect(id);
+ if (!effect)
+ return;
- if (effect)
- {
- effect->deliverMessage();
- effect->playSFX();
-
- AnimatedSprite *sprite = effect->getIcon();
-
- if (!sprite)
- {
- // delete sprite, if necessary
- for (unsigned int i = 0; i < mStatusEffectIcons.size();)
- if (mStatusEffectIcons[i] == index)
- {
- mStatusEffectIcons.erase(mStatusEffectIcons.begin()
- + i);
- miniStatusWindow->eraseIcon(i);
- }
- else
- i++;
- }
- else
- {
- // replace sprite or append
- bool found = false;
-
- for (unsigned int i = 0; i < mStatusEffectIcons.size();
- i++)
- if (mStatusEffectIcons[i] == index)
- {
- miniStatusWindow->setIcon(i, sprite);
- found = true;
- break;
- }
-
- if (!found)
- { // add new
- int offset = mStatusEffectIcons.size();
- miniStatusWindow->setIcon(offset, sprite);
- mStatusEffectIcons.push_back(index);
- }
- }
- }
+ effect->deliverMessage(newStatus);
+ effect->playSfx(newStatus);
+
+ Sprite *sprite = newStatus ? effect->getIconSprite() : nullptr;
+ auto it = std::find_if(mStatusIcons.begin(), mStatusIcons.end(),
+ [id](const StatusIcon &icon) {
+ return icon.effectId == id;
+ });
+
+ if (!sprite && it != mStatusIcons.end())
+ mStatusIcons.erase(it);
+ else if (sprite && it == mStatusIcons.end())
+ mStatusIcons.push_back(StatusIcon{id, std::unique_ptr<Sprite>(sprite)});
+
+ updateSize();
}
}
}
@@ -226,43 +197,84 @@ void MiniStatusWindow::logic()
}
*/
- for (auto &icon : mIcons)
- if (icon)
- icon->update(Time::absoluteTimeMs());
+ for (auto &icon : mStatusIcons)
+ icon.sprite->update(Time::deltaTimeMs());
+}
+
+void MiniStatusWindow::draw(gcn::Graphics *graphics)
+{
+ drawChildren(graphics);
+
+ drawIcons(static_cast<Graphics*>(graphics));
}
void MiniStatusWindow::mouseMoved(gcn::MouseEvent &event)
{
Popup::mouseMoved(event);
- const int x = event.getX();
- const int y = event.getY();
+ std::string tooltip1;
+ std::string tooltip2;
if (event.getSource() == mXpBar)
{
- mTextPopup->show(x + getX(), y + getY(),
- strprintf("%u/%u", PlayerInfo::getAttribute(EXP),
- PlayerInfo::getAttribute(EXP_NEEDED)),
- strprintf("%s: %u", _("Need"),
- PlayerInfo::getAttribute(EXP_NEEDED)
- - PlayerInfo::getAttribute(EXP)));
+ const int xp = PlayerInfo::getAttribute(EXP);
+ const int xpNeeded = PlayerInfo::getAttribute(EXP_NEEDED);
+ tooltip1 = strprintf("%u/%u", xp, xpNeeded);
+ tooltip2 = strprintf("%s: %u", _("Need"), xpNeeded - xp);
}
else if (event.getSource() == mHpBar)
{
- mTextPopup->show(x + getX(), y + getY(),
- strprintf("%u/%u", PlayerInfo::getAttribute(HP),
- PlayerInfo::getAttribute(MAX_HP)));
+ const int hp = PlayerInfo::getAttribute(HP);
+ const int maxHp = PlayerInfo::getAttribute(MAX_HP);
+ tooltip1 = strprintf("%u/%u", hp, maxHp);
}
else if (event.getSource() == mMpBar)
{
- mTextPopup->show(x + getX(), y + getY(),
- strprintf("%u/%u", PlayerInfo::getAttribute(MP),
- PlayerInfo::getAttribute(MAX_MP)));
+ const int mp = PlayerInfo::getAttribute(MP);
+ const int maxMp = PlayerInfo::getAttribute(MAX_MP);
+ tooltip1 = strprintf("%u/%u", mp, maxMp);
}
else
{
+ // Check if the mouse is over one of the status icons
+ const auto game = Game::instance();
+ const int tileWidth = game->getCurrentTileWidth();
+ const int tileHeight = game->getCurrentTileHeight();
+
+ int iconX = mXpBar->getX() + mXpBar->getWidth() + ICON_SPACING + tileWidth / 2;
+ int iconY = ICON_SPACING + tileHeight;
+
+ for (const auto &icon : mStatusIcons)
+ {
+ int spriteX = iconX + icon.sprite->getOffsetX() - icon.sprite->getWidth() / 2;
+ int spriteY = iconY + icon.sprite->getOffsetY() - icon.sprite->getHeight();
+
+ if (event.getX() >= spriteX &&
+ event.getX() < spriteX + icon.sprite->getWidth() &&
+ event.getY() >= spriteY &&
+ event.getY() < spriteY + icon.sprite->getHeight())
+ {
+ auto effect = StatusEffectDB::getStatusEffect(icon.effectId);
+ if (effect)
+ tooltip1 = effect->name;
+ break;
+ }
+
+ iconX += ICON_SPACING + icon.sprite->getWidth();
+ }
+ }
+
+ if (tooltip1.empty())
+ {
mTextPopup->setVisible(false);
}
+ else
+ {
+ mTextPopup->show(event.getX() + getX(),
+ event.getY() + getY(),
+ tooltip1,
+ tooltip2);
+ }
}
void MiniStatusWindow::mouseExited(gcn::MouseEvent &event)
@@ -271,3 +283,19 @@ void MiniStatusWindow::mouseExited(gcn::MouseEvent &event)
mTextPopup->setVisible(false);
}
+
+void MiniStatusWindow::updateSize()
+{
+ int width = mXpBar->getX() + mXpBar->getWidth();
+ int height = mXpBar->getY() + mXpBar->getHeight();
+
+ // Increase width based on the size of the status icons
+ if (!mStatusIcons.empty())
+ {
+ width += ICON_SPACING;
+ for (const auto &icon : mStatusIcons)
+ width += ICON_SPACING + icon.sprite->getWidth();
+ }
+
+ setContentSize(width, height);
+}
diff --git a/src/gui/ministatuswindow.h b/src/gui/ministatuswindow.h
index db9e4c69..21c4b76e 100644
--- a/src/gui/ministatuswindow.h
+++ b/src/gui/ministatuswindow.h
@@ -19,16 +19,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef MINISTATUS_H
-#define MINISTATUS_H
+#pragma once
#include "eventlistener.h"
#include "gui/widgets/popup.h"
+#include <memory>
#include <vector>
-class AnimatedSprite;
+class Sprite;
class Graphics;
class ProgressBar;
class TextPopup;
@@ -42,28 +42,20 @@ class MiniStatusWindow : public Popup, public EventListener
{
public:
MiniStatusWindow();
-
- void drawIcons(Graphics *graphics);
+ ~MiniStatusWindow() override;
void event(Event::Channel channel, const Event &event) override;
void logic() override; // Updates icons
- void draw(gcn::Graphics *graphics) override
- { drawChildren(graphics); }
+ void draw(gcn::Graphics *graphics) override;
void mouseMoved(gcn::MouseEvent &mouseEvent) override;
void mouseExited(gcn::MouseEvent &event) override;
private:
- bool isInBar(ProgressBar *bar, int x, int y) const;
-
- /**
- * Sets one of the icons.
- */
- void setIcon(int index, AnimatedSprite *sprite);
-
- void eraseIcon(int index);
+ void drawIcons(Graphics *graphics);
+ void updateSize();
/*
* Mini Status Bars
@@ -73,10 +65,13 @@ class MiniStatusWindow : public Popup, public EventListener
ProgressBar *mXpBar;
TextPopup *mTextPopup;
- std::vector<int> mStatusEffectIcons;
- std::vector<AnimatedSprite *> mIcons;
+ struct StatusIcon
+ {
+ int effectId;
+ std::unique_ptr<Sprite> sprite;
+ };
+
+ std::vector<StatusIcon> mStatusIcons;
};
extern MiniStatusWindow *miniStatusWindow;
-
-#endif
diff --git a/src/gui/npcdialog.cpp b/src/gui/npcdialog.cpp
index 18b3ff1b..16e7db94 100644
--- a/src/gui/npcdialog.cpp
+++ b/src/gui/npcdialog.cpp
@@ -87,8 +87,8 @@ NpcDialog::NpcDialog(int npcId)
// Setup output text box
mTextBox = new BrowserBox(BrowserBox::AUTO_WRAP);
mTextBox->setWrapIndent(15);
- mTextBox->setFrameSize(2);
mTextBox->setLinkHandler(mItemLinkHandler.get());
+ mTextBox->setEnableKeys(true);
mScrollArea = new ScrollArea(mTextBox);
mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
@@ -537,16 +537,11 @@ void NpcEventListener::event(Event::Channel channel,
else if (event.getType() == Event::Next)
{
int id = event.getInt("id");
- NpcDialog *dialog = getDialog(id, false);
- if (!dialog)
- {
- int mNpcId = id;
- Net::getNpcHandler()->nextDialog(mNpcId);
- return;
- }
-
- dialog->showNextButton();
+ if (NpcDialog *dialog = getDialog(id, false))
+ dialog->showNextButton();
+ else
+ Net::getNpcHandler()->nextDialog(id);
}
else if (event.getType() == Event::ClearDialog)
{
@@ -556,32 +551,19 @@ void NpcEventListener::event(Event::Channel channel,
else if (event.getType() == Event::Close)
{
int id = event.getInt("id");
- NpcDialog *dialog = getDialog(id, false);
- if (!dialog)
- {
- int mNpcId = id;
- Net::getNpcHandler()->closeDialog(mNpcId);
- return;
- }
-
- dialog->showCloseButton();
- }
- else if (event.getType() == Event::CloseDialog)
- {
- if (NpcDialog *dialog = getDialog(event.getInt("id"), false))
- dialog->setVisible(false);
+ if (NpcDialog *dialog = getDialog(id, false))
+ dialog->showCloseButton();
+ else
+ Net::getNpcHandler()->closeDialog(id);
}
else if (event.getType() == Event::CloseAll)
{
NpcDialog::closeAll();
}
- else if (event.getType() == Event::End)
+ else if (event.getType() == Event::CloseDialog)
{
- int id = event.getInt("id");
- NpcDialog *dialog = getDialog(id, false);
-
- if (dialog)
+ if (NpcDialog *dialog = getDialog(event.getInt("id"), false))
dialog->close();
}
else if (event.getType() == Event::Post)
diff --git a/src/gui/npcdialog.h b/src/gui/npcdialog.h
index f2b50370..8a18a455 100644
--- a/src/gui/npcdialog.h
+++ b/src/gui/npcdialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef NPCDIALOG_H
-#define NPCDIALOG_H
+#pragma once
#include "gui/widgets/window.h"
@@ -214,5 +213,3 @@ class NpcDialog final : public Window,
NpcInputState mInputState = NPC_INPUT_NONE;
NpcActionState mActionState = NPC_ACTION_WAIT;
};
-
-#endif // NPCDIALOG_H
diff --git a/src/gui/npcpostdialog.h b/src/gui/npcpostdialog.h
index 61c17ca6..7021b5b4 100644
--- a/src/gui/npcpostdialog.h
+++ b/src/gui/npcpostdialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GUI_NPCPOSTDIALOG_H
-#define GUI_NPCPOSTDIALOG_H
+#pragma once
#include "gui/widgets/window.h"
@@ -57,5 +56,3 @@ private:
TextBox *mText;
TextField *mSender;
};
-
-#endif
diff --git a/src/gui/okdialog.h b/src/gui/okdialog.h
index fcb327a9..f56f24e2 100644
--- a/src/gui/okdialog.h
+++ b/src/gui/okdialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef OK_DIALOG_H
-#define OK_DIALOG_H
+#pragma once
#include "gui/widgets/window.h"
@@ -47,5 +46,3 @@ class OkDialog : public Window, public gcn::ActionListener
private:
TextBox *mTextBox;
};
-
-#endif // OK_DIALOG_H
diff --git a/src/gui/outfitwindow.cpp b/src/gui/outfitwindow.cpp
index b5033d70..f914c0cc 100644
--- a/src/gui/outfitwindow.cpp
+++ b/src/gui/outfitwindow.cpp
@@ -78,8 +78,8 @@ OutfitWindow::~OutfitWindow()
void OutfitWindow::load()
{
- for (int o = 0; o < OUTFITS_COUNT; o++)
- memset(mOutfits[o].items, -1, sizeof(mOutfits[o].items));
+ for (auto &mOutfit : mOutfits)
+ memset(mOutfit.items, -1, sizeof(mOutfit.items));
for (auto &outfit : config.outfits)
{
@@ -89,10 +89,8 @@ void OutfitWindow::load()
std::string buf;
std::stringstream ss(outfit.items);
- for (size_t i = 0; (ss >> buf) && i < OUTFIT_ITEM_COUNT; i++)
- {
+ for (int i = 0; (ss >> buf) && i < OUTFIT_ITEM_COUNT; i++)
mOutfits[outfit.index].items[i] = atoi(buf.c_str());
- }
mOutfits[outfit.index].unequip = outfit.unequip;
}
@@ -105,16 +103,15 @@ void OutfitWindow::save()
std::string outfitStr;
for (int o = 0; o < OUTFITS_COUNT; o++)
{
- auto &items = mOutfits[o].items;
bool emptyOutfit = true;
- for (int i = 0; i < OUTFIT_ITEM_COUNT; i++)
+ for (int item : mOutfits[o].items)
{
if (!outfitStr.empty())
outfitStr += " ";
- outfitStr += items[i] ? toString(items[i]) : toString(-1);
- emptyOutfit &= items[i] <= 0;
+ outfitStr += item ? toString(item) : toString(-1);
+ emptyOutfit &= item <= 0;
}
if (!emptyOutfit)
@@ -159,10 +156,9 @@ void OutfitWindow::wearOutfit(int outfit)
if (mOutfits[outfit].unequip)
unequipNotInOutfit(outfit);
- Item *item;
- for (int i = 0; i < OUTFIT_ITEM_COUNT; i++)
+ for (int i : mOutfits[outfit].items)
{
- item = PlayerInfo::getInventory()->findItem(mOutfits[outfit].items[i]);
+ Item *item = PlayerInfo::getInventory()->findItem(i);
if (item && !item->isEquipped() && item->getQuantity())
{
if (item->isEquippable())
@@ -174,9 +170,7 @@ void OutfitWindow::wearOutfit(int outfit)
void OutfitWindow::copyOutfit(int outfit)
{
for (int i = 0; i < OUTFIT_ITEM_COUNT; i++)
- {
mOutfits[mCurrentOutfit].items[i] = mOutfits[outfit].items[i];
- }
}
void OutfitWindow::draw(gcn::Graphics *graphics)
@@ -328,9 +322,9 @@ void OutfitWindow::unequipNotInOutfit(int outfit)
if (inventory->getItem(i) && inventory->getItem(i)->isEquipped())
{
bool found = false;
- for (int f = 0; f < OUTFIT_ITEM_COUNT; f++)
+ for (int item : mOutfits[outfit].items)
{
- if (inventory->getItem(i)->getId() == mOutfits[outfit].items[f])
+ if (inventory->getItem(i)->getId() == item)
{
found = true;
break;
diff --git a/src/gui/outfitwindow.h b/src/gui/outfitwindow.h
index 56e96795..10de5321 100644
--- a/src/gui/outfitwindow.h
+++ b/src/gui/outfitwindow.h
@@ -19,15 +19,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef OUTFITWINDOW_H
-#define OUTFITWINDOW_H
+#pragma once
#include "gui/widgets/window.h"
#include <guichan/actionlistener.hpp>
-#define OUTFITS_COUNT 15
-#define OUTFIT_ITEM_COUNT 9
+constexpr int OUTFITS_COUNT = 15;
+constexpr int OUTFIT_ITEM_COUNT = 9;
class Button;
class CheckBox;
@@ -91,5 +90,3 @@ class OutfitWindow : public Window, gcn::ActionListener
};
extern OutfitWindow *outfitWindow;
-
-#endif
diff --git a/src/gui/palette.cpp b/src/gui/palette.cpp
index 6c6e6f06..948660d2 100644
--- a/src/gui/palette.cpp
+++ b/src/gui/palette.cpp
@@ -25,7 +25,6 @@
#include <cmath>
static constexpr double PI = 3.14159265;
-const gcn::Color Palette::BLACK = gcn::Color(0, 0, 0);
Timer Palette::mRainbowTimer;
Palette::Palettes Palette::mInstances;
@@ -47,23 +46,37 @@ Palette::Palette(int size) :
mInstances.insert(this);
}
+Palette::Palette(Palette &&pal)
+ : mColors(std::move(pal.mColors))
+ , mGradVector(std::move(pal.mGradVector))
+{
+ mInstances.insert(this);
+}
+
Palette::~Palette()
{
mInstances.erase(this);
}
-const gcn::Color &Palette::getColor(char c, bool &valid)
- {
- for (const auto &color : mColors)
+Palette &Palette::operator=(Palette &&pal)
+{
+ if (this != &pal)
{
- if (color.ch == c)
- {
- valid = true;
- return color.color;
- }
+ mColors = std::move(pal.mColors);
+ mGradVector = std::move(pal.mGradVector);
}
- valid = false;
- return BLACK;
+ return *this;
+}
+
+void Palette::setColor(int type,
+ const gcn::Color &color,
+ const std::optional<gcn::Color> &outlineColor,
+ GradientType grad,
+ int delay)
+{
+ auto &elem = mColors[type];
+ elem.set(type, color, grad, delay);
+ elem.outlineColor = outlineColor;
}
void Palette::advanceGradients()
@@ -97,17 +110,19 @@ void Palette::advanceGradient(int advance)
const int pos = elem->gradientIndex % delay;
const int colIndex = elem->gradientIndex / delay;
- if (elem->grad == PULSE)
- {
+ switch (elem->grad) {
+ case STATIC:
+ break;
+ case PULSE: {
const int colVal = (int) (255.0 * sin(PI * colIndex / numOfColors));
const gcn::Color &col = elem->testColor;
elem->color.r = ((colVal * col.r) / 255) % (col.r + 1);
elem->color.g = ((colVal * col.g) / 255) % (col.g + 1);
elem->color.b = ((colVal * col.b) / 255) % (col.b + 1);
+ break;
}
- if (elem->grad == SPECTRUM)
- {
+ case SPECTRUM: {
int colVal;
if (colIndex % 2)
@@ -129,9 +144,9 @@ void Palette::advanceGradient(int advance)
elem->color.b =
(colIndex == 3 || colIndex == 4) ? 255 :
(colIndex == 2 || colIndex == 5) ? colVal : 0;
+ break;
}
- else if (elem->grad == RAINBOW)
- {
+ case RAINBOW: {
const gcn::Color &startCol = RAINBOW_COLORS[colIndex];
const gcn::Color &destCol =
RAINBOW_COLORS[(colIndex + 1) % numOfColors];
@@ -147,6 +162,8 @@ void Palette::advanceGradient(int advance)
elem->color.b =(int)(startColVal * startCol.b +
destColVal * destCol.b);
+ break;
+ }
}
}
}
diff --git a/src/gui/palette.h b/src/gui/palette.h
index 9de911d5..268b9fc6 100644
--- a/src/gui/palette.h
+++ b/src/gui/palette.h
@@ -20,16 +20,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef PALETTE_H
-#define PALETTE_H
+#pragma once
#include "utils/time.h"
#include <guichan/color.hpp>
#include <cstdlib>
-#include <string>
+#include <optional>
#include <set>
+#include <string>
#include <vector>
// Default Gradient Delay
@@ -41,8 +41,13 @@ constexpr int GRADIENT_DELAY = 40;
class Palette
{
public:
- /** Black Color Constant */
- static const gcn::Color BLACK;
+ Palette(int size);
+ Palette(const Palette &) = delete;
+ Palette(Palette &&);
+ ~Palette();
+
+ Palette &operator=(const Palette &) = delete;
+ Palette &operator=(Palette &&);
/** Colors can be static or can alter over time. */
enum GradientType {
@@ -52,62 +57,49 @@ class Palette
RAINBOW
};
- /**
- * Returns the color associated with a character, if it exists. Returns
- * Palette::BLACK if the character is not found.
- *
- * @param c character requested
- * @param valid indicate whether character is known
- *
- * @return the requested color or Palette::BLACK
- */
- const gcn::Color &getColor(char c, bool &valid);
+ void setColor(int type,
+ const gcn::Color &color,
+ const std::optional<gcn::Color> &outlineColor,
+ GradientType grad,
+ int delay);
/**
- * Gets the color associated with the type. Sets the alpha channel
- * before returning.
+ * Gets the color associated with the type.
*
* @param type the color type requested
- * @param alpha alpha channel to use
- *
* @return the requested color
*/
- const gcn::Color &getColor(int type, int alpha = 255)
+ const gcn::Color &getColor(int type) const
{
- gcn::Color &col = mColors[type].color;
- col.a = alpha;
- return col;
+ return mColors[type].color;
}
/**
- * Gets the GradientType associated with the specified type.
+ * Gets the optional outline color associated with the type.
*
- * @param type the color type of the color
- *
- * @return the gradient type of the color with the given index
+ * @param type the color type requested
+ * @return the requested outline color, if any
*/
- GradientType getGradientType(int type) const
+ const std::optional<gcn::Color> &getOutlineColor(int type) const
{
- return mColors[type].grad;
+ return mColors[type].outlineColor;
}
/**
- * Get the character used by the specified color.
+ * Gets the GradientType associated with the specified type.
*
* @param type the color type of the color
- *
- * @return the color char of the color with the given index
+ * @return the gradient type of the color with the given index
*/
- char getColorChar(int type) const
+ GradientType getGradientType(int type) const
{
- return mColors[type].ch;
+ return mColors[type].grad;
}
/**
* Gets the gradient delay for the specified type.
*
* @param type the color type of the color
- *
* @return the gradient delay of the color with the given index
*/
int getGradientDelay(int type) const
@@ -129,10 +121,6 @@ class Palette
using Palettes = std::set<Palette *>;
static Palettes mInstances;
- Palette(int size);
-
- ~Palette();
-
void advanceGradient(int advance);
struct ColorElem
@@ -141,8 +129,8 @@ class Palette
gcn::Color color;
gcn::Color testColor;
gcn::Color committedColor;
+ std::optional<gcn::Color> outlineColor;
std::string text;
- char ch;
GradientType grad;
GradientType committedGrad;
int gradientIndex;
@@ -169,5 +157,3 @@ class Palette
std::vector<ColorElem> mColors;
std::vector<ColorElem*> mGradVector;
};
-
-#endif
diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp
index b1165f27..4bafc074 100644
--- a/src/gui/popupmenu.cpp
+++ b/src/gui/popupmenu.cpp
@@ -91,12 +91,12 @@ void PopupMenu::showPopup(int x, int y, Being *being)
switch (player_relations.getRelation(name))
{
- case PlayerRelation::NEUTRAL:
+ case PlayerRelation::Neutral:
mBrowserBox->addRow(strprintf("@@friend|%s@@",
strprintf(_("Befriend %s"),
name.c_str()).c_str()));
- case PlayerRelation::FRIEND:
+ case PlayerRelation::Friend:
mBrowserBox->addRow(strprintf("@@disregard|%s@@",
strprintf(_("Disregard %s"),
name.c_str()).c_str()));
@@ -105,7 +105,7 @@ void PopupMenu::showPopup(int x, int y, Being *being)
name.c_str()).c_str()));
break;
- case PlayerRelation::DISREGARDED:
+ case PlayerRelation::Disregarded:
mBrowserBox->addRow(strprintf("@@unignore|%s@@",
strprintf(_("Unignore %s"),
name.c_str()).c_str()));
@@ -114,7 +114,7 @@ void PopupMenu::showPopup(int x, int y, Being *being)
name.c_str()).c_str()));
break;
- case PlayerRelation::IGNORED:
+ case PlayerRelation::Ignored:
mBrowserBox->addRow(strprintf("@@unignore|%s@@",
strprintf(_("Unignore %s"),
name.c_str()).c_str()));
@@ -126,7 +126,7 @@ void PopupMenu::showPopup(int x, int y, Being *being)
strprintf(_("Invite %s to join your guild"),
name.c_str()).c_str()));
if (local_player->isInParty() ||
- Net::getNetworkType() == ServerType::MANASERV)
+ Net::getNetworkType() == ServerType::ManaServ)
{
mBrowserBox->addRow(strprintf("@@party|%s@@",
strprintf(_("Invite %s to join your party"),
@@ -223,25 +223,25 @@ void PopupMenu::handleLink(const std::string &link)
else if (link == "unignore" && being &&
being->getType() == ActorSprite::PLAYER)
{
- player_relations.setRelation(being->getName(), PlayerRelation::NEUTRAL);
+ player_relations.setRelation(being->getName(), PlayerRelation::Neutral);
}
else if (link == "ignore" && being &&
being->getType() == ActorSprite::PLAYER)
{
- player_relations.setRelation(being->getName(), PlayerRelation::IGNORED);
+ player_relations.setRelation(being->getName(), PlayerRelation::Ignored);
}
else if (link == "disregard" && being &&
being->getType() == ActorSprite::PLAYER)
{
- player_relations.setRelation(being->getName(), PlayerRelation::DISREGARDED);
+ player_relations.setRelation(being->getName(), PlayerRelation::Disregarded);
}
else if (link == "friend" && being &&
being->getType() == ActorSprite::PLAYER)
{
- player_relations.setRelation(being->getName(), PlayerRelation::FRIEND);
+ player_relations.setRelation(being->getName(), PlayerRelation::Friend);
}
// Guild action
else if (link == "guild" && being &&
@@ -249,18 +249,15 @@ void PopupMenu::handleLink(const std::string &link)
{
local_player->inviteToGuild(being);
}
-
// Pick Up Floor Item action
else if ((link == "pickup") && mFloorItem)
{
local_player->pickUp(mFloorItem);
}
-
// Look To action
else if (link == "look")
{
}
-
else if (link == "activate" || link == "equip" || link == "unequip")
{
assert(mItem);
@@ -288,49 +285,36 @@ void PopupMenu::handleLink(const std::string &link)
else if (mFloorItem)
chatWindow->addItemText(mFloorItem->getInfo().name);
}
-
- else if (link == "split")
- {
- ItemAmountWindow::showWindow(ItemAmountWindow::ItemSplit,
- inventoryWindow, mItem);
- }
-
else if (link == "drop")
{
ItemAmountWindow::showWindow(ItemAmountWindow::ItemDrop,
inventoryWindow, mItem);
}
-
else if (link == "store")
{
ItemAmountWindow::showWindow(ItemAmountWindow::StoreAdd,
inventoryWindow, mItem);
}
-
else if (link == "retrieve")
{
ItemAmountWindow::showWindow(ItemAmountWindow::StoreRemove, mWindow,
mItem);
}
-
else if (link == "party" && being &&
being->getType() == ActorSprite::PLAYER)
{
Net::getPartyHandler()->invite(being);
}
-
else if (link == "name" && being)
{
const std::string &name = being->getName();
chatWindow->addInputText(name);
}
-
else if (link == "admin-kick" && being &&
being->getType() == ActorSprite::PLAYER)
{
Net::getAdminHandler()->kick(being->getName());
}
-
// Unknown actions
else if (link != "cancel")
{
@@ -376,11 +360,6 @@ void PopupMenu::showPopup(Window *parent, int x, int y, Item *item,
else
mBrowserBox->addRow(strprintf("@@drop|%s@@", _("Drop")));
}
-
- if (Net::getInventoryHandler()->canSplit(item))
- {
- mBrowserBox->addRow(strprintf("@@split|%s@@", _("Split")));
- }
}
// Assume in storage for now
// TODO: make this whole system more flexible, if needed
diff --git a/src/gui/popupmenu.h b/src/gui/popupmenu.h
index c7199b78..5a5a88ee 100644
--- a/src/gui/popupmenu.h
+++ b/src/gui/popupmenu.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef POPUP_MENU_H
-#define POPUP_MENU_H
+#pragma once
#include "gui/widgets/linkhandler.h"
#include "gui/widgets/popup.h"
@@ -76,5 +75,3 @@ class PopupMenu : public Popup, public LinkHandler
*/
void showPopup(int x, int y);
};
-
-#endif
diff --git a/src/gui/quitdialog.cpp b/src/gui/quitdialog.cpp
index 4afbd419..51831c4c 100644
--- a/src/gui/quitdialog.cpp
+++ b/src/gui/quitdialog.cpp
@@ -71,7 +71,8 @@ QuitDialog::QuitDialog(QuitDialog** pointerToMe):
placeOption(place, mSwitchAccountServer);
// Only added if we are connected to a gameserver
- if (state == STATE_GAME) placeOption(place, mSwitchCharacter);
+ if (state == STATE_GAME)
+ placeOption(place, mSwitchCharacter);
}
mOptions[0]->setSelected(true);
@@ -90,7 +91,9 @@ QuitDialog::QuitDialog(QuitDialog** pointerToMe):
QuitDialog::~QuitDialog()
{
- if (mMyPointer) *mMyPointer = nullptr;
+ if (mMyPointer)
+ *mMyPointer = nullptr;
+
// Optional widgets, so delete them by hand.
delete mForceQuit;
delete mLogoutQuit;
@@ -166,7 +169,8 @@ void QuitDialog::keyPressed(gcn::KeyEvent &keyEvent)
mOptions[0]->setSelected(true);
return;
}
- else if (it == mOptions.begin() && dir < 0)
+
+ if (it == mOptions.begin() && dir < 0)
it = mOptions.end();
it += dir;
diff --git a/src/gui/quitdialog.h b/src/gui/quitdialog.h
index d62d5c51..4672e45f 100644
--- a/src/gui/quitdialog.h
+++ b/src/gui/quitdialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef QUITDIALOG_H
-#define QUITDIALOG_H
+#pragma once
#include "gui/widgets/window.h"
@@ -69,5 +68,3 @@ class QuitDialog : public Window, public gcn::ActionListener,
QuitDialog **mMyPointer;
};
-
-#endif
diff --git a/src/gui/recorder.cpp b/src/gui/recorder.cpp
index 8dd0f8ed..894e3631 100644
--- a/src/gui/recorder.cpp
+++ b/src/gui/recorder.cpp
@@ -32,15 +32,16 @@
#include "utils/gettext.h"
#include "utils/stringutils.h"
-Recorder::Recorder(ChatWindow *chat, const std::string &title,
- const std::string &buttonTxt) :
- Window(title)
+Recorder::Recorder(ChatWindow *chat,
+ const std::string &title,
+ const std::string &buttonTxt)
+ : Window(title)
+ , mChat(chat)
{
setWindowName("Recorder");
const int offsetX = 2 * getPadding() + 10;
const int offsetY = getTitleBarHeight() + getPadding() + 10;
- mChat = chat;
auto *button = new Button(buttonTxt, "activate", this);
// 123 is the default chat window height. If you change this in Chat, please
@@ -56,16 +57,12 @@ Recorder::Recorder(ChatWindow *chat, const std::string &title,
loadWindowState();
}
-Recorder::~Recorder()
-{
-}
+Recorder::~Recorder() = default;
void Recorder::record(const std::string &msg)
{
if (mStream.is_open())
- {
mStream << msg << std::endl;
- }
}
void Recorder::setRecordingFile(const std::string &msg)
diff --git a/src/gui/recorder.h b/src/gui/recorder.h
index efd73021..8a84f423 100644
--- a/src/gui/recorder.h
+++ b/src/gui/recorder.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef RECORD_H
-#define RECORD_H
+#pragma once
#include "gui/widgets/window.h"
@@ -72,5 +71,3 @@ class Recorder : public Window, public gcn::ActionListener
std::ofstream mStream;
};
-
-#endif
diff --git a/src/gui/register.cpp b/src/gui/register.cpp
index d4ebb59c..62114c10 100644
--- a/src/gui/register.cpp
+++ b/src/gui/register.cpp
@@ -22,14 +22,12 @@
#include "gui/register.h"
#include "client.h"
-#include "configuration.h"
#include "log.h"
#include "gui/logindialog.h"
#include "gui/okdialog.h"
#include "gui/widgets/button.h"
-#include "gui/widgets/checkbox.h"
#include "gui/widgets/label.h"
#include "gui/widgets/layout.h"
#include "gui/widgets/passwordfield.h"
@@ -227,7 +225,7 @@ void RegisterDialog::action(const gcn::ActionEvent &event)
mLoginData->password = mPasswordField->getText();
if (mFemaleButton)
mLoginData->gender = mFemaleButton->isSelected() ?
- Gender::FEMALE : Gender::MALE;
+ Gender::Female : Gender::Male;
if (mEmailField)
mLoginData->email = mEmailField->getText();
mLoginData->registerLogin = true;
diff --git a/src/gui/register.h b/src/gui/register.h
index 1996cd47..ae9ee582 100644
--- a/src/gui/register.h
+++ b/src/gui/register.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef REGISTER_H
-#define REGISTER_H
+#pragma once
#include "gui/widgets/window.h"
@@ -94,5 +93,3 @@ class RegisterDialog : public Window, public gcn::ActionListener,
LoginData *mLoginData;
};
-
-#endif
diff --git a/src/gui/sdlinput.h b/src/gui/sdlinput.h
index a29f17ca..599aafe7 100644
--- a/src/gui/sdlinput.h
+++ b/src/gui/sdlinput.h
@@ -56,8 +56,7 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SDLINPUT_H
-#define SDLINPUT_H
+#pragma once
#include <queue>
@@ -204,5 +203,3 @@ protected:
bool mMouseDown = false;
};
-
-#endif
diff --git a/src/gui/selldialog.cpp b/src/gui/selldialog.cpp
index 5f499982..4aeacd6f 100644
--- a/src/gui/selldialog.cpp
+++ b/src/gui/selldialog.cpp
@@ -205,7 +205,7 @@ void SellDialog::action(const gcn::ActionEvent &event)
sellCount = item->sellCurrentDuplicate(mAmountItems);
// For Manaserv, the Item id is to be given as index.
- if ((Net::getNetworkType() == ServerType::MANASERV))
+ if ((Net::getNetworkType() == ServerType::ManaServ))
itemIndex = item->getId();
Net::getNpcHandler()->sellItem(mNpcId, itemIndex, sellCount);
diff --git a/src/gui/selldialog.h b/src/gui/selldialog.h
index d59343cb..165d9cc8 100644
--- a/src/gui/selldialog.h
+++ b/src/gui/selldialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SELL_H
-#define SELL_H
+#pragma once
#include "gui/widgets/window.h"
@@ -113,5 +112,3 @@ class SellDialog : public Window, gcn::ActionListener, gcn::SelectionListener
int mMaxItems = 0;
int mAmountItems = 0;
};
-
-#endif
diff --git a/src/gui/serverdialog.cpp b/src/gui/serverdialog.cpp
index 01b477da..f5418625 100644
--- a/src/gui/serverdialog.cpp
+++ b/src/gui/serverdialog.cpp
@@ -32,26 +32,21 @@
#include "gui/sdlinput.h"
#include "gui/widgets/button.h"
-#include "gui/widgets/dropdown.h"
#include "gui/widgets/label.h"
#include "gui/widgets/layout.h"
#include "gui/widgets/listbox.h"
#include "gui/widgets/scrollarea.h"
-#include "gui/widgets/textfield.h"
#include "resources/theme.h"
#include "utils/gettext.h"
#include "utils/stringutils.h"
-#include "utils/xml.h"
#include <guichan/font.hpp>
#include <cstdlib>
#include <string>
-static const int MAX_SERVERLIST = 6;
-
ServersListModel::ServersListModel(ServerInfos *servers, ServerDialog *parent):
mServers(servers),
mVersionStrings(servers->size(), VersionString(0, std::string())),
@@ -61,13 +56,11 @@ ServersListModel::ServersListModel(ServerInfos *servers, ServerDialog *parent):
int ServersListModel::getNumberOfElements()
{
- MutexLocker lock(mParent->getMutex());
return mServers->size();
}
std::string ServersListModel::getElementAt(int elementIndex)
{
- MutexLocker lock(mParent->getMutex());
const ServerInfo &server = mServers->at(elementIndex);
std::string myServer;
myServer += server.hostname;
@@ -102,27 +95,25 @@ public:
auto *model = static_cast<ServersListModel*>(mListModel);
- updateAlpha();
-
- graphics->setColor(Theme::getThemeColor(Theme::HIGHLIGHT,
- (int) (mAlpha * 255.0f)));
graphics->setFont(getFont());
const int height = getRowHeight();
- const gcn::Color unsupported =
- Theme::getThemeColor(Theme::SERVER_VERSION_NOT_SUPPORTED,
- (int) (mAlpha * 255.0f));
// Draw filled rectangle around the selected list element
if (mSelected >= 0)
+ {
+ auto highlightColor = Theme::getThemeColor(Theme::HIGHLIGHT);
+ highlightColor.a = gui->getTheme()->getGuiAlpha();
+ graphics->setColor(highlightColor);
graphics->fillRectangle(gcn::Rectangle(0, height * mSelected,
getWidth(), height));
+ }
// Draw the list elements
for (int i = 0, y = 0; i < model->getNumberOfElements();
++i, y += height)
{
- ServerInfo info = model->getServer(i);
+ const ServerInfo &info = model->getServer(i);
graphics->setColor(Theme::getThemeColor(Theme::TEXT));
@@ -140,8 +131,9 @@ public:
if (info.version.first > 0)
{
- graphics->setColor(unsupported);
-
+ auto unsupportedColor = Theme::getThemeColor(Theme::SERVER_VERSION_NOT_SUPPORTED);
+ unsupportedColor.a = gui->getTheme()->getGuiAlpha();
+ graphics->setColor(unsupportedColor);
graphics->drawText(info.version.second,
getWidth() - info.version.first - 2, top);
}
@@ -164,9 +156,8 @@ ServerDialog::ServerDialog(ServerInfo *serverInfo, const std::string &dir):
loadCustomServers();
- mServersListModel = new ServersListModel(&mServers, this);
-
- mServersList = new ServersListBox(mServersListModel);
+ mServersListModel = std::make_unique<ServersListModel>(&mServers, this);
+ mServersList = new ServersListBox(mServersListModel.get());
auto *usedScroll = new ScrollArea(mServersList);
usedScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
@@ -185,8 +176,8 @@ ServerDialog::ServerDialog(ServerInfo *serverInfo, const std::string &dir):
usedScroll->setVerticalScrollAmount(0);
place(0, 0, usedScroll, 6, 5).setPadding(3);
- place(0, 5, mDescription, 5);
- place(0, 6, mDownloadText, 5);
+ place(0, 5, mDescription, 6);
+ place(0, 6, mDownloadText, 6);
place(0, 7, mManualEntryButton);
place(1, 7, mModifyButton);
place(2, 7, mDeleteButton);
@@ -226,16 +217,7 @@ ServerDialog::ServerDialog(ServerInfo *serverInfo, const std::string &dir):
downloadServerList();
}
-ServerDialog::~ServerDialog()
-{
- if (mDownload)
- {
- mDownload->cancel();
- delete mDownload;
- mDownload = nullptr;
- }
- delete mServersListModel;
-}
+ServerDialog::~ServerDialog() = default;
void ServerDialog::action(const gcn::ActionEvent &event)
{
@@ -251,7 +233,7 @@ void ServerDialog::action(const gcn::ActionEvent &event)
// Check login
if (index < 0
#ifndef MANASERV_SUPPORT
- || mServersListModel->getServer(index).type == ServerType::MANASERV
+ || mServersListModel->getServer(index).type == ServerType::ManaServ
#endif
)
{
@@ -262,6 +244,7 @@ void ServerDialog::action(const gcn::ActionEvent &event)
else
{
mDownload->cancel();
+
mQuitButton->setEnabled(false);
mConnectButton->setEnabled(false);
mDeleteButton->setEnabled(false);
@@ -345,7 +328,6 @@ void ServerDialog::valueChanged(const gcn::SelectionEvent &)
// Update the server and post fields according to the new selection
const ServerInfo &myServer = mServersListModel->getServer(index);
mDescription->setCaption(myServer.description);
-
mDeleteButton->setEnabled(myServer.save);
mModifyButton->setEnabled(myServer.save);
}
@@ -362,36 +344,42 @@ void ServerDialog::mouseClicked(gcn::MouseEvent &mouseEvent)
void ServerDialog::logic()
{
- {
- MutexLocker lock(&mMutex);
- if (mDownloadStatus == DOWNLOADING_COMPLETE)
- {
- mDownloadStatus = DOWNLOADING_OVER;
+ Window::logic();
- mDescription->setCaption(mServers[0].description);
- mDownloadText->setCaption(std::string());
- }
- else if (mDownloadStatus == DOWNLOADING_IN_PROGRESS)
- {
- mDownloadText->setCaption(strprintf(_("Downloading server list..."
- "%2.2f%%"),
- mDownloadProgress * 100));
- }
- else if (mDownloadStatus == DOWNLOADING_IDLE)
- {
- mDownloadText->setCaption(_("Waiting for server..."));
- }
- else if (mDownloadStatus == DOWNLOADING_PREPARING)
+ if (mDownloadDone)
+ return;
+
+ auto state = mDownload->getState();
+
+ switch (state.status) {
+ case DownloadStatus::InProgress:
+ mDownloadText->setCaption(strprintf(_("Downloading server list..."
+ "%2.0f%%"),
+ state.progress * 100));
+ break;
+
+ case DownloadStatus::Canceled:
+ case DownloadStatus::Error:
+ mDownloadDone = true;
+ logger->log("Error retrieving server list: %s", mDownload->getError());
+ mDownloadText->setCaption(_("Error retrieving server list!"));
+ break;
+
+ case DownloadStatus::Complete:
+ mDownloadDone = true;
+ loadServers();
+
+ if (mServers.empty())
{
- mDownloadText->setCaption(_("Preparing download"));
+ mDownloadText->setCaption(_("No servers found!"));
}
- else if (mDownloadStatus == DOWNLOADING_ERROR)
+ else
{
- mDownloadText->setCaption(_("Error retreiving server list!"));
+ mDownloadText->setCaption(std::string());
+ mDescription->setCaption(mServers[0].description);
}
+ break;
}
-
- Window::logic();
}
void ServerDialog::downloadServerList()
@@ -406,7 +394,7 @@ void ServerDialog::downloadServerList()
if (listFile.empty())
listFile = "https://www.manasource.org/serverlist.xml";
- mDownload = new Net::Download(this, listFile, &downloadUpdate);
+ mDownload = std::make_unique<Net::Download>(listFile);
mDownload->setFile(mDir + "/serverlist.xml");
mDownload->start();
}
@@ -432,102 +420,99 @@ void ServerDialog::loadServers()
for (auto serverNode : rootNode.children())
{
- if (serverNode.name() != "server")
- continue;
+ if (serverNode.name() == "server")
+ loadServer(serverNode);
+ }
+}
- ServerInfo server;
+void ServerDialog::loadServer(XML::Node serverNode)
+{
+ ServerInfo server;
- std::string type = serverNode.getProperty("type", "unknown");
+ std::string type = serverNode.getProperty("type", "unknown");
- server.type = ServerInfo::parseType(type);
+ server.type = ServerInfo::parseType(type);
- // Ignore unknown server types
- if (server.type == ServerType::UNKNOWN
+ // Ignore unknown server types
+ if (server.type == ServerType::Unknown
#ifndef MANASERV_SUPPORT
- || server.type == ServerType::MANASERV
+ || server.type == ServerType::ManaServ
#endif
)
- {
- logger->log("Ignoring server entry with unknown type: %s",
- type.c_str());
- continue;
- }
+ {
+ logger->log("Ignoring server entry with unknown type: %s",
+ type.c_str());
+ return;
+ }
- server.name = serverNode.getProperty("name", std::string());
+ server.name = serverNode.getProperty("name", std::string());
- std::string version = serverNode.getProperty("minimumVersion",
- std::string());
+ std::string version = serverNode.getProperty("minimumVersion",
+ std::string());
- bool meetsMinimumVersion = compareStrI(version, PACKAGE_VERSION) <= 0;
+ bool meetsMinimumVersion = strcmp(version.c_str(), PACKAGE_VERSION) <= 0;
- // For display in the list
- if (meetsMinimumVersion)
- version.clear();
- else if (version.empty())
- version = _("requires a newer version");
- else
- version = strprintf(_("requires v%s"), version.c_str());
+ // For display in the list
+ if (meetsMinimumVersion)
+ version.clear();
+ else if (version.empty())
+ version = _("requires a newer version");
+ else
+ version = strprintf(_("requires v%s"), version.c_str());
- for (auto subNode : serverNode.children())
+ for (auto subNode : serverNode.children())
+ {
+ if (subNode.name() == "connection")
{
- if (subNode.name() == "connection")
+ server.hostname = subNode.getProperty("hostname", std::string());
+ server.port = subNode.getProperty("port", 0);
+ if (server.port == 0)
{
- server.hostname = subNode.getProperty("hostname", std::string());
- server.port = subNode.getProperty("port", 0);
- if (server.port == 0)
- {
- // If no port is given, use the default for the given type
- server.port = ServerInfo::defaultPortForServerType(server.type);
- }
- }
- else if (subNode.name() == "description")
- {
- server.description = subNode.textContent();
- }
- else if (subNode.name() == "persistentIp")
- {
- const auto text = subNode.textContent();
- server.persistentIp = text == "1" || text == "true";
+ // If no port is given, use the default for the given type
+ server.port = ServerInfo::defaultPortForServerType(server.type);
}
}
+ else if (subNode.name() == "description")
+ {
+ server.description = subNode.textContent();
+ }
+ else if (subNode.name() == "persistentIp")
+ {
+ const auto text = subNode.textContent();
+ server.persistentIp = text == "1" || text == "true";
+ }
+ }
- server.version.first = gui->getFont()->getWidth(version);
- server.version.second = version;
+ server.version.first = gui->getFont()->getWidth(version);
+ server.version.second = version;
- MutexLocker lock(&mMutex);
- // Add the server to the local list if it's not already present
- bool found = false;
- int i = 0;
- for (auto &s : mServers)
+ // Add the server to the local list if it's not already present
+ bool found = false;
+ int i = 0;
+ for (auto &s : mServers)
+ {
+ if (s == server)
{
- if (s == server)
- {
- // Use the name listed in the server list
- s.name = server.name;
- s.version = server.version;
- s.description = server.description;
- mServersListModel->setVersionString(i, version);
- found = true;
- break;
- }
- ++i;
+ // Use the name listed in the server list
+ s.name = server.name;
+ s.version = server.version;
+ s.description = server.description;
+ mServersListModel->setVersionString(i, version);
+ found = true;
+ break;
}
-
- if (!found)
- mServers.push_back(server);
+ ++i;
}
+
+ if (!found)
+ mServers.push_back(server);
}
void ServerDialog::loadCustomServers()
{
for (auto &server : config.servers)
- {
if (server.isValid())
- {
- server.save = true;
mServers.push_back(server);
- }
- }
}
void ServerDialog::saveCustomServers(const ServerInfo &currentServer, int index)
@@ -558,51 +543,6 @@ void ServerDialog::saveCustomServers(const ServerInfo &currentServer, int index)
// Restore the correct description
if (index < 0)
index = 0;
- mDescription->setCaption(mServers[index].description);
-}
-
-int ServerDialog::downloadUpdate(void *ptr, DownloadStatus status,
- size_t total, size_t remaining)
-{
- if (status == DOWNLOAD_STATUS_CANCELLED)
- return -1;
-
- auto *sd = reinterpret_cast<ServerDialog*>(ptr);
- bool finished = false;
-
- if (status == DOWNLOAD_STATUS_COMPLETE)
- {
- finished = true;
- }
- else if (status < 0)
- {
- logger->log("Error retreiving server list: %s",
- sd->mDownload->getError());
- sd->mDownloadStatus = DOWNLOADING_ERROR;
- }
- else
- {
- float progress = (float) remaining / total;
-
- if (progress != progress)
- progress = 0.0f; // check for NaN
- else if (progress < 0.0f)
- progress = 0.0f; // no idea how this could ever happen, but why not check for it anyway.
- else if (progress > 1.0f)
- progress = 1.0f;
-
- MutexLocker lock(&sd->mMutex);
- sd->mDownloadStatus = DOWNLOADING_IN_PROGRESS;
- sd->mDownloadProgress = progress;
- }
-
- if (finished)
- {
- sd->loadServers();
-
- MutexLocker lock(&sd->mMutex);
- sd->mDownloadStatus = DOWNLOADING_COMPLETE;
- }
-
- return 0;
+ if (static_cast<size_t>(index) < mServers.size())
+ mDescription->setCaption(mServers[index].description);
}
diff --git a/src/gui/serverdialog.h b/src/gui/serverdialog.h
index 4db36462..cc2725be 100644
--- a/src/gui/serverdialog.h
+++ b/src/gui/serverdialog.h
@@ -19,21 +19,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SERVERDIALOG_H
-#define SERVERDIALOG_H
+#pragma once
#include "gui/widgets/window.h"
#include "net/download.h"
#include "net/serverinfo.h"
-
-#include "utils/mutex.h"
+#include "utils/xml.h"
#include <guichan/actionlistener.hpp>
#include <guichan/keylistener.hpp>
#include <guichan/listmodel.hpp>
#include <guichan/selectionlistener.hpp>
+#include <memory>
#include <string>
#include <vector>
@@ -90,7 +89,6 @@ class ServerDialog : public Window,
{
public:
ServerDialog(ServerInfo *serverInfo, const std::string &dir);
-
~ServerDialog() override;
/**
@@ -110,10 +108,8 @@ class ServerDialog : public Window,
void logic() override;
protected:
- friend class ServersListModel;
- Mutex *getMutex() { return &mMutex; }
-
friend class CustomServerDialog;
+
/**
* Saves the new server entry in the custom server list.
* Removes the given entry when the serverInfo is empty.
@@ -128,12 +124,10 @@ class ServerDialog : public Window,
*/
void downloadServerList();
void loadServers();
+ void loadServer(XML::Node serverNode);
void loadCustomServers();
- static int downloadUpdate(void *ptr, DownloadStatus status,
- size_t total, size_t remaining);
-
Label *mDescription;
Button *mQuitButton;
Button *mConnectButton;
@@ -142,31 +136,13 @@ class ServerDialog : public Window,
Button *mDeleteButton;
ListBox *mServersList;
- ServersListModel *mServersListModel;
+ std::unique_ptr<ServersListModel> mServersListModel;
const std::string &mDir;
- enum ServerDialogDownloadStatus
- {
- DOWNLOADING_ERROR,
- DOWNLOADING_PREPARING,
- DOWNLOADING_IDLE,
- DOWNLOADING_IN_PROGRESS,
- DOWNLOADING_COMPLETE,
- DOWNLOADING_OVER
- };
-
- /** Status of the current download. */
- ServerDialogDownloadStatus mDownloadStatus = DOWNLOADING_PREPARING;
-
- Net::Download *mDownload = nullptr;
+ std::unique_ptr<Net::Download> mDownload;
+ bool mDownloadDone = false;
Label *mDownloadText;
-
- Mutex mMutex;
- float mDownloadProgress = -1.0f;
-
ServerInfos mServers;
ServerInfo *mServerInfo;
};
-
-#endif
diff --git a/src/gui/setup.h b/src/gui/setup.h
index d510267d..ec45f93b 100644
--- a/src/gui/setup.h
+++ b/src/gui/setup.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SETUP_H
-#define SETUP_H
+#pragma once
#include "gui/widgets/window.h"
@@ -72,5 +71,3 @@ class Setup : public Window, public gcn::ActionListener
};
extern Setup* setupWindow;
-
-#endif
diff --git a/src/gui/setup_audio.cpp b/src/gui/setup_audio.cpp
index f51bfcb6..43b132d8 100644
--- a/src/gui/setup_audio.cpp
+++ b/src/gui/setup_audio.cpp
@@ -29,6 +29,7 @@
#include "gui/widgets/checkbox.h"
#include "gui/widgets/label.h"
+#include "gui/widgets/layout.h"
#include "gui/widgets/slider.h"
#include "utils/gettext.h"
@@ -71,11 +72,11 @@ Setup_Audio::Setup_Audio():
// Do the layout
place(0, 0, mSoundCheckBox);
- place(0, 1, mSfxSlider);
+ place(0, 1, mSfxSlider).setVAlign(LayoutCell::CENTER);
place(1, 1, sfxLabel);
- place(0, 2, mNotificationsSlider);
+ place(0, 2, mNotificationsSlider).setVAlign(LayoutCell::CENTER);
place(1, 2, notificationsLabel);
- place(0, 3, mMusicSlider);
+ place(0, 3, mMusicSlider).setVAlign(LayoutCell::CENTER);
place(1, 3, musicLabel);
place(0, 4, mDownloadMusicCheckBox);
}
diff --git a/src/gui/setup_audio.h b/src/gui/setup_audio.h
index 4ee277ef..c19b38b6 100644
--- a/src/gui/setup_audio.h
+++ b/src/gui/setup_audio.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GUI_SETUP_AUDIO_H
-#define GUI_SETUP_AUDIO_H
+#pragma once
#include "guichanfwd.h"
@@ -51,5 +50,3 @@ class Setup_Audio : public SetupTab, public gcn::ActionListener
gcn::Slider *mNotificationsSlider;
gcn::Slider *mMusicSlider;
};
-
-#endif // GUI_SETUP_AUDIO_H
diff --git a/src/gui/setup_colors.cpp b/src/gui/setup_colors.cpp
index 880f6f8a..89eb668e 100644
--- a/src/gui/setup_colors.cpp
+++ b/src/gui/setup_colors.cpp
@@ -73,14 +73,21 @@ Setup_Colors::Setup_Colors() :
mGradTypeText = new Label;
- std::string longText = _("Static");
-
- if (getFont()->getWidth(_("Pulse")) > getFont()->getWidth(longText))
- longText = _("Pulse");
- if (getFont()->getWidth(_("Rainbow")) > getFont()->getWidth(longText))
- longText = _("Rainbow");
- if (getFont()->getWidth(_("Spectrum")) > getFont()->getWidth(longText))
- longText = _("Spectrum");
+ // Initialize with widest label for layout purposes
+ const char *longText = _("Static");
+ int longWidth = getFont()->getWidth(longText);
+
+ auto maybeLonger = [&] (const char *text) {
+ const int width = getFont()->getWidth(text);
+ if (width > longWidth)
+ {
+ longText = text;
+ longWidth = width;
+ }
+ };
+ maybeLonger(_("Pulse"));
+ maybeLonger(_("Rainbow"));
+ maybeLonger(_("Spectrum"));
mGradTypeText->setCaption(longText);
@@ -150,19 +157,19 @@ Setup_Colors::Setup_Colors() :
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(3, 7, mGradTypeSlider).setVAlign(Layout::CENTER);
place(4, 7, mGradTypeText, 2).setPadding(1);
place(0, 8, mRedLabel, 3);
- place(3, 8, mRedSlider);
+ place(3, 8, mRedSlider).setVAlign(Layout::CENTER);
place(5, 8, mRedText).setPadding(1);
place(0, 9, mGreenLabel, 3);
- place(3, 9, mGreenSlider);
+ place(3, 9, mGreenSlider).setVAlign(Layout::CENTER);
place(5, 9, mGreenText).setPadding(1);
place(0, 10, mBlueLabel, 3);
- place(3, 10, mBlueSlider);
+ place(3, 10, mBlueSlider).setVAlign(Layout::CENTER);
place(5, 10, mBlueText).setPadding(1);
place(0, 11, mGradDelayLabel, 3);
- place(3, 11, mGradDelaySlider);
+ place(3, 11, mGradDelaySlider).setVAlign(Layout::CENTER);
place(5, 11, mGradDelayText).setPadding(1);
mGradTypeText->setCaption(std::string());
@@ -214,10 +221,10 @@ void Setup_Colors::action(const gcn::ActionEvent &event)
}
}
-void Setup_Colors::valueChanged(const gcn::SelectionEvent &event)
+void Setup_Colors::valueChanged(const gcn::SelectionEvent &)
{
mSelected = mColorBox->getSelected();
- int type = userPalette->getColorTypeAt(mSelected);
+ const int type = userPalette->getColorTypeAt(mSelected);
const gcn::Color *col = &userPalette->getColor(type);
Palette::GradientType grad = userPalette->getGradientType(type);
const int delay = userPalette->getGradientDelay(type);
@@ -226,11 +233,7 @@ void Setup_Colors::valueChanged(const gcn::SelectionEvent &event)
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)
{
@@ -242,6 +245,10 @@ void Setup_Colors::valueChanged(const gcn::SelectionEvent &event)
case UserPalette::HIT_CRITICAL:
case UserPalette::MISS:
mTextPreview->setShadow(false);
+ break;
+ default:
+ mTextPreview->setShadow(true);
+ break;
}
if (grad != Palette::STATIC && grad != Palette::PULSE)
diff --git a/src/gui/setup_colors.h b/src/gui/setup_colors.h
index b534ca8a..9aa5be74 100644
--- a/src/gui/setup_colors.h
+++ b/src/gui/setup_colors.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SETUP_COLORS_H
-#define SETUP_COLORS_H
+#pragma once
#include "guichanfwd.h"
@@ -87,5 +86,3 @@ class Setup_Colors : public SetupTab,
void updateColor();
void updateGradType();
};
-
-#endif // SETUP_COLORS_H
diff --git a/src/gui/setup_interface.cpp b/src/gui/setup_interface.cpp
index 7eef974c..ce77d3e6 100644
--- a/src/gui/setup_interface.cpp
+++ b/src/gui/setup_interface.cpp
@@ -23,12 +23,15 @@
#include "configuration.h"
+#include "gui/okdialog.h"
#include "gui/widgets/checkbox.h"
+#include "gui/widgets/dropdown.h"
#include "gui/widgets/label.h"
#include "gui/widgets/layout.h"
#include "gui/widgets/slider.h"
#include "gui/widgets/spacer.h"
-#include "gui/widgets/dropdown.h"
+
+#include "resources/theme.h"
#include "utils/gettext.h"
@@ -37,8 +40,35 @@
#include <SDL.h>
+#include <algorithm>
#include <string>
+class ThemesListModel : public gcn::ListModel
+{
+public:
+ int getNumberOfElements() override
+ {
+ return gui->getAvailableThemes().size();
+ }
+
+ std::string getElementAt(int i) override
+ {
+ return gui->getAvailableThemes().at(i).getName();
+ }
+
+ static int getThemeIndex(const std::string &path)
+ {
+ auto &themes = gui->getAvailableThemes();
+ auto themeIt = std::find_if(themes.begin(),
+ themes.end(),
+ [&](const ThemeInfo &theme) {
+ return theme.getPath() == path;
+ });
+ return themeIt != themes.end() ? std::distance(themes.begin(), themeIt) : 0;
+ }
+};
+
+
const char *SIZE_NAME[4] =
{
N_("Tiny"),
@@ -97,8 +127,7 @@ Setup_Interface::Setup_Interface():
mPickupParticleEnabled)),
mSpeechSlider(new Slider(0, 3)),
mSpeechLabel(new Label(std::string())),
- mAlphaSlider(new Slider(0.2, 1.0)),
- mFontSize(config.fontSize)
+ mAlphaSlider(new Slider(0.2, 1.0))
{
setName(_("Interface"));
@@ -108,18 +137,21 @@ Setup_Interface::Setup_Interface():
mShowMonsterDamageCheckBox = new CheckBox(_("Show damage"),
mShowMonsterDamageEnabled);
- speechLabel = new Label(_("Overhead text:"));
- alphaLabel = new Label(_("GUI opacity"));
- fontSizeLabel = new Label(_("Font size:"));
+ gcn::Label *speechLabel = new Label(_("Overhead text:"));
+ gcn::Label *alphaLabel = new Label(_("GUI opacity"));
+ gcn::Label *themeLabel = new Label(_("Theme:"));
+ gcn::Label *fontSizeLabel = new Label(_("Font size:"));
+
+ mThemesListModel = std::make_unique<ThemesListModel>();
+ mThemeDropDown = new DropDown(mThemesListModel.get());
- mFontSizeListModel = new FontSizeChoiceListModel;
- mFontSizeDropDown = new DropDown(mFontSizeListModel);
+ mFontSizeListModel = std::make_unique<FontSizeChoiceListModel>();
+ mFontSizeDropDown = new DropDown(mFontSizeListModel.get());
mAlphaSlider->setValue(mOpacity);
mAlphaSlider->setWidth(90);
mAlphaSlider->setEnabled(!config.disableTransparency);
-
// Set actions
mShowMonsterDamageCheckBox->setActionEventId("monsterdamage");
mVisibleNamesCheckBox->setActionEventId("visiblenames");
@@ -127,6 +159,7 @@ Setup_Interface::Setup_Interface():
mPickupParticleCheckBox->setActionEventId("pickupparticle");
mNameCheckBox->setActionEventId("showownname");
mNPCLogCheckBox->setActionEventId("lognpc");
+ mThemeDropDown->setActionEventId("theme");
mAlphaSlider->setActionEventId("guialpha");
mSpeechSlider->setActionEventId("speech");
@@ -137,13 +170,16 @@ Setup_Interface::Setup_Interface():
mPickupParticleCheckBox->addActionListener(this);
mNameCheckBox->addActionListener(this);
mNPCLogCheckBox->addActionListener(this);
+ mThemeDropDown->addActionListener(this);
mAlphaSlider->addActionListener(this);
mSpeechSlider->addActionListener(this);
mSpeechLabel->setCaption(speechModeToString(mSpeechMode));
mSpeechSlider->setValue(mSpeechMode);
- mFontSizeDropDown->setSelected(mFontSize - 10);
+ mThemeDropDown->setSelected(ThemesListModel::getThemeIndex(config.theme));
+
+ mFontSizeDropDown->setSelected(config.fontSize - 10);
mFontSizeDropDown->adjustHeight();
// Do the layout
@@ -162,27 +198,35 @@ Setup_Interface::Setup_Interface():
place(0, 5, space, 1, 1);
- place(0, 6, fontSizeLabel, 2);
- place(2, 6, mFontSizeDropDown, 2);
+ place(0, 6, themeLabel, 2);
+ place(2, 6, mThemeDropDown, 2).setPadding(2);
- place(0, 7, space, 1, 1);
+ place(0, 7, fontSizeLabel, 2);
+ place(2, 7, mFontSizeDropDown, 2).setPadding(2);
- place(0, 8, mAlphaSlider, 2);
- place(2, 8, alphaLabel, 2);
+ place(0, 8, space, 1, 1);
- place(0, 9, mSpeechSlider, 2);
- place(2, 9, speechLabel, 2);
- place(4, 9, mSpeechLabel, 2).setPadding(2);
-}
+ place(0, 9, mAlphaSlider, 2);
+ place(2, 9, alphaLabel, 2);
-Setup_Interface::~Setup_Interface()
-{
- delete mFontSizeListModel;
+ place(0, 10, mSpeechSlider, 2);
+ place(2, 10, speechLabel, 2);
+ place(4, 10, mSpeechLabel, 2).setPadding(2);
}
+Setup_Interface::~Setup_Interface() = default;
+
void Setup_Interface::apply()
{
- config.fontSize = mFontSizeDropDown->getSelected() + 10;
+ auto &theme = gui->getAvailableThemes().at(mThemeDropDown->getSelected());
+ auto fontSize = mFontSizeDropDown->getSelected() + 10;
+ if (config.theme != theme.getPath() || config.fontSize != fontSize)
+ {
+ new OkDialog(_("Changing Theme or Font Size"),
+ _("Theme and font size changes will apply after restart."));
+ }
+ config.theme = theme.getPath();
+ config.fontSize = fontSize;
mShowMonsterDamageEnabled = config.showMonstersTakedDamage;
mVisibleNamesEnabled = config.visibleNames;
@@ -201,6 +245,8 @@ void Setup_Interface::cancel()
mSpeechSlider->setValue(mSpeechMode);
mNameCheckBox->setSelected(mNameEnabled);
mNPCLogCheckBox->setSelected(mNPCLogEnabled);
+ mThemeDropDown->setSelected(ThemesListModel::getThemeIndex(config.theme));
+ mFontSizeDropDown->setSelected(config.fontSize - 10);
mAlphaSlider->setValue(mOpacity);
//mAlphaSlider->setEnabled(!mSDLTransparencyDisabled);
diff --git a/src/gui/setup_interface.h b/src/gui/setup_interface.h
index 530d575a..027526a2 100644
--- a/src/gui/setup_interface.h
+++ b/src/gui/setup_interface.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GUI_SETUP_INTERFACE_H
-#define GUI_SETUP_INTERFACE_H
+#pragma once
#include "being.h"
#include "guichanfwd.h"
@@ -30,8 +29,6 @@
#include <guichan/actionlistener.hpp>
#include <guichan/keylistener.hpp>
-class FontSizeChoiceListModel;
-
class Setup_Interface : public SetupTab, public gcn::ActionListener,
public gcn::KeyListener
{
@@ -54,11 +51,8 @@ class Setup_Interface : public SetupTab, public gcn::ActionListener,
double mOpacity;
Being::Speech mSpeechMode;
- FontSizeChoiceListModel *mFontSizeListModel;
-
- gcn::Label *speechLabel;
- gcn::Label *alphaLabel;
- gcn::Label *fontSizeLabel;
+ std::unique_ptr<gcn::ListModel> mThemesListModel;
+ std::unique_ptr<gcn::ListModel> mFontSizeListModel;
gcn::CheckBox *mShowMonsterDamageCheckBox;
gcn::CheckBox *mVisibleNamesCheckBox;
@@ -73,9 +67,7 @@ class Setup_Interface : public SetupTab, public gcn::ActionListener,
gcn::Label *mSpeechLabel;
gcn::Slider *mAlphaSlider;
- int mFontSize;
+ gcn::DropDown *mThemeDropDown;
gcn::DropDown *mFontSizeDropDown;
};
-
-#endif
diff --git a/src/gui/setup_joystick.h b/src/gui/setup_joystick.h
index e51ccbe8..8b319ad2 100644
--- a/src/gui/setup_joystick.h
+++ b/src/gui/setup_joystick.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GUI_SETUP_JOYSTICK_H
-#define GUI_SETUP_JOYSTICK_H
+#pragma once
#include "guichanfwd.h"
@@ -44,5 +43,3 @@ class Setup_Joystick : public SetupTab, public gcn::ActionListener
bool mJoystickEnabled;
gcn::CheckBox *mJoystickCheckBox;
};
-
-#endif
diff --git a/src/gui/setup_keyboard.h b/src/gui/setup_keyboard.h
index 1c9d1733..e953bdf3 100644
--- a/src/gui/setup_keyboard.h
+++ b/src/gui/setup_keyboard.h
@@ -20,8 +20,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GUI_SETUP_KEYBOARD_H
-#define GUI_SETUP_KEYBOARD_H
+#pragma once
#include "guichanfwd.h"
@@ -71,5 +70,3 @@ class Setup_Keyboard : public SetupTab, public gcn::ActionListener
bool mKeySetting; /**< flag to check if key being set. */
};
-
-#endif
diff --git a/src/gui/setup_players.cpp b/src/gui/setup_players.cpp
index 67fe79da..7cfa572a 100644
--- a/src/gui/setup_players.cpp
+++ b/src/gui/setup_players.cpp
@@ -267,13 +267,13 @@ Setup_Players::Setup_Players():
place(0, 0, mPlayerTitleTable, 4);
place(0, 1, mPlayerScrollArea, 4, 4).setPadding(2);
place(0, 5, mDeleteButton);
- place(0, 6, mShowGenderCheckBox, 2).setPadding(2);
- place(0, 7, mEnableChatLogCheckBox, 2).setPadding(2);
+ place(0, 6, mShowGenderCheckBox, 2);
+ place(0, 7, mEnableChatLogCheckBox, 2);
place(2, 5, ignore_action_label);
- place(2, 6, mIgnoreActionChoicesBox, 2).setPadding(2);
+ place(2, 6, mIgnoreActionChoicesBox, 2);
place(0, 8, mDefaultTrading);
place(0, 9, mDefaultWhisper);
- place(0, 10, mWhisperTabCheckBox, 4).setPadding(4);
+ place(0, 10, mWhisperTabCheckBox, 4);
player_relations.addListener(this);
}
diff --git a/src/gui/setup_players.h b/src/gui/setup_players.h
index 126d621b..3ca422d2 100644
--- a/src/gui/setup_players.h
+++ b/src/gui/setup_players.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GUI_SETUP_PLAYERS_H
-#define GUI_SETUP_PLAYERS_H
+#pragma once
#include "guichanfwd.h"
#include "playerrelations.h"
@@ -70,5 +69,3 @@ private:
gcn::CheckBox *mShowGenderCheckBox;
gcn::CheckBox *mEnableChatLogCheckBox;
};
-
-#endif
diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp
index 38602a5c..313badd8 100644
--- a/src/gui/setup_video.cpp
+++ b/src/gui/setup_video.cpp
@@ -25,13 +25,13 @@
#include "configuration.h"
#include "game.h"
#include "graphics.h"
-#include "gui/widgets/dropdown.h"
#include "localplayer.h"
#include "particle.h"
#include "gui/okdialog.h"
#include "gui/widgets/checkbox.h"
+#include "gui/widgets/dropdown.h"
#include "gui/widgets/label.h"
#include "gui/widgets/layout.h"
#include "gui/widgets/slider.h"
@@ -325,17 +325,17 @@ Setup_Video::Setup_Video():
place(0, 2, mDisableSDLTransparencyCheckBox, 4);
place(0, 3, mFpsCheckBox);
- place(1, 3, mFpsSlider, 2);
+ place(1, 3, mFpsSlider, 2).setVAlign(LayoutCell::CENTER);
place(3, 3, mFpsLabel);
place(0, 4, mParticleEffectsCheckBox, 4);
place(0, 5, particleDetailLabel);
- place(1, 5, mParticleDetailSlider, 2);
+ place(1, 5, mParticleDetailSlider, 2).setVAlign(LayoutCell::CENTER);
place(3, 5, mParticleDetailField);
place(0, 6, overlayDetailLabel);
- place(1, 6, mOverlayDetailSlider, 2);
+ place(1, 6, mOverlayDetailSlider, 2).setVAlign(LayoutCell::CENTER);
place(3, 6, mOverlayDetailField);
}
@@ -557,6 +557,6 @@ void Setup_Video::refreshScaleList()
}
mScaleListModel->setVideoSettings(mVideoSettings);
- mScaleDropDown->setListModel(mScaleListModel.get());
+ mScaleDropDown->adjustHeight();
mScaleDropDown->setSelected(mVideoSettings.userScale);
}
diff --git a/src/gui/setup_video.h b/src/gui/setup_video.h
index 6d4fbe77..969d8e8f 100644
--- a/src/gui/setup_video.h
+++ b/src/gui/setup_video.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GUI_SETUP_VIDEO_H
-#define GUI_SETUP_VIDEO_H
+#pragma once
#include "guichanfwd.h"
@@ -30,6 +29,7 @@
#include <guichan/actionlistener.hpp>
#include <guichan/keylistener.hpp>
+class DropDown;
class ResolutionListModel;
class ScaleListModel;
@@ -60,7 +60,7 @@ class Setup_Video : public SetupTab, public gcn::ActionListener,
gcn::DropDown *mWindowModeDropDown;
gcn::DropDown *mResolutionDropDown;
- gcn::DropDown *mScaleDropDown;
+ DropDown *mScaleDropDown;
gcn::CheckBox *mVSyncCheckBox;
gcn::CheckBox *mOpenGLCheckBox;
gcn::CheckBox *mCustomCursorCheckBox;
@@ -80,5 +80,3 @@ class Setup_Video : public SetupTab, public gcn::ActionListener,
gcn::CheckBox *mDisableSDLTransparencyCheckBox;
};
-
-#endif
diff --git a/src/gui/shortcutwindow.cpp b/src/gui/shortcutwindow.cpp
index 7d299d2c..2cffbb81 100644
--- a/src/gui/shortcutwindow.cpp
+++ b/src/gui/shortcutwindow.cpp
@@ -31,6 +31,7 @@ static constexpr int GRAB_MARGIN = 4;
ShortcutWindow::ShortcutWindow(const std::string &title,
ShortcutContainer *content)
+ : Window(SkinType::ToolWindow, std::string())
{
setWindowName(title);
// no title presented, title bar gets some extra space so window can be moved.
@@ -41,7 +42,11 @@ ShortcutWindow::ShortcutWindow(const std::string &title,
setSaveVisible(true);
setupWindow->registerWindowForReset(this);
- const int border = getPadding() * 2;
+ auto scrollArea = new ScrollArea(content);
+ scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ scrollArea->setOpaque(false);
+
+ const int border = (getPadding() + content->getFrameSize()) * 2;
setMinWidth(content->getBoxWidth() + border);
setMinHeight(content->getBoxHeight() + border + GRAB_MARGIN);
setMaxWidth(content->getBoxWidth() * content->getMaxItems() + border);
@@ -49,10 +54,6 @@ ShortcutWindow::ShortcutWindow(const std::string &title,
setDefaultSize(getMinWidth(), getMaxHeight(), ImageRect::LOWER_RIGHT);
- auto scrollArea = new ScrollArea(content);
- scrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
- scrollArea->setOpaque(false);
-
place(0, 0, scrollArea, 5, 5).setPadding(0);
Layout &layout = getLayout();
diff --git a/src/gui/shortcutwindow.h b/src/gui/shortcutwindow.h
index 7494dfed..68e031ad 100644
--- a/src/gui/shortcutwindow.h
+++ b/src/gui/shortcutwindow.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SHORTCUTWINDOW_H
-#define SHORTCUTWINDOW_H
+#pragma once
#include "gui/widgets/window.h"
@@ -39,5 +38,3 @@ class ShortcutWindow : public Window
extern ShortcutWindow *itemShortcutWindow;
extern ShortcutWindow *emoteShortcutWindow;
-
-#endif
diff --git a/src/gui/skilldialog.cpp b/src/gui/skilldialog.cpp
index 5b85252d..40421daf 100644
--- a/src/gui/skilldialog.cpp
+++ b/src/gui/skilldialog.cpp
@@ -30,7 +30,6 @@
#include "gui/widgets/button.h"
#include "gui/widgets/label.h"
#include "gui/widgets/listbox.h"
-#include "gui/widgets/progressbar.h"
#include "gui/widgets/scrollarea.h"
#include "gui/widgets/tab.h"
#include "gui/widgets/tabbedarea.h"
@@ -43,7 +42,6 @@
#include "resources/resourcemanager.h"
#include "resources/theme.h"
-#include "utils/dtor.h"
#include "utils/gettext.h"
#include "utils/stringutils.h"
#include "utils/xml.h"
@@ -61,7 +59,7 @@ struct SkillInfo
{
unsigned short id;
std::string name;
- Image *icon = nullptr;
+ ResourceRef<Image> icon;
bool modifiable;
bool visible;
SkillModel *model = nullptr;
@@ -73,25 +71,16 @@ struct SkillInfo
float progress;
gcn::Color color;
- ~SkillInfo()
- {
- if (icon)
- icon->decRef();
- }
+ ~SkillInfo() = default;
void setIcon(const std::string &iconPath)
{
ResourceManager *res = ResourceManager::getInstance();
if (!iconPath.empty())
- {
icon = res->getImage(iconPath);
- }
if (!icon)
- {
- icon = Theme::getImageFromTheme(
- paths.getStringValue("unknownItemFile"));
- }
+ icon = Theme::getImageFromTheme(paths.getStringValue("unknownItemFile"));
}
void update();
@@ -113,19 +102,19 @@ public:
void updateVisibilities();
- void addSkill(SkillInfo *info)
- { mSkills.push_back(info); }
+ void addSkill(std::unique_ptr<SkillInfo> info)
+ { mSkills.push_back(std::move(info)); }
private:
- std::vector<SkillInfo *> mSkills;
+ std::vector<std::unique_ptr<SkillInfo>> mSkills;
std::vector<SkillInfo *> mVisibleSkills;
};
class SkillListBox : public ListBox
{
public:
- SkillListBox(SkillModel *model):
- ListBox(model)
+ SkillListBox(SkillModel *model)
+ : ListBox(model)
{}
SkillInfo *getSelectedInfo()
@@ -142,19 +131,17 @@ public:
if (!mListModel)
return;
- auto* model = static_cast<SkillModel*>(mListModel);
-
- updateAlpha();
+ auto *model = static_cast<SkillModel *>(mListModel);
+ auto *graphics = static_cast<Graphics *>(gcnGraphics);
- auto *graphics = static_cast<Graphics*>(gcnGraphics);
-
- graphics->setColor(Theme::getThemeColor(Theme::HIGHLIGHT,
- (int) (mAlpha * 255.0f)));
graphics->setFont(getFont());
// Draw filled rectangle around the selected list element
if (mSelected >= 0)
{
+ auto highlightColor = Theme::getThemeColor(Theme::HIGHLIGHT);
+ highlightColor.a = gui->getTheme()->getGuiAlpha();
+ graphics->setColor(highlightColor);
graphics->fillRectangle(gcn::Rectangle(0, getRowHeight() * mSelected,
getWidth(), getRowHeight()));
}
@@ -165,12 +152,8 @@ public:
i < model->getNumberOfElements();
++i, y += getRowHeight())
{
- SkillInfo *e = model->getSkillAt(i);
-
- if (e)
- {
+ if (SkillInfo *e = model->getSkillAt(i))
e->draw(graphics, y, getWidth());
- }
}
}
@@ -180,8 +163,8 @@ public:
class SkillTab : public Tab
{
public:
- SkillTab(const std::string &name, SkillListBox *listBox):
- mListBox(listBox)
+ SkillTab(const std::string &name, SkillListBox *listBox)
+ : mListBox(listBox)
{
setCaption(name);
}
@@ -189,7 +172,6 @@ public:
~SkillTab() override
{
delete mListBox;
- mListBox = nullptr;
}
SkillInfo *getSelectedInfo()
@@ -215,11 +197,11 @@ SkillDialog::SkillDialog():
setMinWidth(240);
setupWindow->registerWindowForReset(this);
- mTabs = new TabbedArea();
+ mTabbedArea = new TabbedArea;
mPointsLabel = new Label("0");
mIncreaseButton = new Button(_("Up"), "inc", this);
- place(0, 0, mTabs, 5, 5);
+ place(0, 0, mTabbedArea, 5, 5);
place(0, 5, mPointsLabel, 4);
place(4, 5, mIncreaseButton);
@@ -236,7 +218,7 @@ void SkillDialog::action(const gcn::ActionEvent &event)
{
if (event.getId() == "inc")
{
- auto *tab = static_cast<SkillTab*>(mTabs->getSelectedTab());
+ auto *tab = static_cast<SkillTab*>(mTabbedArea->getSelectedTab());
if (SkillInfo *info = tab->getSelectedInfo())
Net::getPlayerHandler()->increaseSkill(info->id);
}
@@ -249,12 +231,11 @@ void SkillDialog::action(const gcn::ActionEvent &event)
std::string SkillDialog::update(int id)
{
auto i = mSkills.find(id);
-
if (i != mSkills.end())
{
- SkillInfo *info = i->second;
- info->update();
- return info->name;
+ SkillInfo &info = *i->second;
+ info.update();
+ return info.name;
}
return std::string();
@@ -267,9 +248,7 @@ void SkillDialog::update()
mPointsLabel->adjustSize();
for (auto &skill : mSkills)
- {
skill.second->update();
- }
}
void SkillDialog::event(Event::Channel channel, const Event &event)
@@ -291,20 +270,11 @@ void SkillDialog::event(Event::Channel channel, const Event &event)
void SkillDialog::clearSkills()
{
- // Fixes issues with removing tabs
- if (mTabs->getSelectedTabIndex() != -1)
- {
- mTabs->setSelectedTab((unsigned int) 0);
+ for (auto &tab : mTabs)
+ mTabbedArea->removeTab(tab.get());
- while (mTabs->getSelectedTabIndex() != -1)
- {
- gcn::Tab *tab = mTabs->getSelectedTab();
- mTabs->removeTabWithIndex(mTabs->getSelectedTabIndex());
- delete tab;
- }
- }
-
- delete_all(mSkills);
+ mTabs.clear();
+ mSkillModels.clear();
mSkills.clear();
}
@@ -317,40 +287,40 @@ void SkillDialog::loadSkills()
int setCount = 0;
std::string setName;
- ScrollArea *scroll;
- SkillListBox *listbox;
- SkillTab *tab;
if (!root || root.name() != "skills")
{
logger->log("Error loading skills file: %s", SKILLS_FILE);
- if (Net::getNetworkType() == ServerType::TMWATHENA)
+ if (Net::getNetworkType() == ServerType::TmwAthena)
{
- auto *model = new SkillModel();
- auto *skill = new SkillInfo;
+ auto model = std::make_unique<SkillModel>();
+ auto skill = std::make_unique<SkillInfo>();
skill->id = 1;
skill->name = "basic";
skill->setIcon(std::string());
skill->modifiable = true;
skill->visible = true;
- skill->model = model;
+ skill->model = model.get();
skill->update();
- model->addSkill(skill);
- mSkills[1] = skill;
+ mSkills[1] = skill.get();
+ model->addSkill(std::move(skill));
model->updateVisibilities();
- listbox = new SkillListBox(model);
- scroll = new ScrollArea(listbox);
+ auto listbox = new SkillListBox(model.get());
+ auto scroll = std::make_unique<ScrollArea>(listbox);
scroll->setOpaque(false);
scroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
scroll->setVerticalScrollPolicy(ScrollArea::SHOW_ALWAYS);
- tab = new SkillTab("Skills", listbox);
+ auto tab = std::make_unique<SkillTab>("Skills", listbox);
+ mTabbedArea->addTab(tab.get(), scroll.get());
- mTabs->addTab(tab, scroll);
+ mTabs.push_back(std::move(tab));
+ mTabWidgets.push_back(std::move(scroll));
+ mSkillModels.push_back(std::move(model));
update();
}
@@ -365,7 +335,7 @@ void SkillDialog::loadSkills()
setCount++;
setName = set.getProperty("name", strprintf(_("Skill Set %d"), setCount));
- auto *model = new SkillModel();
+ auto model = std::make_unique<SkillModel>();
for (auto node : set.children())
{
@@ -375,34 +345,39 @@ void SkillDialog::loadSkills()
std::string name = node.getProperty("name", strprintf(_("Skill %d"), id));
std::string icon = node.getProperty("icon", "");
- auto *skill = new SkillInfo;
+ auto skill = std::make_unique<SkillInfo>();
skill->id = id;
skill->name = name;
skill->setIcon(icon);
skill->modifiable = false;
skill->visible = false;
- skill->model = model;
+ skill->model = model.get();
skill->update();
- model->addSkill(skill);
+ mSkills[id] = skill.get();
- mSkills[id] = skill;
+ model->addSkill(std::move(skill));
}
}
model->updateVisibilities();
- listbox = new SkillListBox(model);
- scroll = new ScrollArea(listbox);
+ auto listbox = new SkillListBox(model.get());
+ auto scroll = std::make_unique<ScrollArea>(listbox);
scroll->setOpaque(false);
scroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER);
scroll->setVerticalScrollPolicy(ScrollArea::SHOW_ALWAYS);
- tab = new SkillTab(setName, listbox);
+ auto tab = std::make_unique<SkillTab>(setName, listbox);
+
+ mTabbedArea->addTab(tab.get(), scroll.get());
- mTabs->addTab(tab, scroll);
+ mTabs.push_back(std::move(tab));
+ mTabWidgets.push_back(std::move(scroll));
+ mSkillModels.push_back(std::move(model));
}
}
+
update();
}
@@ -412,9 +387,9 @@ void SkillDialog::setModifiable(int id, bool modifiable)
if (it != mSkills.end())
{
- SkillInfo *info = it->second;
- info->modifiable = modifiable;
- info->update();
+ SkillInfo &info = *it->second;
+ info.modifiable = modifiable;
+ info.update();
}
}
@@ -423,12 +398,8 @@ void SkillModel::updateVisibilities()
mVisibleSkills.clear();
for (auto &skill : mSkills)
- {
if (skill->visible)
- {
- mVisibleSkills.push_back(skill);
- }
- }
+ mVisibleSkills.push_back(skill.get());
}
void SkillInfo::update()
@@ -504,8 +475,7 @@ void SkillInfo::draw(Graphics *graphics, int y, int width)
if (!skillExp.empty())
{
- gcn::Rectangle rect(33, y + 15, width - 33, 17);
-
- ProgressBar::render(graphics, rect, color, progress, skillExp);
+ const gcn::Rectangle rect(33, y + 15, width - 33, 17);
+ gui->getTheme()->drawProgressBar(graphics, rect, color, progress, skillExp);
}
}
diff --git a/src/gui/skilldialog.h b/src/gui/skilldialog.h
index e88c279f..83dc8dd2 100644
--- a/src/gui/skilldialog.h
+++ b/src/gui/skilldialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SKILLDIALOG_H
-#define SKILLDIALOG_H
+#pragma once
#include "gui/widgets/window.h"
#include "eventlistener.h"
@@ -28,10 +27,13 @@
#include <guichan/actionlistener.hpp>
#include <map>
+#include <memory>
+#include <vector>
class Button;
class Label;
class ScrollArea;
+class SkillModel;
class Tab;
class TabbedArea;
@@ -46,7 +48,6 @@ class SkillDialog : public Window, public gcn::ActionListener, public EventListe
{
public:
SkillDialog();
-
~SkillDialog() override;
void event(Event::Channel channel, const Event &event) override;
@@ -75,12 +76,13 @@ class SkillDialog : public Window, public gcn::ActionListener, public EventListe
bool hasSkills() { return !mSkills.empty(); }
private:
- std::map<int, SkillInfo *> mSkills;
- TabbedArea *mTabs;
+ std::vector<std::unique_ptr<SkillModel>> mSkillModels;
+ std::vector<std::unique_ptr<Tab>> mTabs;
+ std::vector<std::unique_ptr<gcn::Widget>> mTabWidgets;
+ std::map<int, SkillInfo*> mSkills;
+ TabbedArea *mTabbedArea;
Label *mPointsLabel;
Button *mIncreaseButton;
};
extern SkillDialog *skillDialog;
-
-#endif
diff --git a/src/gui/socialwindow.cpp b/src/gui/socialwindow.cpp
index 5a15da8f..265fb166 100644
--- a/src/gui/socialwindow.cpp
+++ b/src/gui/socialwindow.cpp
@@ -34,6 +34,7 @@
#include "gui/widgets/avatarlistbox.h"
#include "gui/widgets/browserbox.h"
#include "gui/widgets/button.h"
+#include "gui/widgets/layout.h"
#include "gui/widgets/linkhandler.h"
#include "gui/widgets/popup.h"
#include "gui/widgets/scrollarea.h"
@@ -170,7 +171,7 @@ public:
{
setCaption(party->getName());
- setTabColor(&Theme::getThemeColor(Theme::PARTY_SOCIAL_TAB));
+ setTabColor(&Theme::getThemeColor(Theme::PARTY_TAB));
mList = std::make_unique<AvatarListBox>(party);
mScroll = std::make_unique<ScrollArea>(mList.get());
@@ -236,6 +237,11 @@ private:
class PlayerList : public AvatarListModel
{
public:
+ ~PlayerList() override
+ {
+ delete_all(mPlayers);
+ }
+
void setPlayers(const std::vector<Avatar*> &players)
{
delete_all(mPlayers);
@@ -273,7 +279,7 @@ public:
mScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_AUTO);
}
- ~PlayerListTab()
+ ~PlayerListTab() override
{
delete mPlayerList;
}
@@ -355,13 +361,8 @@ SocialWindow::SocialWindow() :
setResizable(true);
setSaveVisible(true);
setCloseButton(true);
- setMinWidth(120);
- setMinHeight(55);
- setDefaultSize(590, 200, 150, 124);
setupWindow->registerWindowForReset(this);
- loadWindowState();
-
mCreateButton = new Button(_("Create"), "create", this);
mInviteButton = new Button(_("Invite"), "invite", this);
mLeaveButton = new Button(_("Leave"), "leave", this);
@@ -372,19 +373,23 @@ SocialWindow::SocialWindow() :
place(2, 0, mLeaveButton);
place(0, 1, mTabs, 4, 4);
- widgetResized(nullptr);
+ // Determine minimum size
+ int width = 0, height = 0;
+ getLayout().reflow(width, height);
+ setMinimumContentSize(width, height);
+
+ setDefaultSize(590, 200, 150, 124);
+ loadWindowState();
mCreatePopup = new CreatePopup;
mPlayerListTab = new PlayerListTab;
- mPlayerListTab->setCaption(strprintf(_("Online (%zu)"), 0ul));
+ mPlayerListTab->setCaption(strprintf(_("Online (%u)"), 0u));
mTabs->addTab(mPlayerListTab, mPlayerListTab->mScroll.get());
if (local_player->getParty())
- {
addTab(local_player->getParty());
- }
else
updateButtons();
}
@@ -673,7 +678,9 @@ void SocialWindow::showPartyCreate()
void SocialWindow::setPlayersOnline(const std::vector<Avatar*> &players)
{
mPlayerListTab->setPlayers(players);
- mPlayerListTab->setCaption(strprintf(_("Online (%zu)"), players.size()));
+
+ unsigned playerCount = static_cast<unsigned>(players.size());
+ mPlayerListTab->setCaption(strprintf(_("Online (%u)"), playerCount));
}
void SocialWindow::logic()
diff --git a/src/gui/socialwindow.h b/src/gui/socialwindow.h
index 350f919c..d23f1b86 100644
--- a/src/gui/socialwindow.h
+++ b/src/gui/socialwindow.h
@@ -18,8 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SOCIALWINDOW_H
-#define SOCIALWINDOW_H
+#pragma once
#include "utils/time.h"
@@ -111,5 +110,3 @@ protected:
};
extern SocialWindow *socialWindow;
-
-#endif // SOCIALWINDOW_H
diff --git a/src/gui/speechbubble.cpp b/src/gui/speechbubble.cpp
index 58747d57..72ec8bd2 100644
--- a/src/gui/speechbubble.cpp
+++ b/src/gui/speechbubble.cpp
@@ -27,14 +27,11 @@
#include "gui/widgets/label.h"
#include "gui/widgets/textbox.h"
-#include "resources/theme.h"
-
#include <guichan/font.hpp>
-
#include <guichan/widgets/label.hpp>
-SpeechBubble::SpeechBubble():
- Popup("Speech", "speechbubble.xml")
+SpeechBubble::SpeechBubble()
+ : Popup("Speech", SkinType::SpeechBubble)
{
setMinWidth(0);
setMinHeight(0);
@@ -45,7 +42,7 @@ SpeechBubble::SpeechBubble():
mSpeechBox = new TextBox;
mSpeechBox->setEditable(false);
mSpeechBox->setOpaque(false);
- mSpeechBox->setTextColor(&Theme::getThemeColor(Theme::CHAT));
+ mSpeechBox->setTextColor(&Theme::getThemeColor(Theme::BUBBLE_TEXT));
add(mCaption);
add(mSpeechBox);
@@ -60,11 +57,9 @@ void SpeechBubble::setCaption(const std::string &name, const gcn::Color *color)
void SpeechBubble::setText(const std::string &text, bool showName)
{
- if (text == mText && (mCaption->getWidth() <= mSpeechBox->getMinWidth()))
+ if (text == mText && mCaption->getWidth() <= mSpeechBox->getMinWidth())
return;
- mSpeechBox->setTextColor(&Theme::getThemeColor(Theme::TEXT));
-
int width = mCaption->getWidth();
mSpeechBox->setTextWrapped(text, 130 > width ? 130 : width);
const int speechWidth = mSpeechBox->getMinWidth();
diff --git a/src/gui/speechbubble.h b/src/gui/speechbubble.h
index da677dcd..fbb1a21e 100644
--- a/src/gui/speechbubble.h
+++ b/src/gui/speechbubble.h
@@ -20,8 +20,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SPEECHBUBBLE_H
-#define SPEECHBUBBLE_H
+#pragma once
#include "gui/widgets/popup.h"
@@ -51,5 +50,3 @@ class SpeechBubble : public Popup
gcn::Label *mCaption;
TextBox *mSpeechBox;
};
-
-#endif
diff --git a/src/gui/statuswindow.cpp b/src/gui/statuswindow.cpp
index ffcfa350..108d68cc 100644
--- a/src/gui/statuswindow.cpp
+++ b/src/gui/statuswindow.cpp
@@ -290,7 +290,7 @@ void StatusWindow::event(Event::Channel channel,
it->second->update();
}
- if (Net::getNetworkType() == ServerType::TMWATHENA &&
+ if (Net::getNetworkType() == ServerType::TmwAthena &&
id == TmwAthena::MATK)
{
updateMPBar(mMpBar, true);
diff --git a/src/gui/statuswindow.h b/src/gui/statuswindow.h
index 99c3b46a..fc7ad67c 100644
--- a/src/gui/statuswindow.h
+++ b/src/gui/statuswindow.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef STATUS_H
-#define STATUS_H
+#pragma once
#include "eventlistener.h"
@@ -85,5 +84,3 @@ class StatusWindow : public Window, public EventListener
};
extern StatusWindow *statusWindow;
-
-#endif
diff --git a/src/gui/textdialog.h b/src/gui/textdialog.h
index 66ab3e53..d9634434 100644
--- a/src/gui/textdialog.h
+++ b/src/gui/textdialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GUI_GUILD_DIALOG_H
-#define GUI_GUILD_DIALOG_H
+#pragma once
#include "gui/widgets/window.h"
@@ -59,5 +58,3 @@ private:
TextField *mTextField;
gcn::Button *mOkButton;
};
-
-#endif
diff --git a/src/gui/textpopup.h b/src/gui/textpopup.h
index b1c6b2b3..db7d48e7 100644
--- a/src/gui/textpopup.h
+++ b/src/gui/textpopup.h
@@ -21,8 +21,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef TEXTPOPUP_H
-#define TEXTPOPUP_H
+#pragma once
#include "gui/widgets/popup.h"
@@ -51,5 +50,3 @@ class TextPopup : public Popup
gcn::Label *mText1;
gcn::Label *mText2;
};
-
-#endif // TEXTPOPUP_H
diff --git a/src/gui/tradewindow.cpp b/src/gui/tradewindow.cpp
index db4b6490..e24845b7 100644
--- a/src/gui/tradewindow.cpp
+++ b/src/gui/tradewindow.cpp
@@ -24,7 +24,6 @@
#include "event.h"
#include "inventory.h"
#include "item.h"
-#include "localplayer.h"
#include "playerinfo.h"
#include "units.h"
@@ -39,7 +38,6 @@
#include "gui/widgets/textfield.h"
#include "gui/widgets/layout.h"
-#include "net/inventoryhandler.h"
#include "net/net.h"
#include "net/tradehandler.h"
@@ -48,8 +46,6 @@
#include <guichan/font.hpp>
-#include <sstream>
-
#define CAPTION_PROPOSE _("Propose trade")
#define CAPTION_CONFIRMED _("Confirmed. Waiting...")
#define CAPTION_ACCEPT _("Agree trade")
@@ -125,9 +121,7 @@ TradeWindow::TradeWindow():
reset();
}
-TradeWindow::~TradeWindow()
-{
-}
+TradeWindow::~TradeWindow() = default;
void TradeWindow::setMoney(int amount)
{
@@ -138,7 +132,10 @@ void TradeWindow::setMoney(int amount)
void TradeWindow::addItem(int id, bool own, int quantity)
{
- (own ? mMyInventory : mPartnerInventory)->addItem(id, quantity);
+ if (own)
+ mMyInventory->addItem(id, quantity);
+ else
+ mPartnerInventory->addItem(id, quantity);
}
void TradeWindow::changeQuantity(int index, bool own, int quantity)
@@ -186,22 +183,15 @@ void TradeWindow::receivedOk(bool own)
}
}
-void TradeWindow::tradeItem(Item *item, int quantity)
-{
- Net::getTradeHandler()->addItem(item, quantity);
-}
-
void TradeWindow::valueChanged(const gcn::SelectionEvent &event)
{
- const Item *item;
-
/* If an item is selected in one container, make sure no item is selected
* in the other container.
*/
if (event.getSource() == mMyItemContainer &&
- (item = mMyItemContainer->getSelectedItem()))
+ mMyItemContainer->getSelectedItem())
mPartnerItemContainer->selectNone();
- else if ((item = mPartnerItemContainer->getSelectedItem()))
+ else if (mPartnerItemContainer->getSelectedItem())
mMyItemContainer->selectNone();
}
diff --git a/src/gui/tradewindow.h b/src/gui/tradewindow.h
index e9d8d4f1..85b2f97d 100644
--- a/src/gui/tradewindow.h
+++ b/src/gui/tradewindow.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TRADE_H
-#define TRADE_H
+#pragma once
#include "gui/widgets/window.h"
@@ -82,11 +81,6 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener
void receivedOk(bool own);
/**
- * Send trade packet.
- */
- void tradeItem(Item *item, int quantity);
-
- /**
* Updates the labels and makes sure only one item is selected in
* either my inventory or partner inventory.
*/
@@ -134,5 +128,3 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener
};
extern TradeWindow *tradeWindow;
-
-#endif
diff --git a/src/gui/truetypefont.cpp b/src/gui/truetypefont.cpp
index 30037f84..444641b5 100644
--- a/src/gui/truetypefont.cpp
+++ b/src/gui/truetypefont.cpp
@@ -56,16 +56,16 @@ bool operator==(SDL_Color lhs, SDL_Color rhs)
class TextChunk
{
public:
- TextChunk(const std::string &text, SDL_Color color)
+ TextChunk(const std::string &text)
: text(text)
- , color(color)
{}
void generate(TTF_Font *font)
{
+ // Always render in white, we'll use color modulation when rendering
SDL_Surface *surface = TTF_RenderUTF8_Blended(font,
getSafeUtf8String(text),
- color);
+ SDL_Color { 255, 255, 255, 255 });
if (!surface)
return;
@@ -77,7 +77,6 @@ public:
std::unique_ptr<Image> img;
const std::string text;
- const SDL_Color color;
};
std::list<TrueTypeFont*> TrueTypeFont::mFonts;
@@ -124,24 +123,13 @@ void TrueTypeFont::drawString(gcn::Graphics *graphics,
return;
auto *g = static_cast<Graphics *>(graphics);
- const gcn::Color col = g->getColor();
-
- /* The alpha value is ignored at image generation to avoid caching the
- * same text with different alpha values.
- */
- const SDL_Color color = {
- static_cast<Uint8>(col.r),
- static_cast<Uint8>(col.g),
- static_cast<Uint8>(col.b),
- 255
- };
bool found = false;
for (auto i = mCache.begin(); i != mCache.end(); ++i)
{
auto &chunk = *i;
- if (chunk.text == text && chunk.color == color)
+ if (chunk.text == text)
{
// Raise priority: move it to front
mCache.splice(mCache.begin(), mCache, i);
@@ -154,18 +142,17 @@ void TrueTypeFont::drawString(gcn::Graphics *graphics,
{
if (mCache.size() >= CACHE_SIZE)
mCache.pop_back();
- mCache.emplace_front(text, color);
+ mCache.emplace_front(text);
mCache.front().generate(mFont);
}
if (auto img = mCache.front().img.get())
{
- img->setAlpha(col.a / 255.0f);
g->drawRescaledImageF(img, 0, 0, x, y,
img->getWidth(),
img->getHeight(),
img->getWidth() / mScale,
- img->getHeight() / mScale);
+ img->getHeight() / mScale, true);
}
}
diff --git a/src/gui/truetypefont.h b/src/gui/truetypefont.h
index 9aa308b1..a479537d 100644
--- a/src/gui/truetypefont.h
+++ b/src/gui/truetypefont.h
@@ -20,8 +20,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TRUETYPEFONT_H
-#define TRUETYPEFONT_H
+#pragma once
#include <guichan/font.hpp>
@@ -82,5 +81,3 @@ class TrueTypeFont : public gcn::Font
static std::list<TrueTypeFont*> mFonts;
static float mScale;
};
-
-#endif
diff --git a/src/gui/unregisterdialog.h b/src/gui/unregisterdialog.h
index c82d7a78..0c94e0af 100644
--- a/src/gui/unregisterdialog.h
+++ b/src/gui/unregisterdialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef UNREGISTERDIALOG_H
-#define UNREGISTERDIALOG_H
+#pragma once
#include "gui/widgets/window.h"
@@ -57,5 +56,3 @@ class UnRegisterDialog : public Window, public gcn::ActionListener
LoginData *mLoginData;
};
-
-#endif
diff --git a/src/gui/updaterwindow.cpp b/src/gui/updaterwindow.cpp
index 772df725..5cfb45cd 100644
--- a/src/gui/updaterwindow.cpp
+++ b/src/gui/updaterwindow.cpp
@@ -46,8 +46,8 @@
#include <iostream>
#include <fstream>
-const std::string xmlUpdateFile = "resources.xml";
-const std::string txtUpdateFile = "resources2.txt";
+constexpr char xmlUpdateFile[] = "resources.xml";
+constexpr char txtUpdateFile[] = "resources2.txt";
/**
* Load the given file into a vector of updateFiles.
@@ -123,7 +123,6 @@ UpdaterWindow::UpdaterWindow(const std::string &updateHost,
Window(_("Updating...")),
mUpdateHost(updateHost),
mUpdatesDir(updatesDir),
- mCurrentFile("news.txt"),
mLoadUpdates(applyUpdates),
mLinkHandler(std::make_unique<ItemLinkHandler>(this))
{
@@ -141,7 +140,6 @@ UpdaterWindow::UpdaterWindow(const std::string &updateHost,
mPlayButton = new Button(_("Play"), "play", this);
mBrowserBox->setLinkHandler(mLinkHandler.get());
- mBrowserBox->setFrameSize(4);
mProgressBar->setSmoothProgress(false);
mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
mPlayButton->setEnabled(false);
@@ -161,40 +159,22 @@ UpdaterWindow::UpdaterWindow(const std::string &updateHost,
setVisible(true);
mCancelButton->requestFocus();
- // Try to download the updates list
- download();
+ startDownload("news.txt", true);
}
UpdaterWindow::~UpdaterWindow()
{
if (mLoadUpdates)
loadUpdates();
-
- if (mDownload)
- {
- mDownload->cancel();
-
- delete mDownload;
- mDownload = nullptr;
- }
- free(mMemoryBuffer);
-}
-
-void UpdaterWindow::setProgress(float progress)
-{
- // Do delayed progress bar update, since Guichan isn't thread-safe
- MutexLocker lock(&mDownloadMutex);
- mDownloadProgress = progress;
}
void UpdaterWindow::setLabel(const std::string &str)
{
- // Do delayed label text update, since Guichan isn't thread-safe
- MutexLocker lock(&mDownloadMutex);
- mNewLabelCaption = str;
+ mLabel->setCaption(str);
+ mLabel->adjustSize();
}
-void UpdaterWindow::enable()
+void UpdaterWindow::enablePlay()
{
mCancelButton->setEnabled(false);
mPlayButton->setEnabled(true);
@@ -204,20 +184,9 @@ void UpdaterWindow::enable()
void UpdaterWindow::action(const gcn::ActionEvent &event)
{
if (event.getId() == "cancel")
- {
- // Register the user cancel
- mUserCancel = true;
- // Skip the updating process
- if (mDownloadStatus != UPDATE_COMPLETE)
- {
- mDownload->cancel();
- mDownloadStatus = UPDATE_ERROR;
- }
- }
+ cancel();
else if (event.getId() == "play")
- {
- Client::setState(STATE_LOAD_DATA);
- }
+ play();
}
void UpdaterWindow::keyPressed(gcn::KeyEvent &keyEvent)
@@ -226,140 +195,63 @@ void UpdaterWindow::keyPressed(gcn::KeyEvent &keyEvent)
if (key.getValue() == Key::ESCAPE)
{
- action(gcn::ActionEvent(nullptr, mCancelButton->getActionEventId()));
- Client::setState(STATE_WORLD_SELECT);
+ if (!cancel())
+ {
+ mLoadUpdates = false;
+ Client::setState(STATE_WORLD_SELECT);
+ }
}
else if (key.getValue() == Key::ENTER)
{
- if (mDownloadStatus == UPDATE_COMPLETE ||
- mDownloadStatus == UPDATE_ERROR)
- {
- action(gcn::ActionEvent(nullptr, mPlayButton->getActionEventId()));
- }
- else
- {
- action(gcn::ActionEvent(nullptr, mCancelButton->getActionEventId()));
- }
+ play();
}
}
-void UpdaterWindow::loadNews()
+bool UpdaterWindow::cancel()
{
- if (!mMemoryBuffer)
+ // Skip the updating process
+ if (mDialogState != DialogState::Done)
{
- logger->log("Couldn't load news");
- return;
- }
-
- // Reallocate and include terminating 0 character
- mMemoryBuffer = (char*)realloc(mMemoryBuffer, mDownloadedBytes + 1);
- mMemoryBuffer[mDownloadedBytes] = '\0';
-
- mBrowserBox->clearRows();
-
- // Tokenize and add each line separately
- char *line = strtok(mMemoryBuffer, "\n");
- while (line)
- {
- mBrowserBox->addRow(line);
- line = strtok(nullptr, "\n");
+ mDownload->cancel();
+ return true;
}
-
- // Free the memory buffer now that we don't need it anymore
- free(mMemoryBuffer);
- mMemoryBuffer = nullptr;
-
- mScrollArea->setVerticalScrollAmount(0);
+ return false;
}
-int UpdaterWindow::updateProgress(void *ptr, DownloadStatus status,
- size_t dt, size_t dn)
+void UpdaterWindow::play()
{
- auto *uw = reinterpret_cast<UpdaterWindow *>(ptr);
-
- if (status == DOWNLOAD_STATUS_COMPLETE)
- {
- uw->mDownloadComplete = true;
- }
- else if (status == DOWNLOAD_STATUS_ERROR ||
- status == DOWNLOAD_STATUS_CANCELLED)
- {
- uw->mDownloadStatus = UPDATE_ERROR;
- }
-
- float progress = (float) dn / dt;
-
- if (progress != progress)
- progress = 0.0f; // check for NaN
- if (progress < 0.0f)
- progress = 0.0f; // no idea how this could ever happen, but why not check for it anyway.
- if (progress > 1.0f)
- progress = 1.0f;
-
- uw->setLabel(
- uw->mCurrentFile + " (" + toString((int) (progress * 100)) + "%)");
- uw->setProgress(progress);
-
- if (Client::getState() != STATE_UPDATE || uw->mDownloadStatus == UPDATE_ERROR)
- {
- // If the action was canceled return an error code to stop the mThread
- return -1;
- }
-
- return 0;
+ if (mPlayButton->isEnabled())
+ Client::setState(STATE_LOAD_DATA);
}
-size_t UpdaterWindow::memoryWrite(void *ptr, size_t size, size_t nmemb, void *stream)
+void UpdaterWindow::loadNews()
{
- auto *uw = reinterpret_cast<UpdaterWindow *>(stream);
- size_t totalMem = size * nmemb;
- uw->mMemoryBuffer = (char*) realloc(uw->mMemoryBuffer,
- uw->mDownloadedBytes + totalMem);
- if (uw->mMemoryBuffer)
- {
- memcpy(&(uw->mMemoryBuffer[uw->mDownloadedBytes]), ptr, totalMem);
- uw->mDownloadedBytes += totalMem;
- }
+ mBrowserBox->clearRows();
+ mBrowserBox->addRows(mDownload->getBuffer());
- return totalMem;
+ mScrollArea->setVerticalScrollAmount(0);
}
-void UpdaterWindow::download()
+void UpdaterWindow::startDownload(const std::string &fileName,
+ bool storeInMemory,
+ std::optional<unsigned long> adler32)
{
- mDownload = new Net::Download(this, mUpdateHost + "/" + mCurrentFile,
- updateProgress);
+ mDownload = std::make_unique<Net::Download>(mUpdateHost + "/" + fileName);
+ mCurrentFile = fileName;
- if (mStoreInMemory)
- {
- mDownload->setWriteFunction(UpdaterWindow::memoryWrite);
- }
+ if (storeInMemory)
+ mDownload->setUseBuffer();
else
- {
- if (mDownloadStatus == UPDATE_RESOURCES)
- {
- mDownload->setFile(mUpdatesDir + "/" + mCurrentFile,
- mCurrentChecksum);
- }
- else
- {
- mDownload->setFile(mUpdatesDir + "/" + mCurrentFile);
- }
- }
+ mDownload->setFile(mUpdatesDir + "/" + fileName, adler32);
- if (mDownloadStatus != UPDATE_RESOURCES)
+ if (mDialogState != DialogState::DownloadResources)
mDownload->noCache();
- setLabel(mCurrentFile + " (0%)");
- mDownloadComplete = false;
-
- // TODO: check return
mDownload->start();
}
void UpdaterWindow::loadUpdates()
{
- ResourceManager *resman = ResourceManager::getInstance();
-
if (mUpdateFiles.empty())
{
// updates not downloaded
@@ -367,142 +259,144 @@ void UpdaterWindow::loadUpdates()
if (mUpdateFiles.empty())
{
logger->log("Warning this server does not have a"
- " %s file falling back to %s", xmlUpdateFile.c_str(),
- txtUpdateFile.c_str());
+ " %s file falling back to %s", xmlUpdateFile,
+ txtUpdateFile);
mUpdateFiles = loadTxtFile(mUpdatesDir + "/" + txtUpdateFile);
}
}
for (const UpdateFile &file : mUpdateFiles)
- {
- resman->addToSearchPath(mUpdatesDir + "/" + file.name, false);
- }
+ ResourceManager::addToSearchPath(mUpdatesDir + "/" + file.name, false);
}
void UpdaterWindow::logic()
{
- const std::string xmlUpdateFile = "resources.xml";
- const std::string txtUpdateFile = "resources2.txt";
+ Window::logic();
- // Update Scroll logic
- mScrollArea->logic();
+ if (mDialogState == DialogState::Done)
+ return;
- // Synchronize label caption when necessary
- {
- MutexLocker lock(&mDownloadMutex);
+ const auto state = mDownload->getState();
+ float progress = 0.0f;
- if (mLabel->getCaption() != mNewLabelCaption)
- {
- mLabel->setCaption(mNewLabelCaption);
- mLabel->adjustSize();
- }
+ switch (state.status) {
+ case DownloadStatus::InProgress: {
+ setLabel(mCurrentFile + " (" + toString((int) (state.progress * 100)) + "%)");
+ progress = state.progress;
+ break;
+ }
+
+ case DownloadStatus::Canceled:
+ mDialogState = DialogState::Done;
+
+ enablePlay();
+ setLabel(_("Download canceled"));
+ break;
+
+ case DownloadStatus::Error: {
+ mDialogState = DialogState::Done;
- mProgressBar->setProgress(mDownloadProgress);
+ std::string error = "##1";
+ error += mDownload->getError();
+ error += "\n\n##1";
+ error += _("The update process is incomplete. "
+ "It is strongly recommended that you try again later.");
+ mBrowserBox->addRows(error);
+
+ int maxScroll = mScrollArea->getVerticalMaxScroll();
+ mScrollArea->setVerticalScrollAmount(maxScroll);
+
+ enablePlay();
+ setLabel(_("Error while downloading"));
+ break;
}
- switch (mDownloadStatus)
+ case DownloadStatus::Complete:
+ downloadCompleted();
+ break;
+ }
+
+ mProgressBar->setProgress(progress);
+}
+
+void UpdaterWindow::downloadCompleted()
+{
+ switch (mDialogState)
{
- case UPDATE_ERROR:
- // TODO: Only send complete sentences to gettext
- mBrowserBox->addRow(std::string());
- mBrowserBox->addRow(_("##1 The update process is incomplete."));
- // TRANSLATORS: Continues "you try again later.".
- mBrowserBox->addRow(_("##1 It is strongly recommended that"));
- // TRANSLATORS: Begins "It is strongly recommended that".
- mBrowserBox->addRow(_("##1 you try again later."));
-
- mBrowserBox->addRow(mDownload->getError());
- mScrollArea->setVerticalScrollAmount(
- mScrollArea->getVerticalMaxScroll());
- mDownloadStatus = UPDATE_COMPLETE;
- break;
- case UPDATE_NEWS:
- if (mDownloadComplete)
- {
- // Parse current memory buffer as news and dispose of the data
- loadNews();
+ case DialogState::DownloadNews:
+ loadNews();
- mCurrentFile = xmlUpdateFile;
- mStoreInMemory = false;
- mDownloadStatus = UPDATE_LIST;
- download(); // download() changes mDownloadComplete to false
- }
- break;
- case UPDATE_LIST:
- if (mDownloadComplete)
+ mDialogState = DialogState::DownloadList;
+ startDownload(xmlUpdateFile, false);
+ break;
+
+ case DialogState::DownloadList:
+ if (mCurrentFile == xmlUpdateFile)
+ {
+ mUpdateFiles = loadXMLFile(mUpdatesDir + "/" + xmlUpdateFile);
+ if (mUpdateFiles.empty())
{
- if (mCurrentFile == xmlUpdateFile)
- {
- mUpdateFiles = loadXMLFile(mUpdatesDir + "/" + xmlUpdateFile);
- if (mUpdateFiles.empty())
- {
- logger->log("Warning this server does not have a %s"
- " file falling back to %s",
- xmlUpdateFile.c_str(), txtUpdateFile.c_str());
-
- // If the resources.xml file fails, fall back onto a older version
- mCurrentFile = txtUpdateFile;
- mStoreInMemory = false;
- mDownloadStatus = UPDATE_LIST;
- download();
- break;
- }
- }
- else if (mCurrentFile == txtUpdateFile)
- {
- mUpdateFiles = loadTxtFile(mUpdatesDir + "/" + txtUpdateFile);
- }
- mStoreInMemory = false;
- mDownloadStatus = UPDATE_RESOURCES;
+ logger->log("Warning this server does not have a %s"
+ " file falling back to %s",
+ xmlUpdateFile, txtUpdateFile);
+
+ // If the resources.xml file fails, fall back onto a older version
+ mDialogState = DialogState::DownloadList;
+ startDownload(txtUpdateFile, false);
+ break;
}
- break;
- case UPDATE_RESOURCES:
- if (mDownloadComplete)
+ }
+ else if (mCurrentFile == txtUpdateFile)
+ {
+ mUpdateFiles = loadTxtFile(mUpdatesDir + "/" + txtUpdateFile);
+ }
+
+ mDialogState = DialogState::DownloadResources;
+ break;
+
+ case DialogState::DownloadResources:
+ if (mUpdateIndex < mUpdateFiles.size())
+ {
+ const UpdateFile &thisFile = mUpdateFiles[mUpdateIndex];
+ if (!thisFile.required)
{
- if (mUpdateIndex < mUpdateFiles.size())
+ if (!(thisFile.type == "music" && config.downloadMusic))
{
- const UpdateFile &thisFile = mUpdateFiles[mUpdateIndex];
- if (!thisFile.required)
- {
- if (!(thisFile.type == "music" && config.downloadMusic))
- {
- mUpdateIndex++;
- break;
- }
- }
- mCurrentFile = thisFile.name;
- std::stringstream ss(thisFile.hash);
- ss >> std::hex >> mCurrentChecksum;
-
- std::string filename = mUpdatesDir + "/" + mCurrentFile;
- FILE *file = fopen(filename.c_str(), "r+b");
-
- if (!file || Net::Download::fadler32(file) != mCurrentChecksum)
- {
- if (file)
- fclose(file);
- download();
- }
- else
- {
- fclose(file);
- logger->log("%s already here", mCurrentFile.c_str());
- }
mUpdateIndex++;
- }
- else
- {
- // Download of updates completed
- mDownloadStatus = UPDATE_COMPLETE;
+ break;
}
}
- break;
- case UPDATE_COMPLETE:
- enable();
+
+ unsigned long checksum;
+ std::stringstream ss(thisFile.hash);
+ ss >> std::hex >> checksum;
+
+ std::string filename = mUpdatesDir + "/" + thisFile.name;
+ FILE *file = fopen(filename.c_str(), "r+b");
+
+ if (!file || Net::Download::fadler32(file) != checksum)
+ {
+ if (file)
+ fclose(file);
+ startDownload(thisFile.name, false, checksum);
+ }
+ else
+ {
+ fclose(file);
+ logger->log("%s already here", thisFile.name.c_str());
+ }
+ mUpdateIndex++;
+ }
+ else
+ {
+ // Download of updates completed
+ mDialogState = DialogState::Done;
+ enablePlay();
setLabel(_("Completed"));
- mDownloadStatus = UPDATE_IDLE;
- break;
- case UPDATE_IDLE:
- break;
+ }
+ break;
+
+ case DialogState::Done:
+ break;
}
}
diff --git a/src/gui/updaterwindow.h b/src/gui/updaterwindow.h
index 6ea1d754..dd1400ba 100644
--- a/src/gui/updaterwindow.h
+++ b/src/gui/updaterwindow.h
@@ -19,15 +19,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef UPDATERWINDOW_H
-#define UPDATERWINDOW_H
+#pragma once
#include "gui/widgets/window.h"
#include "net/download.h"
-#include "utils/mutex.h"
-
#include <guichan/actionlistener.hpp>
#include <guichan/keylistener.hpp>
@@ -65,7 +62,7 @@ class UpdaterWindow : public Window, public gcn::ActionListener,
* @param updateHost Host where to get the updated files.
* @param updatesDir Directory where to store updates (should be absolute
* and already created).
- * @param applyUpdates If true, the update window will pass the updates to teh
+ * @param applyUpdates If true, the update window will pass the updates to the
* resource manager
*/
UpdaterWindow(const std::string &updateHost,
@@ -74,27 +71,6 @@ class UpdaterWindow : public Window, public gcn::ActionListener,
~UpdaterWindow() override;
- /**
- * Set's progress bar status
- */
- void setProgress(float progress);
-
- /**
- * Set's label above progress
- */
- void setLabel(const std::string &);
-
- /**
- * Enables play button
- */
- void enable();
-
- /**
- * Loads and display news. Assumes the news file contents have been loaded
- * into the memory buffer.
- */
- void loadNews();
-
void action(const gcn::ActionEvent &event) override;
void keyPressed(gcn::KeyEvent &keyEvent) override;
@@ -102,38 +78,38 @@ class UpdaterWindow : public Window, public gcn::ActionListener,
void logic() override;
private:
- void download();
+ bool cancel();
+ void play();
- /**
- * Loads the updates this window has gotten into the resource manager
- */
- void loadUpdates();
+ void setLabel(const std::string &);
+ void enablePlay();
+ void startDownload(const std::string &fileName,
+ bool storeInMemory,
+ std::optional<unsigned long> adler32 = {});
+ void downloadCompleted();
/**
- * A download callback for progress updates.
+ * Loads and display news. Assumes the news file contents have been loaded
+ * into the memory buffer.
*/
- static int updateProgress(void *ptr, DownloadStatus status,
- size_t dt, size_t dn);
+ void loadNews();
/**
- * A libcurl callback for writing to memory.
+ * Loads the updates this window has gotten into the resource manager
*/
- static size_t memoryWrite(void *ptr, size_t size, size_t nmemb,
- void *stream);
+ void loadUpdates();
- enum UpdateDownloadStatus
+ enum class DialogState
{
- UPDATE_ERROR,
- UPDATE_IDLE,
- UPDATE_LIST,
- UPDATE_COMPLETE,
- UPDATE_NEWS,
- UPDATE_RESOURCES
+ DownloadNews,
+ DownloadList,
+ DownloadResources,
+ Done,
};
/** Status of the current download. */
- UpdateDownloadStatus mDownloadStatus = UPDATE_NEWS;
+ DialogState mDialogState = DialogState::DownloadNews;
/** Host where we get the updated files. */
std::string mUpdateHost;
@@ -144,35 +120,8 @@ private:
/** The file currently downloading. */
std::string mCurrentFile;
- /** The new label caption to be set in the logic method. */
- std::string mNewLabelCaption;
-
- /** The new progress value to be set in the logic method. */
- float mDownloadProgress = 0.0f;
-
- /** The mutex used to guard access to mNewLabelCaption and mDownloadProgress. */
- Mutex mDownloadMutex;
-
- /** The Adler32 checksum of the file currently downloading. */
- unsigned long mCurrentChecksum = 0;
-
- /** A flag to indicate whether to use a memory buffer or a regular file. */
- bool mStoreInMemory = true;
-
- /** Flag that show if current download is complete. */
- bool mDownloadComplete = true;
-
- /** Flag that show if the user has canceled the update. */
- bool mUserCancel = false;
-
- /** Byte count currently downloaded in mMemoryBuffer. */
- int mDownloadedBytes = 0;
-
- /** Buffer for files downloaded to memory. */
- char *mMemoryBuffer = nullptr;
-
/** Download handle. */
- Net::Download *mDownload = nullptr;
+ std::unique_ptr<Net::Download> mDownload;
/** List of files to download. */
std::vector<UpdateFile> mUpdateFiles;
@@ -191,5 +140,3 @@ private:
ScrollArea *mScrollArea; /**< Used to scroll news box. */
std::unique_ptr<LinkHandler> mLinkHandler;
};
-
-#endif
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index 558ce0e6..9e529063 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -32,7 +32,6 @@
#include "textmanager.h"
#include "gui/gui.h"
-#include "gui/ministatuswindow.h"
#include "gui/popupmenu.h"
#include "gui/beingpopup.h"
@@ -237,9 +236,6 @@ void Viewport::draw(gcn::Graphics *gcnGraphics)
}
}
- if (miniStatusWindow)
- miniStatusWindow->drawIcons(graphics);
-
// Draw contained widgets
WindowContainer::draw(gcnGraphics);
}
@@ -309,10 +305,10 @@ void Viewport::_drawDebugPath(Graphics *graphics)
unsigned char walkMask;
switch (Net::getNetworkType())
{
- case ServerType::TMWATHENA:
+ case ServerType::TmwAthena:
walkMask = Map::BLOCKMASK_WALL | Map::BLOCKMASK_CHARACTER;
break;
- case ServerType::MANASERV:
+ case ServerType::ManaServ:
default:
walkMask = Map::BLOCKMASK_WALL;
break;
@@ -579,18 +575,18 @@ void Viewport::updateCursorType()
gui->setCursorType(mHoverBeing->getHoverCursor());
break;
default:
- gui->setCursorType(Cursor::POINTER);
+ gui->setCursorType(Cursor::Pointer);
break;
}
// Item mouseover
}
else if (mHoverItem)
{
- gui->setCursorType(Cursor::PICKUP);
+ gui->setCursorType(Cursor::PickUp);
}
else
{
- gui->setCursorType(Cursor::POINTER);
+ gui->setCursorType(Cursor::Pointer);
}
}
diff --git a/src/gui/viewport.h b/src/gui/viewport.h
index b69a73b6..bf73f8ca 100644
--- a/src/gui/viewport.h
+++ b/src/gui/viewport.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef VIEWPORT_H
-#define VIEWPORT_H
+#pragma once
#include "eventlistener.h"
#include "position.h"
@@ -221,5 +220,3 @@ class Viewport : public WindowContainer, public gcn::MouseListener,
};
extern Viewport *viewport; /**< The viewport. */
-
-#endif
diff --git a/src/gui/widgets/avatarlistbox.cpp b/src/gui/widgets/avatarlistbox.cpp
index ec3327b2..4a806d04 100644
--- a/src/gui/widgets/avatarlistbox.cpp
+++ b/src/gui/widgets/avatarlistbox.cpp
@@ -32,33 +32,21 @@
#include <guichan/font.hpp>
-int AvatarListBox::instances = 0;
-Image *AvatarListBox::onlineIcon = nullptr;
-Image *AvatarListBox::offlineIcon = nullptr;
-
AvatarListBox::AvatarListBox(AvatarListModel *model):
ListBox(model)
{
- instances++;
-
- if (instances == 1)
- {
- onlineIcon = Theme::getImageFromTheme("circle-green.png");
- offlineIcon = Theme::getImageFromTheme("circle-gray.png");
- }
-
setWidth(200);
}
-AvatarListBox::~AvatarListBox()
+unsigned int AvatarListBox::getRowHeight() const
{
- instances--;
+ auto rowHeight = ListBox::getRowHeight();
- if (instances == 0)
- {
- onlineIcon->decRef();
- offlineIcon->decRef();
- }
+ auto theme = gui->getTheme();
+ if (auto onlineIcon = theme->getIcon("online"))
+ rowHeight = std::max<unsigned>(rowHeight, onlineIcon->getHeight() + 2);
+
+ return rowHeight;
}
void AvatarListBox::draw(gcn::Graphics *gcnGraphics)
@@ -66,34 +54,42 @@ void AvatarListBox::draw(gcn::Graphics *gcnGraphics)
if (!mListModel)
return;
- auto* model = static_cast<AvatarListModel*>(mListModel);
+ auto *model = static_cast<AvatarListModel *>(mListModel);
+ auto *graphics = static_cast<Graphics *>(gcnGraphics);
- updateAlpha();
-
- auto *graphics = static_cast<Graphics*>(gcnGraphics);
-
- graphics->setColor(Theme::getThemeColor(Theme::HIGHLIGHT,
- (int) (mAlpha * 255.0f)));
graphics->setFont(getFont());
- const int fontHeight = getFont()->getHeight();
+ const int rowHeight = getRowHeight();
// Draw filled rectangle around the selected list element
if (mSelected >= 0)
- graphics->fillRectangle(gcn::Rectangle(0, fontHeight * mSelected,
- getWidth(), fontHeight));
+ {
+ auto highlightColor = Theme::getThemeColor(Theme::HIGHLIGHT);
+ highlightColor.a = gui->getTheme()->getGuiAlpha();
+ graphics->setColor(highlightColor);
+ graphics->fillRectangle(gcn::Rectangle(0, rowHeight * mSelected,
+ getWidth(), rowHeight));
+ }
+
+ auto theme = gui->getTheme();
+ auto onlineIcon = theme->getIcon("online");
+ auto offlineIcon = theme->getIcon("offline");
// Draw the list elements
graphics->setColor(Theme::getThemeColor(Theme::TEXT));
for (int i = 0, y = 0;
i < model->getNumberOfElements();
- ++i, y += fontHeight)
+ ++i, y += rowHeight)
{
Avatar *a = model->getAvatarAt(i);
+ int x = 1;
+
// Draw online status
- Image *icon = a->getOnline() ? onlineIcon : offlineIcon;
- if (icon)
- graphics->drawImage(icon, 2, y + 1);
+ if (const Image *icon = a->getOnline() ? onlineIcon : offlineIcon)
+ {
+ graphics->drawImage(icon, x, y + (rowHeight - icon->getHeight()) / 2);
+ x += icon->getWidth() + 4;
+ }
if (a->getDisplayBold())
graphics->setFont(boldFont);
@@ -111,7 +107,7 @@ void AvatarListBox::draw(gcn::Graphics *gcnGraphics)
}
// Draw Name
- graphics->drawText(text, 15, y);
+ graphics->drawText(text, x, y);
if (a->getDisplayBold())
graphics->setFont(getFont());
diff --git a/src/gui/widgets/avatarlistbox.h b/src/gui/widgets/avatarlistbox.h
index 7ee36d1e..1f51935f 100644
--- a/src/gui/widgets/avatarlistbox.h
+++ b/src/gui/widgets/avatarlistbox.h
@@ -18,8 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GUI_GUILDLISTBOX_H
-#define GUI_GUILDLISTBOX_H
+#pragma once
#include "avatar.h"
@@ -43,7 +42,7 @@ class AvatarListBox : public ListBox
public:
AvatarListBox(AvatarListModel *model);
- ~AvatarListBox() override;
+ unsigned int getRowHeight() const override;
/**
* Draws the list box.
@@ -51,11 +50,4 @@ public:
void draw(gcn::Graphics *gcnGraphics) override;
void mousePressed(gcn::MouseEvent &event) override;
-
-private:
- static int instances;
- static Image *onlineIcon;
- static Image *offlineIcon;
};
-
-#endif
diff --git a/src/gui/widgets/browserbox.cpp b/src/gui/widgets/browserbox.cpp
index 9eee9448..4fe85ae5 100644
--- a/src/gui/widgets/browserbox.cpp
+++ b/src/gui/widgets/browserbox.cpp
@@ -22,6 +22,9 @@
#include "gui/widgets/browserbox.h"
+#include "keyboardconfig.h"
+#include "textrenderer.h"
+
#include "gui/gui.h"
#include "gui/truetypefont.h"
#include "gui/widgets/linkhandler.h"
@@ -38,9 +41,44 @@
#include <algorithm>
+/**
+ * Check for key replacements in format "###key;"
+ */
+static void replaceKeys(std::string &text)
+{
+ auto keyStart = text.find("###");
+
+ while (keyStart != std::string::npos)
+ {
+ const auto keyEnd = text.find(";", keyStart + 3);
+ if (keyEnd == std::string::npos)
+ break;
+
+ std::string_view key(text.data() + keyStart + 3, keyEnd - keyStart - 3);
+
+ // Remove "key" prefix
+ if (key.size() > 3 && key.substr(0, 3) == "key")
+ key.remove_prefix(3);
+
+ const auto keyName = keyboard.getKeyName(key);
+ if (!keyName.empty())
+ {
+ text.replace(keyStart, keyEnd - keyStart + 1, keyName);
+ keyStart = text.find("###", keyStart + keyName.size());
+ }
+ else
+ {
+ keyStart = text.find("###", keyEnd + 1);
+ }
+ }
+}
+
+
struct LayoutContext
{
- LayoutContext(gcn::Font *font);
+ LayoutContext(gcn::Font *font, const Palette &palette);
+
+ LinePart linePart(int x, std::string text);
int y = 0;
gcn::Font *font;
@@ -48,23 +86,39 @@ struct LayoutContext
const int minusWidth;
const int tildeWidth;
int lineHeight;
- gcn::Color selColor;
const gcn::Color textColor;
+ const std::optional<gcn::Color> textOutlineColor;
+ gcn::Color color;
+ std::optional<gcn::Color> outlineColor;
};
-LayoutContext::LayoutContext(gcn::Font *font)
+inline LayoutContext::LayoutContext(gcn::Font *font, const Palette &palette)
: font(font)
, fontHeight(font->getHeight())
, minusWidth(font->getWidth("-"))
, tildeWidth(font->getWidth("~"))
, lineHeight(fontHeight)
- , selColor(Theme::getThemeColor(Theme::TEXT))
- , textColor(Theme::getThemeColor(Theme::TEXT))
+ , textColor(palette.getColor(Theme::TEXT))
+ , textOutlineColor(palette.getOutlineColor(Theme::TEXT))
+ , color(textColor)
+ , outlineColor(textOutlineColor)
{
if (auto *trueTypeFont = dynamic_cast<const TrueTypeFont*>(font))
lineHeight = trueTypeFont->getLineHeight();
}
+inline LinePart LayoutContext::linePart(int x, std::string text)
+{
+ return {
+ x,
+ y,
+ color,
+ outlineColor,
+ std::move(text),
+ font
+ };
+}
+
BrowserBox::BrowserBox(Mode mode):
mMode(mode)
@@ -75,28 +129,38 @@ BrowserBox::BrowserBox(Mode mode):
BrowserBox::~BrowserBox() = default;
-void BrowserBox::addRow(const std::string &row)
+void BrowserBox::addRows(std::string_view rows)
+{
+ std::string_view::size_type start = 0;
+ std::string_view::size_type end = 0;
+ while (end != std::string::npos)
+ {
+ end = rows.find('\n', start);
+ addRow(rows.substr(start, end - start));
+ start = end + 1;
+ }
+}
+
+void BrowserBox::addRow(std::string_view row)
{
TextRow &newRow = mTextRows.emplace_back();
// Use links and user defined colors
if (mUseLinksAndUserColors)
{
- std::string tmp = row;
-
// Check for links in format "@@link|Caption@@"
- auto idx1 = tmp.find("@@");
- while (idx1 != std::string::npos)
+ auto linkStart = row.find("@@");
+ while (linkStart != std::string::npos)
{
- const auto idx2 = tmp.find("|", idx1);
- const auto idx3 = tmp.find("@@", idx2);
+ const auto linkSep = row.find("|", linkStart);
+ const auto linkEnd = row.find("@@", linkSep);
- if (idx2 == std::string::npos || idx3 == std::string::npos)
+ if (linkSep == std::string::npos || linkEnd == std::string::npos)
break;
BrowserLink &link = newRow.links.emplace_back();
- link.link = tmp.substr(idx1 + 2, idx2 - (idx1 + 2));
- link.caption = tmp.substr(idx2 + 1, idx3 - (idx2 + 1));
+ link.link = row.substr(linkStart + 2, linkSep - (linkStart + 2));
+ link.caption = row.substr(linkSep + 1, linkEnd - (linkSep + 1));
if (link.caption.empty())
{
@@ -107,18 +171,18 @@ void BrowserBox::addRow(const std::string &row)
link.caption = link.link;
}
- newRow.text += tmp.substr(0, idx1);
+ newRow.text += row.substr(0, linkStart);
newRow.text += "##<" + link.caption;
- tmp.erase(0, idx3 + 2);
- if (!tmp.empty())
+ row = row.substr(linkEnd + 2);
+ if (!row.empty())
{
newRow.text += "##>";
}
- idx1 = tmp.find("@@");
+ linkStart = row.find("@@");
}
- newRow.text += tmp;
+ newRow.text += row;
}
// Don't use links and user defined colors
else
@@ -126,8 +190,11 @@ void BrowserBox::addRow(const std::string &row)
newRow.text = row;
}
+ if (mEnableKeys)
+ replaceKeys(newRow.text);
+
// Layout the newly added row
- LayoutContext context(getFont());
+ LayoutContext context(getFont(), gui->getTheme()->getPalette(mPalette));
context.y = getHeight();
layoutTextRow(newRow, context);
@@ -175,14 +242,14 @@ void BrowserBox::mousePressed(gcn::MouseEvent &event)
if (mHoveredLink) {
mLinkHandler->handleLink(mHoveredLink->link);
- gui->setCursorType(Cursor::POINTER);
+ gui->setCursorType(Cursor::Pointer);
}
}
void BrowserBox::mouseMoved(gcn::MouseEvent &event)
{
updateHoveredLink(event.getX(), event.getY());
- gui->setCursorType(mHoveredLink ? Cursor::HAND : Cursor::POINTER);
+ gui->setCursorType(mHoveredLink ? Cursor::Hand : Cursor::Pointer);
event.consume(); // Suppress mouse cursor change by parent
}
@@ -204,19 +271,20 @@ void BrowserBox::draw(gcn::Graphics *graphics)
if (mHoveredLink)
{
+ auto &palette = gui->getTheme()->getPalette(mPalette);
auto &link = *mHoveredLink;
const gcn::Rectangle &rect = link.rect;
if (mHighlightMode & BACKGROUND)
{
- graphics->setColor(Theme::getThemeColor(Theme::HIGHLIGHT));
+ graphics->setColor(palette.getColor(Theme::HIGHLIGHT));
graphics->fillRectangle(rect);
}
if (mHighlightMode & UNDERLINE)
{
- graphics->setColor(Theme::getThemeColor(Theme::HYPERLINK));
+ graphics->setColor(palette.getColor(Theme::HYPERLINK));
graphics->drawLine(rect.x,
rect.y + rect.height,
rect.x + rect.width,
@@ -233,34 +301,16 @@ void BrowserBox::draw(gcn::Graphics *graphics)
if (part.y > yEnd)
return;
- auto font = part.font;
-
- // Handle text shadows
- if (mShadows)
- {
- graphics->setColor(Theme::getThemeColor(Theme::SHADOW,
- part.color.a / 2));
-
- if (mOutline)
- font->drawString(graphics, part.text, part.x + 2, part.y + 2);
- else
- font->drawString(graphics, part.text, part.x + 1, part.y + 1);
- }
-
- if (mOutline)
- {
- // Text outline
- graphics->setColor(Theme::getThemeColor(Theme::OUTLINE,
- part.color.a / 4));
- font->drawString(graphics, part.text, part.x + 1, part.y);
- font->drawString(graphics, part.text, part.x - 1, part.y);
- font->drawString(graphics, part.text, part.x, part.y + 1);
- font->drawString(graphics, part.text, part.x, part.y - 1);
- }
-
- // the main text
- graphics->setColor(part.color);
- font->drawString(graphics, part.text, part.x, part.y);
+ TextRenderer::renderText(graphics,
+ part.text,
+ part.x,
+ part.y,
+ Graphics::LEFT,
+ part.color,
+ part.font,
+ part.outlineColor.has_value() || mOutline,
+ mShadows,
+ part.outlineColor);
}
}
}
@@ -270,13 +320,13 @@ void BrowserBox::draw(gcn::Graphics *graphics)
*/
void BrowserBox::relayoutText()
{
- LayoutContext context(getFont());
+ LayoutContext context(getFont(), gui->getTheme()->getPalette(mPalette));
for (auto &row : mTextRows)
layoutTextRow(row, context);
mLastLayoutWidth = getWidth();
- mLayoutTimer.set(100);
+ mLayoutTimer.set(33);
setHeight(context.y);
}
@@ -288,7 +338,8 @@ void BrowserBox::layoutTextRow(TextRow &row, LayoutContext &context)
{
// each line starts with normal font in default color
context.font = getFont();
- context.selColor = context.textColor;
+ context.color = context.textColor;
+ context.outlineColor = context.textOutlineColor;
const int startY = context.y;
row.parts.clear();
@@ -301,15 +352,7 @@ void BrowserBox::layoutTextRow(TextRow &row, LayoutContext &context)
if (startsWith(row.text, "---"))
{
for (x = 0; x < getWidth(); x += context.minusWidth - 1)
- {
- row.parts.push_back(LinePart {
- x,
- context.y,
- context.selColor,
- "-",
- context.font
- });
- }
+ row.parts.push_back(context.linePart(x, "-"));
context.y += row.height;
@@ -318,7 +361,9 @@ void BrowserBox::layoutTextRow(TextRow &row, LayoutContext &context)
return;
}
- gcn::Color prevColor = context.selColor;
+ auto &palette = gui->getTheme()->getPalette(mPalette);
+ auto prevColor = context.color;
+ auto prevOutlineColor = context.outlineColor;
// TODO: Check if we must take texture size limits into account here
// TODO: Check if some of the O(n) calls can be removed
@@ -342,44 +387,38 @@ void BrowserBox::layoutTextRow(TextRow &row, LayoutContext &context)
const char c = row.text.at(start + 2);
start += 3;
- bool valid;
- const gcn::Color &col = Theme::getThemeColor(c, valid);
-
- if (c == '>')
- {
- context.selColor = prevColor;
- }
- else if (c == '<')
+ switch (c)
{
- prevColor = context.selColor;
- context.selColor = col;
- }
- else if (c == 'B')
- {
- context.font = boldFont;
- }
- else if (c == 'b')
- {
- context.font = getFont();
- }
- else if (valid)
- {
- context.selColor = col;
- }
- else switch (c)
- {
- case '1': context.selColor = RED; break;
- case '2': context.selColor = GREEN; break;
- case '3': context.selColor = BLUE; break;
- case '4': context.selColor = ORANGE; break;
- case '5': context.selColor = YELLOW; break;
- case '6': context.selColor = PINK; break;
- case '7': context.selColor = PURPLE; break;
- case '8': context.selColor = GRAY; break;
- case '9': context.selColor = BROWN; break;
- case '0':
- default:
- context.selColor = context.textColor;
+ case '>':
+ context.color = prevColor;
+ context.outlineColor = prevOutlineColor;
+ break;
+ case '<':
+ prevColor = context.color;
+ prevOutlineColor = context.outlineColor;
+ context.color = palette.getColor(Theme::HYPERLINK);
+ context.outlineColor = palette.getOutlineColor(Theme::HYPERLINK);
+ break;
+ case 'B':
+ context.font = boldFont;
+ break;
+ case 'b':
+ context.font = getFont();
+ break;
+ default: {
+ const auto colorId = Theme::getColorIdForChar(c);
+ if (colorId)
+ {
+ context.color = palette.getColor(*colorId);
+ context.outlineColor = palette.getOutlineColor(*colorId);
+ }
+ else
+ {
+ context.color = context.textColor;
+ context.outlineColor = context.textOutlineColor;
+ }
+ break;
+ }
}
// Update the position of the links
@@ -452,7 +491,8 @@ void BrowserBox::layoutTextRow(TextRow &row, LayoutContext &context)
row.parts.push_back(LinePart {
getWidth() - context.tildeWidth,
context.y,
- context.selColor,
+ context.color,
+ context.outlineColor,
"~",
getFont()
});
@@ -466,14 +506,7 @@ void BrowserBox::layoutTextRow(TextRow &row, LayoutContext &context)
wrapped = true;
}
- row.parts.push_back(LinePart {
- x,
- context.y,
- context.selColor,
- std::move(part),
- context.font
- });
-
+ row.parts.push_back(context.linePart(x, std::move(part)));
row.width = std::max(row.width, x + partWidth);
if (mMode == AUTO_WRAP && partWidth == 0)
@@ -506,7 +539,7 @@ void BrowserBox::updateHoveredLink(int x, int y)
void BrowserBox::maybeRelayoutText()
{
// Reduce relayouting frequency when there is a lot of text
- if (mTextRows.size() > 100)
+ if (mTextRows.size() > 1000)
if (!mLayoutTimer.passed())
return;
diff --git a/src/gui/widgets/browserbox.h b/src/gui/widgets/browserbox.h
index 7278bb59..142bba63 100644
--- a/src/gui/widgets/browserbox.h
+++ b/src/gui/widgets/browserbox.h
@@ -20,8 +20,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef BROWSERBOX_H
-#define BROWSERBOX_H
+#pragma once
#include "utils/time.h"
@@ -52,6 +51,7 @@ struct LinePart
int x;
int y;
gcn::Color color;
+ std::optional<gcn::Color> outlineColor;
std::string text;
gcn::Font *font;
};
@@ -87,6 +87,8 @@ class BrowserBox : public gcn::Widget,
*/
void setLinkHandler(LinkHandler *handler) { mLinkHandler = handler; }
+ void setPalette(int palette) { mPalette = palette; }
+
/**
* Sets the Highlight mode for links.
*/
@@ -118,9 +120,19 @@ class BrowserBox : public gcn::Widget,
void disableLinksAndUserColors() { mUseLinksAndUserColors = false; }
/**
+ * Enable or disable the replacement of keys.
+ */
+ void setEnableKeys(bool enable) { mEnableKeys = enable; }
+
+ /**
+ * Adds one or more text rows to the browser, separated by '\n'.
+ */
+ void addRows(std::string_view rows);
+
+ /**
* Adds a text row to the browser.
*/
- void addRow(const std::string &row);
+ void addRow(std::string_view row);
/**
* Remove all rows.
@@ -145,29 +157,6 @@ class BrowserBox : public gcn::Widget,
void drawFrame(gcn::Graphics *) override {}
/**
- * BrowserBox colors.
- *
- * NOTES (by Javila):
- * - color values is "0x" prefix followed by HTML color style.
- * - we can add up to 10 different colors: [0..9].
- * - not all colors will be fine with all backgrounds due transparent
- * windows and widgets. So, I think it's better keep BrowserBox
- * opaque (white background) by default.
- */
- enum
- {
- RED = 0xff0000, /**< Color 1 */
- GREEN = 0x009000, /**< Color 2 */
- BLUE = 0x0000ff, /**< Color 3 */
- ORANGE = 0xe0980e, /**< Color 4 */
- YELLOW = 0xf1dc27, /**< Color 5 */
- PINK = 0xff00d8, /**< Color 6 */
- PURPLE = 0x8415e2, /**< Color 7 */
- GRAY = 0x919191, /**< Color 8 */
- BROWN = 0x8e4c17 /**< Color 9 */
- };
-
- /**
* Highlight modes for links.
* This can be used for a bitmask.
*/
@@ -186,16 +175,16 @@ class BrowserBox : public gcn::Widget,
std::deque<TextRow> mTextRows;
LinkHandler *mLinkHandler = nullptr;
+ int mPalette = 0;
Mode mMode;
unsigned int mHighlightMode = UNDERLINE | BACKGROUND;
int mWrapIndent = 0;
bool mShadows = false;
bool mOutline = false;
bool mUseLinksAndUserColors = true;
+ bool mEnableKeys = false;
std::optional<BrowserLink> mHoveredLink;
unsigned int mMaxRows = 0;
int mLastLayoutWidth = 0;
Timer mLayoutTimer;
};
-
-#endif
diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp
index 274f329b..31c3a677 100644
--- a/src/gui/widgets/button.cpp
+++ b/src/gui/widgets/button.cpp
@@ -21,25 +21,22 @@
#include "gui/widgets/button.h"
-#include "configuration.h"
#include "graphics.h"
+#include "gui/gui.h"
#include "gui/textpopup.h"
#include "resources/image.h"
#include "resources/theme.h"
-
-#include "utils/dtor.h"
+#include "textrenderer.h"
#include <guichan/exception.hpp>
#include <guichan/font.hpp>
int Button::mInstances = 0;
-float Button::mAlpha = 1.0;
-ImageRect *Button::mButton;
TextPopup *Button::mTextPopup = nullptr;
-enum{
+enum {
BUTTON_STANDARD, // 0
BUTTON_HIGHLIGHTED, // 1
BUTTON_PRESSED, // 2
@@ -47,20 +44,6 @@ enum{
BUTTON_COUNT // 4 - Must be last.
};
-struct ButtonData
-{
- char const *file;
- int gridX;
- int gridY;
-};
-
-static ButtonData const data[BUTTON_COUNT] = {
- { "button.png", 0, 0 },
- { "buttonhi.png", 9, 4 },
- { "buttonpress.png", 16, 19 },
- { "button_disabled.png", 25, 23 }
-};
-
Button::Button()
{
init();
@@ -80,18 +63,19 @@ Button::Button(const std::string &caption, const std::string &actionEventId,
adjustSize();
}
-bool Button::setButtonIcon(const std::string& iconFile)
+Button::~Button() = default;
+
+bool Button::setButtonIcon(const std::string &iconFile)
{
// We clean up possible older references.
- if (mButtonIcon)
- removeButtonIcon();
+ removeButtonIcon();
// If nothing relevant was set, we can quit now.
if (iconFile.empty())
return false;
// Load the icon frames.
- Image *btnIcons = Theme::getImageFromTheme(iconFile);
+ auto btnIcons = Theme::getImageFromTheme(iconFile);
if (!btnIcons)
return false;
@@ -101,141 +85,76 @@ bool Button::setButtonIcon(const std::string& iconFile)
if (frameWidth > 0 && frameHeight > 0)
{
- mButtonIcon = new Image*[BUTTON_COUNT];
+ mButtonIcon.resize(BUTTON_COUNT);
+
for (int mode = 0; mode < BUTTON_COUNT; ++mode)
{
- mButtonIcon[mode] = btnIcons->getSubImage(mode * frameWidth, 0,
- frameWidth, frameHeight);
+ mButtonIcon[mode].reset(
+ btnIcons->getSubImage(mode * frameWidth, 0, frameWidth, frameHeight));
}
adjustSize();
}
- btnIcons->decRef();
- return (mButtonIcon);
+ return !mButtonIcon.empty();
}
-void Button::removeButtonIcon(bool adjustButtonSize)
+void Button::removeButtonIcon()
{
- if (!mButtonIcon)
+ if (mButtonIcon.empty())
return;
- // Delete potential button icons
- for (int mode = 0; mode < BUTTON_COUNT; ++mode)
- {
- delete mButtonIcon[mode];
- mButtonIcon[mode] = nullptr;
- }
- delete[] mButtonIcon;
- mButtonIcon = nullptr;
-
- if (adjustButtonSize)
- adjustSize();
+ mButtonIcon.clear();
+ adjustSize();
}
void Button::init()
{
- setFrameSize(0);
+ auto &skin = gui->getTheme()->getSkin(SkinType::Button);
+ setFrameSize(skin.frameSize);
+ setSpacing(skin.padding);
if (mInstances == 0)
{
- // Load the skin
- mButton = new ImageRect[BUTTON_COUNT];
-
- for (int mode = 0; mode < BUTTON_COUNT; ++mode)
- {
- Image *modeImage = Theme::getImageFromTheme(data[mode].file);
- int a = 0;
- for (int y = 0; y < 3; y++)
- {
- for (int x = 0; x < 3; x++)
- {
- mButton[mode].grid[a] = modeImage->getSubImage(
- data[x].gridX, data[y].gridY,
- data[x + 1].gridX - data[x].gridX + 1,
- data[y + 1].gridY - data[y].gridY + 1);
- a++;
- }
- }
- modeImage->decRef();
- }
- updateAlpha();
-
- // Load the popup
+ // Create the tooltip popup. It is shared by all buttons and will get
+ // deleted by the WindowContainer.
if (!mTextPopup)
- mTextPopup = new TextPopup();
+ mTextPopup = new TextPopup;
}
mInstances++;
}
-Button::~Button()
+void Button::draw(gcn::Graphics *graphics)
{
- mInstances--;
-
- if (mInstances == 0)
- {
- for (int mode = 0; mode < BUTTON_COUNT; ++mode)
- {
- std::for_each(mButton[mode].grid, mButton[mode].grid + 9,
- dtor<Image*>());
- }
- delete[] mButton;
+ WidgetState widgetState(this);
+ if (mHasMouse)
+ widgetState.flags |= STATE_HOVERED;
+ if (isPressed())
+ widgetState.flags |= STATE_SELECTED;
- // Remove the popup
- delete mTextPopup;
- mTextPopup = nullptr;
- }
- // Don' try to readjust the size when it's about to be deleted.
- removeButtonIcon(false);
-}
+ auto &skin = gui->getTheme()->getSkin(SkinType::Button);
+ skin.draw(static_cast<Graphics *>(graphics), widgetState);
-void Button::updateAlpha()
-{
- float alpha = std::max(config.guiAlpha,
- Theme::instance()->getMinimumOpacity());
+ auto skinState = skin.getState(widgetState.flags);
+ auto font = (skinState && skinState->textFormat.bold) ? boldFont : getFont();
- if (mAlpha != alpha)
- {
- mAlpha = alpha;
- for (int mode = 0; mode < BUTTON_COUNT; ++mode)
- {
- mButton[mode].setAlpha(mAlpha);
- }
- }
-}
-
-void Button::draw(gcn::Graphics *graphics)
-{
int mode;
- if (!isEnabled())
+ if (widgetState.flags & STATE_DISABLED)
mode = BUTTON_DISABLED;
- else if (isPressed())
+ else if (widgetState.flags & STATE_SELECTED)
mode = BUTTON_PRESSED;
- else if (mHasMouse || isFocused())
+ else if (widgetState.flags & (STATE_HOVERED | STATE_FOCUSED))
mode = BUTTON_HIGHLIGHTED;
else
mode = BUTTON_STANDARD;
- updateAlpha();
-
- static_cast<Graphics*>(graphics)->
- drawImageRect(0, 0, getWidth(), getHeight(), mButton[mode]);
-
- if (mode == BUTTON_DISABLED)
- graphics->setColor(Theme::getThemeColor(Theme::BUTTON_DISABLED));
- else
- graphics->setColor(Theme::getThemeColor(Theme::BUTTON));
-
+ Image *icon = mButtonIcon.empty() ? nullptr : mButtonIcon[mode].get();
int textX = 0;
- int textY = getHeight() / 2 - getFont()->getHeight() / 2;
+ int textY = getHeight() / 2 - font->getHeight() / 2;
int btnIconX = 0;
- int btnIconY = getHeight() / 2
- - ((mButtonIcon && mButtonIcon[mode]) ?
- mButtonIcon[mode]->getHeight() / 2 : 0);
-
- int btnIconWidth = (mButtonIcon && mButtonIcon[mode]) ?
- mButtonIcon[mode]->getWidth() : 0;
+ int btnIconY = getHeight() / 2 - (icon ? icon->getHeight() / 2 : 0);
+ int btnIconWidth = icon ? icon->getWidth() : 0;
switch (getAlignment())
{
@@ -243,7 +162,7 @@ void Button::draw(gcn::Graphics *graphics)
if (btnIconWidth)
{
btnIconX = 4;
- textX = btnIconX + mButtonIcon[mode]->getWidth() + 2;
+ textX = btnIconX + icon->getWidth() + 2;
}
else
{
@@ -253,9 +172,8 @@ void Button::draw(gcn::Graphics *graphics)
case gcn::Graphics::CENTER:
if (btnIconWidth)
{
- btnIconX = getWidth() / 2 - (getFont()->getWidth(mCaption)
- + mButtonIcon[mode]->getWidth() + 2) / 2;
- textX = getWidth() / 2 + mButtonIcon[mode]->getWidth() / 2 + 2;
+ btnIconX = (getWidth() - font->getWidth(mCaption) - icon->getWidth() - 2) / 2;
+ textX = (getWidth() + icon->getWidth()) / 2 + 2;
}
else
{
@@ -264,15 +182,13 @@ void Button::draw(gcn::Graphics *graphics)
break;
case gcn::Graphics::RIGHT:
if (btnIconWidth)
- btnIconX = getWidth() - 4 - getFont()->getWidth(mCaption) - 2;
+ btnIconX = getWidth() - 4 - font->getWidth(mCaption) - 2;
textX = getWidth() - 4;
break;
default:
throw GCN_EXCEPTION("Button::draw(). Unknown alignment.");
}
- graphics->setFont(getFont());
-
if (isPressed())
{
textX++; textY++;
@@ -280,23 +196,32 @@ void Button::draw(gcn::Graphics *graphics)
}
if (btnIconWidth)
- static_cast<Graphics*>(graphics)->drawImage(mButtonIcon[mode],
- btnIconX, btnIconY);
- graphics->drawText(getCaption(), textX, textY, getAlignment());
+ static_cast<Graphics *>(graphics)->drawImage(icon, btnIconX, btnIconY);
+
+ if (auto skinState = skin.getState(widgetState.flags))
+ {
+ auto &textFormat = skinState->textFormat;
+ TextRenderer::renderText(static_cast<Graphics *>(graphics),
+ getCaption(),
+ textX,
+ textY,
+ getAlignment(),
+ font,
+ textFormat);
+ }
}
void Button::adjustSize()
{
// Size of the image button.
int iconWidth = 0, iconHeight = 0;
- if (mButtonIcon)
+ if (!mButtonIcon.empty())
{
for (int mode = 0; mode < BUTTON_COUNT; ++mode)
{
- iconWidth = std::max(iconWidth, mButtonIcon[mode] ?
- mButtonIcon[mode]->getWidth() + 2 : 0);
- iconHeight = std::max(iconHeight, mButtonIcon[mode] ?
- mButtonIcon[mode]->getHeight() : 0);
+ const Image *icon = mButtonIcon[mode].get();
+ iconWidth = std::max(iconWidth, icon->getWidth() + 2);
+ iconHeight = std::max(iconHeight, icon->getHeight());
}
}
@@ -311,16 +236,9 @@ void Button::setCaption(const std::string& caption)
adjustSize();
}
-void Button::logic()
-{
- gcn::Button::logic();
- mTextPopup->logic();
-}
-
void Button::mouseMoved(gcn::MouseEvent &event)
{
gcn::Button::mouseMoved(event);
- mTextPopup->mouseMoved(event);
int x = event.getX();
int y = event.getY();
@@ -344,7 +262,6 @@ void Button::mouseMoved(gcn::MouseEvent &event)
void Button::mouseExited(gcn::MouseEvent &event)
{
gcn::Button::mouseExited(event);
- mTextPopup->mouseExited(event);
mTextPopup->setVisible(false);
}
diff --git a/src/gui/widgets/button.h b/src/gui/widgets/button.h
index a09b4445..97f7307b 100644
--- a/src/gui/widgets/button.h
+++ b/src/gui/widgets/button.h
@@ -19,12 +19,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef BUTTON_H
-#define BUTTON_H
+#pragma once
#include <guichan/widgets/button.hpp>
-class ImageRect;
+#include <memory>
+#include <vector>
+
class Image;
class TextPopup;
@@ -55,11 +56,6 @@ class Button : public gcn::Button
*/
void draw(gcn::Graphics *graphics) override;
- /**
- * Update the alpha value to the button components.
- */
- void updateAlpha();
-
void adjustSize();
void setCaption(const std::string &caption);
@@ -82,27 +78,22 @@ class Button : public gcn::Button
void setButtonPopupText(const std::string &text)
{ mPopupText = text; }
- void logic() override;
void mouseMoved(gcn::MouseEvent &event) override;
void mouseExited(gcn::MouseEvent &event) override;
private:
void init();
- void removeButtonIcon(bool adjustButtonSize = true);
+ void removeButtonIcon();
- static ImageRect* mButton; /**< Button state graphics */
static int mInstances; /**< Number of button instances */
- static float mAlpha;
- Image** mButtonIcon = nullptr; /**< Button Icons graphics */
+ std::vector<std::unique_ptr<Image>> mButtonIcon; /**< Button Icons graphics */
/**
* The buttons popup
* @note: This is a global object. One for all the buttons.
*/
- static TextPopup* mTextPopup;
+ static TextPopup *mTextPopup;
std::string mPopupText; /**< the current button text */
};
-
-#endif
diff --git a/src/gui/widgets/channeltab.h b/src/gui/widgets/channeltab.h
index 2894dacd..d6dc1268 100644
--- a/src/gui/widgets/channeltab.h
+++ b/src/gui/widgets/channeltab.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef CHANNELTAB_H
-#define CHANNELTAB_H
+#pragma once
#include "chattab.h"
@@ -51,5 +50,3 @@ class ChannelTab : public ChatTab
private:
Channel *mChannel;
};
-
-#endif // CHANNELTAB_H
diff --git a/src/gui/widgets/chattab.cpp b/src/gui/widgets/chattab.cpp
index 485de566..03c3270a 100644
--- a/src/gui/widgets/chattab.cpp
+++ b/src/gui/widgets/chattab.cpp
@@ -160,7 +160,7 @@ void ChatTab::chatLog(std::string line, Own own, bool ignoreRecord)
tmp.nick = strprintf(_("Global announcement from %s:"),
tmp.nick.c_str());
tmp.nick += " ";
- lineColor = "##1"; // Equiv. to BrowserBox::RED
+ lineColor = "##g";
}
break;
case BY_PLAYER:
diff --git a/src/gui/widgets/chattab.h b/src/gui/widgets/chattab.h
index 3e770fe1..dfc07638 100644
--- a/src/gui/widgets/chattab.h
+++ b/src/gui/widgets/chattab.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef CHATTAB_H
-#define CHATTAB_H
+#pragma once
#include "gui/chatwindow.h"
@@ -135,5 +134,3 @@ class ChatTab : public Tab, public AutoCompleteLister, public EventListener
};
extern ChatTab *localChatTab;
-
-#endif // CHATTAB_H
diff --git a/src/gui/widgets/checkbox.cpp b/src/gui/widgets/checkbox.cpp
index 274855fd..e6079f2f 100644
--- a/src/gui/widgets/checkbox.cpp
+++ b/src/gui/widgets/checkbox.cpp
@@ -21,121 +21,43 @@
#include "gui/widgets/checkbox.h"
-#include "configuration.h"
-#include "graphics.h"
+#include "textrenderer.h"
-#include "resources/image.h"
+#include "gui/gui.h"
#include "resources/theme.h"
-int CheckBox::instances = 0;
-float CheckBox::mAlpha = 1.0;
-Image *CheckBox::checkBoxNormal;
-Image *CheckBox::checkBoxChecked;
-Image *CheckBox::checkBoxDisabled;
-Image *CheckBox::checkBoxDisabledChecked;
-Image *CheckBox::checkBoxNormalHi;
-Image *CheckBox::checkBoxCheckedHi;
+#include <guichan/font.hpp>
-CheckBox::CheckBox(const std::string &caption, bool selected):
- gcn::CheckBox(caption, selected)
+CheckBox::CheckBox(const std::string &caption, bool selected)
+ : gcn::CheckBox(caption, selected)
{
- if (instances == 0)
- {
- Image *checkBox = Theme::getImageFromTheme("checkbox.png");
- checkBoxNormal = checkBox->getSubImage(0, 0, 9, 10);
- checkBoxChecked = checkBox->getSubImage(9, 0, 9, 10);
- checkBoxDisabled = checkBox->getSubImage(18, 0, 9, 10);
- checkBoxDisabledChecked = checkBox->getSubImage(27, 0, 9, 10);
- checkBoxNormalHi = checkBox->getSubImage(36, 0, 9, 10);
- checkBoxCheckedHi = checkBox->getSubImage(45, 0, 9, 10);
- checkBoxNormal->setAlpha(mAlpha);
- checkBoxChecked->setAlpha(mAlpha);
- checkBoxDisabled->setAlpha(mAlpha);
- checkBoxDisabledChecked->setAlpha(mAlpha);
- checkBoxNormalHi->setAlpha(mAlpha);
- checkBoxCheckedHi->setAlpha(mAlpha);
- checkBox->decRef();
- }
-
- instances++;
-}
-
-CheckBox::~CheckBox()
-{
- instances--;
-
- if (instances == 0)
- {
- delete checkBoxNormal;
- delete checkBoxChecked;
- delete checkBoxDisabled;
- delete checkBoxDisabledChecked;
- delete checkBoxNormalHi;
- delete checkBoxCheckedHi;
- }
+ auto &skin = gui->getTheme()->getSkin(SkinType::CheckBox);
+ setWidth(skin.getMinWidth() + 2 * skin.padding + skin.spacing + getFont()->getWidth(caption));
+ setHeight(skin.getMinHeight() + 2 * skin.padding);
}
void CheckBox::draw(gcn::Graphics* graphics)
{
- drawBox(graphics);
-
- graphics->setFont(getFont());
- graphics->setColor(Theme::getThemeColor(Theme::TEXT));
-
- const int h = getHeight() + getHeight() / 2;
-
- graphics->drawText(getCaption(), h - 2, 0);
-}
-
-void CheckBox::updateAlpha()
-{
- float alpha = std::max(config.guiAlpha,
- Theme::instance()->getMinimumOpacity());
-
- if (mAlpha != alpha)
- {
- mAlpha = alpha;
- checkBoxNormal->setAlpha(mAlpha);
- checkBoxChecked->setAlpha(mAlpha);
- checkBoxDisabled->setAlpha(mAlpha);
- checkBoxDisabledChecked->setAlpha(mAlpha);
- checkBoxNormal->setAlpha(mAlpha);
- checkBoxCheckedHi->setAlpha(mAlpha);
- }
-}
+ WidgetState widgetState(this);
+ if (mHasMouse)
+ widgetState.flags |= STATE_HOVERED;
+ if (isSelected())
+ widgetState.flags |= STATE_SELECTED;
-void CheckBox::drawBox(gcn::Graphics* graphics)
-{
- Image *box;
+ auto &skin = gui->getTheme()->getSkin(SkinType::CheckBox);
+ skin.draw(static_cast<Graphics *>(graphics), widgetState);
- if (isEnabled())
- {
- if (isSelected())
- {
- if (mHasMouse)
- box = checkBoxCheckedHi;
- else
- box = checkBoxChecked;
- }
- else
- {
- if (mHasMouse)
- box = checkBoxNormalHi;
- else
- box = checkBoxNormal;
- }
- }
- else
+ if (auto skinState = skin.getState(widgetState.flags))
{
- if (isSelected())
- box = checkBoxDisabledChecked;
- else
- box = checkBoxDisabled;
+ auto &textFormat = skinState->textFormat;
+ TextRenderer::renderText(static_cast<Graphics *>(graphics),
+ getCaption(),
+ skin.getMinWidth() + skin.padding + skin.spacing,
+ skin.padding,
+ Graphics::LEFT,
+ textFormat.bold ? boldFont : getFont(),
+ textFormat);
}
-
- updateAlpha();
-
- static_cast<Graphics*>(graphics)->drawImage(box, 2, 2);
}
void CheckBox::mouseEntered(gcn::MouseEvent& event)
diff --git a/src/gui/widgets/checkbox.h b/src/gui/widgets/checkbox.h
index f77b1761..ea1a20e7 100644
--- a/src/gui/widgets/checkbox.h
+++ b/src/gui/widgets/checkbox.h
@@ -19,13 +19,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef CHECKBOX_H
-#define CHECKBOX_H
+#pragma once
#include <guichan/widgets/checkbox.hpp>
-class Image;
-
/**
* Check box widget. Same as the Guichan check box but with custom look.
*
@@ -36,43 +33,26 @@ class CheckBox : public gcn::CheckBox
public:
CheckBox(const std::string &caption, bool selected = false);
- ~CheckBox() override;
-
/**
* Draws the caption, then calls drawBox to draw the check box.
*/
- void draw(gcn::Graphics* graphics) override;
-
- /**
- * Update the alpha value to the checkbox components.
- */
- void updateAlpha();
+ void draw(gcn::Graphics *graphics) override;
/**
- * Draws the check box, not the caption.
+ * Overridden because box is drawn in CheckBox::draw.
*/
- void drawBox(gcn::Graphics* graphics) override;
+ void drawBox(gcn::Graphics *graphics) override {}
/**
* Called when the mouse enteres the widget area.
*/
- void mouseEntered(gcn::MouseEvent& event) override;
+ void mouseEntered(gcn::MouseEvent &event) override;
/**
* Called when the mouse leaves the widget area.
*/
- void mouseExited(gcn::MouseEvent& event) override;
+ void mouseExited(gcn::MouseEvent &event) override;
private:
- static int instances;
- static float mAlpha;
bool mHasMouse = false;
- static Image *checkBoxNormal;
- static Image *checkBoxChecked;
- static Image *checkBoxDisabled;
- static Image *checkBoxDisabledChecked;
- static Image *checkBoxNormalHi;
- static Image *checkBoxCheckedHi;
};
-
-#endif
diff --git a/src/gui/widgets/container.h b/src/gui/widgets/container.h
index ef44c8cd..54b7950b 100644
--- a/src/gui/widgets/container.h
+++ b/src/gui/widgets/container.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GUI_CONTAINER_H
-#define GUI_CONTAINER_H
+#pragma once
#include <guichan/widgets/container.hpp>
@@ -33,7 +32,7 @@ class LayoutHelper;
* A widget container.
*
* The main difference between the standard Guichan container and this one is
- * that childs added to this container are automatically deleted when the
+ * that children added to this container are automatically deleted when the
* container is deleted.
*
* This container is also non-opaque by default.
@@ -44,6 +43,9 @@ class Container : public gcn::Container
Container();
~Container() override;
+ // Overridden to disable drawing of the frame
+ void drawFrame(gcn::Graphics *graphics) override {}
+
protected:
/**
* Gets the layout handler for this container.
@@ -63,5 +65,3 @@ class Container : public gcn::Container
private:
LayoutHelper *mLayoutHelper = nullptr;
};
-
-#endif
diff --git a/src/gui/widgets/desktop.cpp b/src/gui/widgets/desktop.cpp
index c8ded9f5..e424beec 100644
--- a/src/gui/widgets/desktop.cpp
+++ b/src/gui/widgets/desktop.cpp
@@ -105,7 +105,7 @@ void Desktop::setBestFittingWallpaper()
return;
ResourceManager *resman = ResourceManager::getInstance();
- auto wallpaper = resman->getImageRef(wallpaperName);
+ auto wallpaper = resman->getImage(wallpaperName);
if (wallpaper)
{
diff --git a/src/gui/widgets/desktop.h b/src/gui/widgets/desktop.h
index 5909ac72..a7aa4a1e 100644
--- a/src/gui/widgets/desktop.h
+++ b/src/gui/widgets/desktop.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef DESKTOP_H
-#define DESKTOP_H
+#pragma once
#include "guichanfwd.h"
@@ -66,5 +65,3 @@ class Desktop : public Container, gcn::WidgetListener
ResourceRef<Image> mWallpaper;
gcn::Label *mVersionLabel;
};
-
-#endif // DESKTOP_H
diff --git a/src/gui/widgets/dropdown.cpp b/src/gui/widgets/dropdown.cpp
index 8811eb8d..7d8ad0e5 100644
--- a/src/gui/widgets/dropdown.cpp
+++ b/src/gui/widgets/dropdown.cpp
@@ -21,127 +21,44 @@
#include "gui/widgets/dropdown.h"
-#include "configuration.h"
#include "graphics.h"
+#include "gui/gui.h"
#include "gui/sdlinput.h"
#include "gui/widgets/listbox.h"
#include "gui/widgets/scrollarea.h"
-#include "resources/image.h"
#include "resources/theme.h"
-#include "utils/dtor.h"
-
-#include <algorithm>
-
-int DropDown::instances = 0;
-Image *DropDown::buttons[2][2];
-ImageRect DropDown::skin;
-float DropDown::mAlpha = 1.0;
+#include <guichan/font.hpp>
DropDown::DropDown(gcn::ListModel *listModel):
gcn::DropDown::DropDown(listModel,
new ScrollArea,
new ListBox(listModel))
{
- setFrameSize(2);
-
- // Initialize graphics
- if (instances == 0)
- {
- // Load the background skin
-
- // Get the button skin
- buttons[1][0] = Theme::getImageFromTheme("vscroll_up_default.png");
- buttons[0][0] = Theme::getImageFromTheme("vscroll_down_default.png");
- buttons[1][1] = Theme::getImageFromTheme("vscroll_up_pressed.png");
- buttons[0][1] = Theme::getImageFromTheme("vscroll_down_pressed.png");
-
- buttons[0][0]->setAlpha(mAlpha);
- buttons[0][1]->setAlpha(mAlpha);
- buttons[1][0]->setAlpha(mAlpha);
- buttons[1][1]->setAlpha(mAlpha);
-
- // get the border skin
- Image *boxBorder = Theme::getImageFromTheme("deepbox.png");
- int gridx[4] = {0, 3, 28, 31};
- int gridy[4] = {0, 3, 28, 31};
- int a = 0;
-
- for (int y = 0; y < 3; y++)
- {
- for (int x = 0; x < 3; x++)
- {
- skin.grid[a] = boxBorder->getSubImage(gridx[x], gridy[y],
- gridx[x + 1] -
- gridx[x] + 1,
- gridy[y + 1] -
- gridy[y] + 1);
- a++;
- }
- }
+ auto &skin = gui->getTheme()->getSkin(SkinType::DropDownFrame);
+ setFrameSize(skin.frameSize);
+ mPadding = skin.padding;
- skin.setAlpha(mAlpha);
-
- boxBorder->decRef();
- }
-
- instances++;
+ setHeight(getFont()->getHeight() + 2 * mPadding);
}
DropDown::~DropDown()
{
- instances--;
- // Free images memory
- if (instances == 0)
- {
- buttons[0][0]->decRef();
- buttons[0][1]->decRef();
- buttons[1][0]->decRef();
- buttons[1][1]->decRef();
-
- std::for_each(skin.grid, skin.grid + 9, dtor<Image*>());
- }
-
delete mScrollArea;
}
-void DropDown::updateAlpha()
-{
- float alpha = std::max(config.guiAlpha,
- Theme::instance()->getMinimumOpacity());
-
- if (mAlpha != alpha)
- {
- mAlpha = alpha;
-
- buttons[0][0]->setAlpha(mAlpha);
- buttons[0][1]->setAlpha(mAlpha);
- buttons[1][0]->setAlpha(mAlpha);
- buttons[1][1]->setAlpha(mAlpha);
-
- skin.setAlpha(mAlpha);
- }
-}
-
void DropDown::draw(gcn::Graphics* graphics)
{
- int h;
+ const int h = mDroppedDown ? mFoldedUpHeight : getHeight();
- if (mDroppedDown)
- h = mFoldedUpHeight;
- else
- h = getHeight();
-
- updateAlpha();
-
- const int alpha = (int) (mAlpha * 255.0f);
+ const int alpha = gui->getTheme()->getGuiAlpha();
gcn::Color faceColor = getBaseColor();
faceColor.a = alpha;
- const gcn::Color *highlightColor = &Theme::getThemeColor(Theme::HIGHLIGHT,
- alpha);
+ auto highlightColor = Theme::getThemeColor(Theme::HIGHLIGHT);
+ highlightColor.a = alpha;
gcn::Color shadowColor = faceColor - 0x303030;
shadowColor.a = alpha;
@@ -149,13 +66,16 @@ void DropDown::draw(gcn::Graphics* graphics)
{
graphics->setFont(getFont());
graphics->setColor(Theme::getThemeColor(Theme::TEXT));
- graphics->drawText(mListBox->getListModel()->getElementAt(mListBox->getSelected()), 1, 0);
+ graphics->drawText(mListBox->getListModel()->getElementAt(mListBox->getSelected()),
+ mPadding,
+ mPadding);
}
if (isFocused())
{
- graphics->setColor(*highlightColor);
- graphics->drawRectangle(gcn::Rectangle(0, 0, getWidth() - h, h));
+ graphics->setColor(highlightColor);
+ graphics->drawRectangle(
+ gcn::Rectangle(mPadding, mPadding, getWidth() - h - mPadding * 2, h - 2 * mPadding));
}
drawButton(graphics);
@@ -166,7 +86,7 @@ void DropDown::draw(gcn::Graphics* graphics)
// Draw two lines separating the ListBox with selected
// element view.
- graphics->setColor(*highlightColor);
+ graphics->setColor(highlightColor);
graphics->drawLine(0, h, getWidth(), h);
graphics->setColor(shadowColor);
graphics->drawLine(0, h + 1, getWidth(), h + 1);
@@ -176,18 +96,64 @@ void DropDown::draw(gcn::Graphics* graphics)
void DropDown::drawFrame(gcn::Graphics *graphics)
{
const int bs = getFrameSize();
- const int w = getWidth() + bs * 2;
- const int h = getHeight() + bs * 2;
- static_cast<Graphics*>(graphics)->drawImageRect(0, 0, w, h, skin);
+ WidgetState state(this);
+ state.width += bs * 2;
+ state.height += bs * 2;
+
+ gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics), SkinType::DropDownFrame, state);
+}
+
+// Overridden so that we can take mPadding into account
+void DropDown::adjustHeight()
+{
+ const int listBoxHeight = mListBox->getHeight();
+ int height = getFont()->getHeight() + 2 * mPadding;
+
+ // The addition/subtraction of 2 compensates for the seperation lines
+ // seperating the selected element view and the scroll area.
+
+ if (mDroppedDown && getParent())
+ {
+ int availableHeight = getParent()->getChildrenArea().height - getY();
+
+ if (listBoxHeight > availableHeight - height - 2)
+ {
+ mScrollArea->setHeight(availableHeight - height - 2);
+ height = availableHeight;
+ }
+ else
+ {
+ height += listBoxHeight + 2;
+ mScrollArea->setHeight(listBoxHeight);
+ }
+ }
+
+ setHeight(height);
+
+ mScrollArea->setWidth(getWidth());
+ // Resize the ListBox to exactly fit the ScrollArea.
+ mListBox->setWidth(mScrollArea->getChildrenArea().width);
+ mScrollArea->setPosition(0, 0);
}
void DropDown::drawButton(gcn::Graphics *graphics)
{
- int height = mDroppedDown ? mFoldedUpHeight : getHeight();
+ WidgetState state(this);
+ if (mDroppedDown)
+ {
+ state.height = mFoldedUpHeight;
+ state.flags |= STATE_SELECTED;
+ }
+ if (mPushed)
+ state.flags |= STATE_HOVERED;
+
+ auto &skin = gui->getTheme()->getSkin(SkinType::DropDownButton);
+
+ // FIXME: Needs support for setting alignment in the theme.
+ state.x = state.width - skin.getMinWidth();
- static_cast<Graphics*>(graphics)->
- drawImage(buttons[mDroppedDown][mPushed], getWidth() - height + 2, 1);
+ skin.draw(static_cast<Graphics *>(graphics), state);
}
// -- KeyListener notifications
@@ -253,3 +219,32 @@ void DropDown::mouseWheelMovedDown(gcn::MouseEvent& mouseEvent)
mouseEvent.consume();
distributeActionEvent();
}
+
+// Overridden to call our version of adjustHeight
+void DropDown::dropDown()
+{
+ if (!mDroppedDown)
+ {
+ mDroppedDown = true;
+ mFoldedUpHeight = getHeight();
+ adjustHeight();
+
+ if (getParent())
+ {
+ getParent()->moveToTop(this);
+ }
+ }
+
+ mListBox->requestFocus();
+}
+
+// Overridden to call our version of adjustHeight
+void DropDown::foldUp()
+{
+ if (mDroppedDown)
+ {
+ mDroppedDown = false;
+ adjustHeight();
+ mInternalFocusHandler.focusNone();
+ }
+}
diff --git a/src/gui/widgets/dropdown.h b/src/gui/widgets/dropdown.h
index f92c7dd5..a5e2e2f7 100644
--- a/src/gui/widgets/dropdown.h
+++ b/src/gui/widgets/dropdown.h
@@ -19,14 +19,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef DROPDOWN_H
-#define DROPDOWN_H
+#pragma once
#include <guichan/widgets/dropdown.hpp>
-class Image;
-class ImageRect;
-
/**
* A drop down box from which you can select different values.
*
@@ -47,15 +43,12 @@ class DropDown : public gcn::DropDown
~DropDown() override;
- /**
- * Update the alpha value to the graphic components.
- */
- static void updateAlpha();
-
void draw(gcn::Graphics *graphics) override;
void drawFrame(gcn::Graphics *graphics) override;
+ void adjustHeight();
+
// Inherited from FocusListener
void focusLost(const gcn::Event& event) override;
@@ -80,12 +73,8 @@ class DropDown : public gcn::DropDown
*/
void drawButton(gcn::Graphics *graphics) override;
- // Add own Images.
- static int instances;
- static Image *buttons[2][2];
- static ImageRect skin;
- static float mAlpha;
-};
-
-#endif // end DROPDOWN_H
+ void dropDown() override;
+ void foldUp() override;
+ int mPadding = 1;
+};
diff --git a/src/gui/widgets/emoteshortcutcontainer.cpp b/src/gui/widgets/emoteshortcutcontainer.cpp
index 8ecbc9bf..06d80ec2 100644
--- a/src/gui/widgets/emoteshortcutcontainer.cpp
+++ b/src/gui/widgets/emoteshortcutcontainer.cpp
@@ -21,13 +21,12 @@
#include "gui/widgets/emoteshortcutcontainer.h"
-#include "configuration.h"
#include "emoteshortcut.h"
#include "graphics.h"
-#include "imagesprite.h"
-#include "item.h"
#include "keyboardconfig.h"
+#include "gui/gui.h"
+
#include "resources/emotedb.h"
#include "resources/image.h"
#include "resources/theme.h"
@@ -36,65 +35,52 @@ static const int MAX_ITEMS = 12;
EmoteShortcutContainer::EmoteShortcutContainer()
{
- addMouseListener(this);
- addWidgetListener(this);
-
- mBackgroundImg = Theme::getImageFromTheme("item_shortcut_bgr.png");
-
- mBackgroundImg->setAlpha(config.guiAlpha);
-
mMaxItems = std::min(EmoteDB::getEmoteCount(), MAX_ITEMS);
-
- mBoxHeight = mBackgroundImg->getHeight();
- mBoxWidth = mBackgroundImg->getWidth();
-}
-
-EmoteShortcutContainer::~EmoteShortcutContainer()
-{
- mBackgroundImg->decRef();
}
void EmoteShortcutContainer::draw(gcn::Graphics *graphics)
{
- if (config.guiAlpha != mAlpha)
- {
- mAlpha = config.guiAlpha;
- mBackgroundImg->setAlpha(mAlpha);
- }
-
auto *g = static_cast<Graphics*>(graphics);
+ auto theme = gui->getTheme();
graphics->setFont(getFont());
for (int i = 0; i < mMaxItems; i++)
{
- const int emoteX = (i % mGridWidth) * mBoxWidth;
- const int emoteY = (i / mGridWidth) * mBoxHeight;
-
- g->drawImage(mBackgroundImg, emoteX, emoteY);
+ WidgetState state;
+ state.x = (i % mGridWidth) * mBoxWidth;
+ state.y = (i / mGridWidth) * mBoxHeight;
+ theme->drawSkin(g, SkinType::ShortcutBox, state);
// Draw emote keyboard shortcut.
const char *key = SDL_GetKeyName(
keyboard.getKeyValue(KeyboardConfig::KEY_EMOTE_1 + i));
graphics->setColor(Theme::getThemeColor(Theme::TEXT));
- g->drawText(key, emoteX + 2, emoteY + 2, gcn::Graphics::LEFT);
+ g->drawText(key, state.x + 2, state.y + 2, gcn::Graphics::LEFT);
int emoteId = emoteShortcut->getEmote(i);
if (emoteId != -1)
{
- EmoteDB::get(emoteId).sprite->draw(g, emoteX + 2, emoteY + 10);
+ if (auto image = EmoteDB::get(emoteId).image)
+ {
+ image->setAlpha(1.0f);
+ g->drawImage(image, state.x + 2, state.y + 10);
+ }
}
}
if (mEmoteMoved != -1)
{
// Draw the emote image being dragged by the cursor.
- const ImageSprite *sprite = EmoteDB::get(mEmoteMoved).sprite.get();
+ if (auto image = EmoteDB::get(mEmoteMoved).image)
+ {
+ image->setAlpha(1.0f);
- const int tPosX = mCursorPosX - (sprite->getWidth() / 2);
- const int tPosY = mCursorPosY - (sprite->getHeight() / 2);
+ const int tPosX = mCursorPosX - (image->getWidth() / 2);
+ const int tPosY = mCursorPosY - (image->getHeight() / 2);
- sprite->draw(g, tPosX, tPosY);
+ g->drawImage(image, tPosX, tPosY);
+ }
}
}
@@ -115,6 +101,7 @@ void EmoteShortcutContainer::mouseDragged(gcn::MouseEvent &event)
emoteShortcut->removeEmote(index);
}
}
+
if (mEmoteMoved != -1)
{
mCursorPosX = event.getX();
@@ -126,7 +113,6 @@ void EmoteShortcutContainer::mouseDragged(gcn::MouseEvent &event)
void EmoteShortcutContainer::mousePressed(gcn::MouseEvent &event)
{
const int index = getIndexFromGrid(event.getX(), event.getY());
-
if (index == -1)
return;
@@ -170,4 +156,3 @@ void EmoteShortcutContainer::mouseReleased(gcn::MouseEvent &event)
mEmoteClicked = false;
}
}
-
diff --git a/src/gui/widgets/emoteshortcutcontainer.h b/src/gui/widgets/emoteshortcutcontainer.h
index ecd41736..57d5efd2 100644
--- a/src/gui/widgets/emoteshortcutcontainer.h
+++ b/src/gui/widgets/emoteshortcutcontainer.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef EMOTESHORTCUTCONTAINER_H
-#define EMOTESHORTCUTCONTAINER_H
+#pragma once
#include "gui/widgets/shortcutcontainer.h"
@@ -34,8 +33,6 @@ class EmoteShortcutContainer : public ShortcutContainer
public:
EmoteShortcutContainer();
- ~EmoteShortcutContainer() override;
-
/**
* Draws the items.
*/
@@ -60,5 +57,3 @@ class EmoteShortcutContainer : public ShortcutContainer
bool mEmoteClicked = false;
int mEmoteMoved = -1;
};
-
-#endif
diff --git a/src/gui/widgets/flowcontainer.h b/src/gui/widgets/flowcontainer.h
index 21daae16..46be0919 100644
--- a/src/gui/widgets/flowcontainer.h
+++ b/src/gui/widgets/flowcontainer.h
@@ -18,8 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef FLOWCONTAINER_H
-#define FLOWCONTAINER_H
+#pragma once
#include "container.h"
@@ -56,5 +55,3 @@ class FlowContainer : public Container,
int mGridWidth = 1;
int mGridHeight = 1;
};
-
-#endif
diff --git a/src/gui/widgets/icon.cpp b/src/gui/widgets/icon.cpp
index 67fd8384..61506a6b 100644
--- a/src/gui/widgets/icon.cpp
+++ b/src/gui/widgets/icon.cpp
@@ -27,7 +27,7 @@
#include "resources/resourcemanager.h"
Icon::Icon(const std::string &file)
- : Icon(ResourceManager::getInstance()->getImageRef(file))
+ : Icon(ResourceManager::getInstance()->getImage(file))
{
}
diff --git a/src/gui/widgets/icon.h b/src/gui/widgets/icon.h
index 3ebc2c16..5e61520c 100644
--- a/src/gui/widgets/icon.h
+++ b/src/gui/widgets/icon.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef ICON_H
-#define ICON_H
+#pragma once
#include "resources/resource.h"
@@ -68,5 +67,3 @@ class Icon : public gcn::Widget
private:
ResourceRef<Image> mImage;
};
-
-#endif // ICON_H
diff --git a/src/gui/widgets/inttextfield.h b/src/gui/widgets/inttextfield.h
index d5829404..bebad71d 100644
--- a/src/gui/widgets/inttextfield.h
+++ b/src/gui/widgets/inttextfield.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef INTTEXTFIELD_H
-#define INTTEXTFIELD_H
+#pragma once
#include "textfield.h"
@@ -71,5 +70,3 @@ class IntTextField : public TextField
int mDefault; /**< Default value */
int mValue; /**< Current value */
};
-
-#endif
diff --git a/src/gui/widgets/itemcontainer.cpp b/src/gui/widgets/itemcontainer.cpp
index 940c69f4..d0d24c51 100644
--- a/src/gui/widgets/itemcontainer.cpp
+++ b/src/gui/widgets/itemcontainer.cpp
@@ -25,7 +25,6 @@
#include "inventory.h"
#include "item.h"
#include "itemshortcut.h"
-#include "log.h"
#include "gui/chatwindow.h"
#include "gui/itempopup.h"
@@ -44,19 +43,12 @@
// TODO: Add support for adding items to the item shortcut window (global
// itemShortcut).
-static const int BOX_WIDTH = 35;
-static const int BOX_HEIGHT = 43;
-
ItemContainer::ItemContainer(Inventory *inventory):
mInventory(inventory)
{
mItemPopup = new ItemPopup;
setFocusable(true);
- mSelImg = Theme::getImageFromTheme("selection.png");
- if (!mSelImg)
- logger->error("Unable to load selection.png");
-
addKeyListener(this);
addMouseListener(this);
addWidgetListener(this);
@@ -64,7 +56,6 @@ ItemContainer::ItemContainer(Inventory *inventory):
ItemContainer::~ItemContainer()
{
- mSelImg->decRef();
delete mItemPopup;
}
@@ -113,39 +104,47 @@ void ItemContainer::draw(gcn::Graphics *graphics)
}
}
+ auto theme = gui->getTheme();
+ auto &slotSkin = theme->getSkin(SkinType::ItemSlot);
+ WidgetState slotState;
+
for (int i = 0; i < mGridColumns; i++)
{
for (int j = 0; j < mGridRows; j++)
{
- int itemX = i * BOX_WIDTH;
- int itemY = j * BOX_HEIGHT;
+ int itemX = i * slotSkin.width;
+ int itemY = j * slotSkin.height;
int itemIndex = j * mGridColumns + i;
+ slotState.x = itemX;
+ slotState.y = itemY;
+ slotState.flags = 0;
+
+ if (itemIndex == mSelectedIndex)
+ {
+ slotState.flags |= STATE_SELECTED;
+
+ if (mSelectionStatus == SEL_DRAGGING)
+ {
+ // Reposition the coords to that of the cursor.
+ itemX = mDragPosX - (slotSkin.width / 2);
+ itemY = mDragPosY - (slotSkin.height / 2);
+ }
+ }
+
+ slotSkin.draw(g, slotState);
+
Item *item = getItemAt(itemIndex);
if (!item || item->getId() == 0)
continue;
- Image *image = item->getImage();
- if (image)
+ if (Image *image = item->getImage())
{
- if (itemIndex == mSelectedIndex)
- {
- if (mSelectionStatus == SEL_DRAGGING)
- {
- // Reposition the coords to that of the cursor.
- itemX = mDragPosX - (BOX_WIDTH / 2);
- itemY = mDragPosY - (BOX_HEIGHT / 2);
- }
- else
- {
- // Draw selection border image.
- g->drawImage(mSelImg, itemX, itemY);
- }
- }
- image->setAlpha(1.0f); // ensure the image if fully drawn...
- g->drawImage(image, itemX, itemY);
+ image->setAlpha(1.0f);
+ g->drawImage(image, itemX + slotSkin.padding, itemY + slotSkin.padding);
}
+
// Draw item caption
std::string caption;
if (item->getQuantity() > 1)
@@ -154,22 +153,22 @@ void ItemContainer::draw(gcn::Graphics *graphics)
caption = "Eq.";
if (item->isEquipped())
- g->setColor(Theme::getThemeColor(Theme::ITEM_EQUIPPED));
+ g->setColor(theme->getColor(Theme::ITEM_EQUIPPED));
else
g->setColor(gcn::Color(0, 0, 0));
- g->drawText(caption, itemX + BOX_WIDTH / 2,
- itemY + BOX_HEIGHT - 14, gcn::Graphics::CENTER);
+ g->drawText(caption, itemX + slotSkin.width / 2,
+ itemY + slotSkin.height - 14, gcn::Graphics::CENTER);
}
}
// Draw an orange box around the selected item
if (isFocused() && mHighlightedIndex != -1)
{
- const int itemX = (mHighlightedIndex % mGridColumns) * BOX_WIDTH;
- const int itemY = (mHighlightedIndex / mGridColumns) * BOX_HEIGHT;
+ const int itemX = (mHighlightedIndex % mGridColumns) * slotSkin.width;
+ const int itemY = (mHighlightedIndex / mGridColumns) * slotSkin.height;
g->setColor(gcn::Color(255, 128, 0));
- g->drawRectangle(gcn::Rectangle(itemX, itemY, BOX_WIDTH, BOX_HEIGHT));
+ g->drawRectangle(gcn::Rectangle(itemX, itemY, slotSkin.width, slotSkin.height));
}
}
@@ -355,9 +354,7 @@ void ItemContainer::mouseReleased(gcn::MouseEvent &event)
// Show ItemTooltip
void ItemContainer::mouseMoved(gcn::MouseEvent &event)
{
- Item *item = getItemAt(getSlotIndex(event.getX(), event.getY()));
-
- if (item)
+ if (Item *item = getItemAt(getSlotIndex(event.getX(), event.getY())))
{
mItemPopup->setItem(item->getInfo());
mItemPopup->position(viewport->getMouseX(), viewport->getMouseY());
@@ -376,26 +373,36 @@ void ItemContainer::mouseExited(gcn::MouseEvent &event)
void ItemContainer::widgetResized(const gcn::Event &event)
{
- mGridColumns = std::max(1, getWidth() / BOX_WIDTH);
+ auto &slotSkin = gui->getTheme()->getSkin(SkinType::ItemSlot);
+
+ mGridColumns = std::max(1, getWidth() / slotSkin.width);
adjustHeight();
}
void ItemContainer::adjustHeight()
{
+ auto &slotSkin = gui->getTheme()->getSkin(SkinType::ItemSlot);
+
mGridRows = (mLastUsedSlot + 1) / mGridColumns;
if (mGridRows == 0 || (mLastUsedSlot + 1) % mGridColumns > 0)
++mGridRows;
- setHeight(mGridRows * BOX_HEIGHT);
+ setHeight(mGridRows * slotSkin.height);
}
int ItemContainer::getSlotIndex(int x, int y) const
{
- if (x < getWidth() && y < getHeight())
- {
- return (y / BOX_HEIGHT) * mGridColumns + (x / BOX_WIDTH);
- }
- return Inventory::NO_SLOT_INDEX;
+ if (x >= getWidth() || y >= getHeight())
+ return Inventory::NO_SLOT_INDEX;
+
+ auto &slotSkin = gui->getTheme()->getSkin(SkinType::ItemSlot);
+ const auto row = y / slotSkin.height;
+ const auto column = x / slotSkin.width;
+
+ if (row < 0 || row >= mGridRows || column < 0 || column >= mGridColumns)
+ return Inventory::NO_SLOT_INDEX;
+
+ return (row * mGridColumns) + column;
}
void ItemContainer::keyAction()
diff --git a/src/gui/widgets/itemcontainer.h b/src/gui/widgets/itemcontainer.h
index 51807aba..c1d611b9 100644
--- a/src/gui/widgets/itemcontainer.h
+++ b/src/gui/widgets/itemcontainer.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef ITEMCONTAINER_H
-#define ITEMCONTAINER_H
+#pragma once
#include <guichan/keylistener.hpp>
#include <guichan/mouselistener.hpp>
@@ -71,6 +70,9 @@ class ItemContainer : public gcn::Widget,
*/
void draw(gcn::Graphics *graphics) override;
+ // Overridden to disable drawing of the frame
+ void drawFrame(gcn::Graphics *graphics) override {}
+
// KeyListener
void keyPressed(gcn::KeyEvent &event) override;
void keyReleased(gcn::KeyEvent &event) override;
@@ -178,7 +180,6 @@ class ItemContainer : public gcn::Widget,
Inventory *mInventory;
int mGridColumns = 1;
int mGridRows = 1;
- Image *mSelImg;
int mSelectedIndex = -1;
int mHighlightedIndex = -1;
int mLastUsedSlot = -1;
@@ -196,5 +197,3 @@ class ItemContainer : public gcn::Widget,
std::list<gcn::SelectionListener *> mSelectionListeners;
};
-
-#endif // ITEMCONTAINER_H
diff --git a/src/gui/widgets/itemlinkhandler.h b/src/gui/widgets/itemlinkhandler.h
index 28e9c11c..58202d33 100644
--- a/src/gui/widgets/itemlinkhandler.h
+++ b/src/gui/widgets/itemlinkhandler.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef ITEM_LINK_HANDLER_H
-#define ITEM_LINK_HANDLER_H
+#pragma once
#include "gui/widgets/linkhandler.h"
@@ -49,5 +48,3 @@ class ItemLinkHandler : public LinkHandler, gcn::ActionListener
Window *mParent = nullptr;
std::string mLink;
};
-
-#endif
diff --git a/src/gui/widgets/itemshortcutcontainer.cpp b/src/gui/widgets/itemshortcutcontainer.cpp
index 0b8f0c8c..b47fa29d 100644
--- a/src/gui/widgets/itemshortcutcontainer.cpp
+++ b/src/gui/widgets/itemshortcutcontainer.cpp
@@ -21,7 +21,6 @@
#include "gui/widgets/itemshortcutcontainer.h"
-#include "configuration.h"
#include "graphics.h"
#include "inventory.h"
#include "item.h"
@@ -39,64 +38,45 @@
#include "utils/stringutils.h"
ItemShortcutContainer::ItemShortcutContainer()
+ : mItemPopup(new ItemPopup)
{
- addMouseListener(this);
- addWidgetListener(this);
-
- mItemPopup = new ItemPopup;
-
- mBackgroundImg = Theme::getImageFromTheme("item_shortcut_bgr.png");
mMaxItems = itemShortcut->getItemCount();
-
- mBackgroundImg->setAlpha(config.guiAlpha);
-
- mBoxHeight = mBackgroundImg->getHeight();
- mBoxWidth = mBackgroundImg->getWidth();
}
-ItemShortcutContainer::~ItemShortcutContainer()
-{
- mBackgroundImg->decRef();
- delete mItemPopup;
-}
+ItemShortcutContainer::~ItemShortcutContainer() = default;
void ItemShortcutContainer::draw(gcn::Graphics *graphics)
{
- if (config.guiAlpha != mAlpha)
- {
- mAlpha = config.guiAlpha;
- mBackgroundImg->setAlpha(mAlpha);
- }
-
auto *g = static_cast<Graphics*>(graphics);
+ auto theme = gui->getTheme();
+ auto &skin = theme->getSkin(SkinType::ShortcutBox);
graphics->setFont(getFont());
for (int i = 0; i < mMaxItems; i++)
{
- const int itemX = (i % mGridWidth) * mBoxWidth;
- const int itemY = (i / mGridWidth) * mBoxHeight;
-
- g->drawImage(mBackgroundImg, itemX, itemY);
+ WidgetState state;
+ state.x = (i % mGridWidth) * mBoxWidth;
+ state.y = (i / mGridWidth) * mBoxHeight;
+ skin.draw(g, state);
// Draw item keyboard shortcut.
const char *key = SDL_GetKeyName(
keyboard.getKeyValue(KeyboardConfig::KEY_SHORTCUT_1 + i));
graphics->setColor(Theme::getThemeColor(Theme::TEXT));
- g->drawText(key, itemX + 2, itemY + 2, gcn::Graphics::LEFT);
+ g->drawText(key,
+ state.x + skin.padding + 2,
+ state.y + skin.padding + 2,
+ gcn::Graphics::LEFT);
- if (itemShortcut->getItem(i) < 0)
+ const int itemId = itemShortcut->getItem(i);
+ if (itemId < 0)
continue;
- Item *item =
- PlayerInfo::getInventory()->findItem(itemShortcut->getItem(i));
-
- if (item)
+ if (Item *item = PlayerInfo::getInventory()->findItem(itemId))
{
// Draw item icon.
- Image* image = item->getImage();
-
- if (image)
+ if (Image *image = item->getImage())
{
std::string caption;
if (item->getQuantity() > 1)
@@ -105,11 +85,13 @@ void ItemShortcutContainer::draw(gcn::Graphics *graphics)
caption = "Eq.";
image->setAlpha(1.0f);
- g->drawImage(image, itemX, itemY);
+ g->drawImage(image, state.x + skin.padding, state.y + skin.padding);
if (item->isEquipped())
g->setColor(Theme::getThemeColor(Theme::ITEM_EQUIPPED));
- g->drawText(caption, itemX + mBoxWidth / 2,
- itemY + mBoxHeight - 14, gcn::Graphics::CENTER);
+ g->drawText(caption,
+ state.x + mBoxWidth / 2,
+ state.y + mBoxHeight - 14,
+ gcn::Graphics::CENTER);
}
}
}
@@ -117,7 +99,7 @@ void ItemShortcutContainer::draw(gcn::Graphics *graphics)
if (mItemMoved)
{
// Draw the item image being dragged by the cursor.
- if (Image* image = mItemMoved->getImage())
+ if (Image *image = mItemMoved->getImage())
{
const int tPosX = mCursorPosX - (image->getWidth() / 2);
const int tPosY = mCursorPosY - (image->getHeight() / 2);
@@ -137,23 +119,20 @@ void ItemShortcutContainer::mouseDragged(gcn::MouseEvent &event)
if (!mItemMoved && mItemClicked)
{
const int index = getIndexFromGrid(event.getX(), event.getY());
-
if (index == -1)
return;
const int itemId = itemShortcut->getItem(index);
-
if (itemId < 0)
return;
- Item *item = PlayerInfo::getInventory()->findItem(itemId);
-
- if (item)
+ if (Item *item = PlayerInfo::getInventory()->findItem(itemId))
{
mItemMoved = item;
itemShortcut->removeItem(index);
}
}
+
if (mItemMoved)
{
mCursorPosX = event.getX();
@@ -225,19 +204,7 @@ void ItemShortcutContainer::mouseReleased(gcn::MouseEvent &event)
// Show ItemTooltip
void ItemShortcutContainer::mouseMoved(gcn::MouseEvent &event)
{
- const int index = getIndexFromGrid(event.getX(), event.getY());
-
- if (index == -1)
- return;
-
- const int itemId = itemShortcut->getItem(index);
-
- if (itemId < 0)
- return;
-
- Item *item = PlayerInfo::getInventory()->findItem(itemId);
-
- if (item)
+ if (Item *item = getItemAt(event.getX(), event.getY()))
{
mItemPopup->setItem(item->getInfo());
mItemPopup->position(viewport->getMouseX(), viewport->getMouseY());
@@ -248,6 +215,19 @@ void ItemShortcutContainer::mouseMoved(gcn::MouseEvent &event)
}
}
+Item *ItemShortcutContainer::getItemAt(int x, int y) const
+{
+ const int index = getIndexFromGrid(x, y);
+ if (index == -1)
+ return nullptr;
+
+ const int itemId = itemShortcut->getItem(index);
+ if (itemId < 0)
+ return nullptr;
+
+ return PlayerInfo::getInventory()->findItem(itemId);
+}
+
// Hide ItemTooltip
void ItemShortcutContainer::mouseExited(gcn::MouseEvent &event)
{
diff --git a/src/gui/widgets/itemshortcutcontainer.h b/src/gui/widgets/itemshortcutcontainer.h
index 243920a0..a01857db 100644
--- a/src/gui/widgets/itemshortcutcontainer.h
+++ b/src/gui/widgets/itemshortcutcontainer.h
@@ -19,13 +19,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef ITEMSHORTCUTCONTAINER_H
-#define ITEMSHORTCUTCONTAINER_H
+#pragma once
#include "gui/widgets/shortcutcontainer.h"
#include <guichan/mouselistener.hpp>
+#include <memory>
+
class Image;
class Item;
class ItemPopup;
@@ -66,10 +67,10 @@ class ItemShortcutContainer : public ShortcutContainer
void mouseExited(gcn::MouseEvent &event) override;
void mouseMoved(gcn::MouseEvent &event) override;
+ Item *getItemAt(int x, int y) const;
+
bool mItemClicked = false;
Item *mItemMoved = nullptr;
- ItemPopup *mItemPopup;
+ std::unique_ptr<ItemPopup> mItemPopup;
};
-
-#endif
diff --git a/src/gui/widgets/label.cpp b/src/gui/widgets/label.cpp
index af5220ef..a2ed8820 100644
--- a/src/gui/widgets/label.cpp
+++ b/src/gui/widgets/label.cpp
@@ -21,8 +21,13 @@
#include "gui/widgets/label.h"
+#include "textrenderer.h"
+
#include "resources/theme.h"
+#include <guichan/exception.hpp>
+#include <guichan/font.hpp>
+
Label::Label()
{
setForegroundColor(Theme::getThemeColor(Theme::TEXT));
@@ -36,5 +41,33 @@ Label::Label(const std::string &caption) :
void Label::draw(gcn::Graphics *graphics)
{
- gcn::Label::draw(static_cast<gcn::Graphics*>(graphics));
+ int textX;
+ int textY = (getHeight() - getFont()->getHeight()) / 2;
+
+ switch (getAlignment())
+ {
+ case Graphics::LEFT:
+ textX = 0;
+ break;
+ case Graphics::CENTER:
+ textX = getWidth() / 2;
+ break;
+ case Graphics::RIGHT:
+ textX = getWidth();
+ break;
+ default:
+ throw GCN_EXCEPTION("Unknown alignment.");
+ }
+
+ TextRenderer::renderText(static_cast<Graphics *>(graphics),
+ getCaption(),
+ textX,
+ textY,
+ getAlignment(),
+ getForegroundColor(),
+ getFont(),
+ mOutlineColor.has_value(),
+ mShadowColor.has_value(),
+ mOutlineColor,
+ mShadowColor);
}
diff --git a/src/gui/widgets/label.h b/src/gui/widgets/label.h
index cb7a8b1c..85bcbe23 100644
--- a/src/gui/widgets/label.h
+++ b/src/gui/widgets/label.h
@@ -19,14 +19,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef LABEL_H
-#define LABEL_H
+#pragma once
#include <guichan/widgets/label.hpp>
+#include <optional>
/**
* Label widget. Same as the Guichan label but modified to use the palette
- * system.
+ * system and support outlines and shadows.
*
* \ingroup GUI
*/
@@ -42,9 +42,31 @@ class Label : public gcn::Label
Label(const std::string &caption);
/**
+ * Sets the color of the outline.
+ */
+ void setOutlineColor(std::optional<gcn::Color> color);
+
+ /**
+ * Sets the color of the shadow.
+ */
+ void setShadowColor(std::optional<gcn::Color> color);
+
+ /**
* Draws the label.
*/
void draw(gcn::Graphics *graphics) override;
+
+ private:
+ std::optional<gcn::Color> mOutlineColor;
+ std::optional<gcn::Color> mShadowColor;
};
-#endif
+inline void Label::setOutlineColor(std::optional<gcn::Color> color)
+{
+ mOutlineColor = color;
+}
+
+inline void Label::setShadowColor(std::optional<gcn::Color> color)
+{
+ mShadowColor = color;
+}
diff --git a/src/gui/widgets/layout.h b/src/gui/widgets/layout.h
index 4e4b28c5..42f08758 100644
--- a/src/gui/widgets/layout.h
+++ b/src/gui/widgets/layout.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef WIDGET_LAYOUT_H
-#define WIDGET_LAYOUT_H
+#pragma once
#include <guichan/widgets/container.hpp>
@@ -168,9 +167,12 @@ class LayoutCell
};
LayoutCell() = default;
-
~LayoutCell();
+ // Copy not allowed, as the cell may own an array.
+ LayoutCell(LayoutCell const &) = delete;
+ LayoutCell &operator=(LayoutCell const &) = delete;
+
/**
* Sets the padding around the cell content.
*/
@@ -232,10 +234,6 @@ class LayoutCell
void computeSizes();
private:
- // Copy not allowed, as the cell may own an array.
- LayoutCell(LayoutCell const &);
- LayoutCell &operator=(LayoutCell const &);
-
union
{
gcn::Widget *mWidget;
@@ -310,5 +308,3 @@ class Layout : public LayoutCell
private:
bool mComputed;
};
-
-#endif // WIDGET_LAYOUT_H
diff --git a/src/gui/widgets/layouthelper.h b/src/gui/widgets/layouthelper.h
index 26360a9a..ad01c565 100644
--- a/src/gui/widgets/layouthelper.h
+++ b/src/gui/widgets/layouthelper.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef LAYOUTHELPER_H
-#define LAYOUTHELPER_H
+#pragma once
#include "gui/widgets/layout.h"
@@ -74,5 +73,3 @@ class LayoutHelper : public gcn::WidgetListener
Layout mLayout; /**< Layout handler */
gcn::Container *mContainer; /**< Managed container */
};
-
-#endif // LAYOUTHELPER_H
diff --git a/src/gui/widgets/linkhandler.h b/src/gui/widgets/linkhandler.h
index 33263a25..48b182a1 100644
--- a/src/gui/widgets/linkhandler.h
+++ b/src/gui/widgets/linkhandler.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef LINK_HANDLER_H
-#define LINK_HANDLER_H
+#pragma once
#include <string>
@@ -35,5 +34,3 @@ class LinkHandler
virtual void handleLink(const std::string &link) = 0;
};
-
-#endif
diff --git a/src/gui/widgets/listbox.cpp b/src/gui/widgets/listbox.cpp
index 55f0f422..112de232 100644
--- a/src/gui/widgets/listbox.cpp
+++ b/src/gui/widgets/listbox.cpp
@@ -21,8 +21,7 @@
#include "gui/widgets/listbox.h"
-#include "configuration.h"
-
+#include "gui/gui.h"
#include "gui/sdlinput.h"
#include "resources/theme.h"
@@ -32,39 +31,29 @@
#include <guichan/key.hpp>
#include <guichan/listmodel.hpp>
-float ListBox::mAlpha = 1.0;
-
ListBox::ListBox(gcn::ListModel *listModel):
gcn::ListBox(listModel)
{
}
-void ListBox::updateAlpha()
-{
- float alpha = std::max(config.guiAlpha,
- Theme::instance()->getMinimumOpacity());
-
- if (mAlpha != alpha)
- mAlpha = alpha;
-}
-
void ListBox::draw(gcn::Graphics *graphics)
{
if (!mListModel)
return;
- updateAlpha();
-
- graphics->setColor(Theme::getThemeColor(Theme::HIGHLIGHT,
- (int) (mAlpha * 255.0f)));
graphics->setFont(getFont());
const int height = getRowHeight();
// Draw filled rectangle around the selected list element
if (mSelected >= 0)
+ {
+ auto highlightColor = Theme::getThemeColor(Theme::HIGHLIGHT);
+ highlightColor.a = gui->getTheme()->getGuiAlpha();
+ graphics->setColor(highlightColor);
graphics->fillRectangle(gcn::Rectangle(0, height * mSelected,
getWidth(), height));
+ }
// Draw the list elements
graphics->setColor(Theme::getThemeColor(Theme::TEXT));
diff --git a/src/gui/widgets/listbox.h b/src/gui/widgets/listbox.h
index d16256b1..40bc2fbc 100644
--- a/src/gui/widgets/listbox.h
+++ b/src/gui/widgets/listbox.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef LISTBOX_H
-#define LISTBOX_H
+#pragma once
#include <guichan/widgets/listbox.hpp>
@@ -43,10 +42,8 @@ class ListBox : public gcn::ListBox
*/
void draw(gcn::Graphics *graphics) override;
- /**
- * Update the alpha value to the graphic components.
- */
- static void updateAlpha();
+ // Overridden to disable drawing of the frame
+ void drawFrame(gcn::Graphics *graphics) override {}
// Inherited from KeyListener
@@ -61,9 +58,4 @@ class ListBox : public gcn::ListBox
void mouseWheelMovedDown(gcn::MouseEvent& mouseEvent) override;
void mouseDragged(gcn::MouseEvent &event) override;
-
- protected:
- static float mAlpha;
};
-
-#endif
diff --git a/src/gui/widgets/passwordfield.h b/src/gui/widgets/passwordfield.h
index 4bed0e05..36964843 100644
--- a/src/gui/widgets/passwordfield.h
+++ b/src/gui/widgets/passwordfield.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef PASSWORDFIELD_H
-#define PASSWORDFIELD_H
+#pragma once
#include "textfield.h"
@@ -42,5 +41,3 @@ class PasswordField : public TextField
*/
void draw(gcn::Graphics *graphics) override;
};
-
-#endif
diff --git a/src/gui/widgets/playerbox.cpp b/src/gui/widgets/playerbox.cpp
index 3bdd6bd1..f251035d 100644
--- a/src/gui/widgets/playerbox.cpp
+++ b/src/gui/widgets/playerbox.cpp
@@ -22,86 +22,22 @@
#include "gui/widgets/playerbox.h"
#include "being.h"
-#include "configuration.h"
#include "graphics.h"
-#include "resources/image.h"
-#include "resources/theme.h"
-
-#include "utils/dtor.h"
-
-int PlayerBox::instances = 0;
-float PlayerBox::mAlpha = 1.0;
-ImageRect PlayerBox::background;
-
-PlayerBox::PlayerBox(const Being *being):
- mBeing(being)
+PlayerBox::PlayerBox(const Being *being)
+ : mBeing(being)
{
- setFrameSize(2);
-
- if (instances == 0)
- {
- // Load the background skin
- Image *textbox = Theme::getImageFromTheme("deepbox.png");
- int bggridx[4] = {0, 3, 28, 31};
- int bggridy[4] = {0, 3, 28, 31};
- int a = 0;
-
- for (int y = 0; y < 3; y++)
- {
- for (int x = 0; x < 3; x++)
- {
- background.grid[a] = textbox->getSubImage(
- bggridx[x], bggridy[y],
- bggridx[x + 1] - bggridx[x] + 1,
- bggridy[y + 1] - bggridy[y] + 1);
- a++;
- }
- }
-
- background.setAlpha(config.guiAlpha);
-
- textbox->decRef();
- }
-
- instances++;
-}
-
-PlayerBox::~PlayerBox()
-{
- instances--;
-
- mBeing = nullptr;
-
- if (instances == 0)
- {
- std::for_each(background.grid, background.grid + 9, dtor<Image*>());
- }
}
void PlayerBox::draw(gcn::Graphics *graphics)
{
+ ScrollArea::draw(graphics);
+
if (mBeing)
{
// Draw character
- const int bs = getFrameSize();
- const int x = getWidth() / 2 + bs;
- const int y = getHeight() - bs;
+ const int x = getWidth() / 2;
+ const int y = (getHeight() + mBeing->getHeight()) / 2 - 12;
mBeing->drawSpriteAt(static_cast<Graphics*>(graphics), x, y);
}
-
- if (config.guiAlpha != mAlpha)
- {
- mAlpha = config.guiAlpha;
- background.setAlpha(config.guiAlpha);
- }
-}
-
-void PlayerBox::drawFrame(gcn::Graphics *graphics)
-{
- const int bs = getFrameSize();
- const int w = getWidth() + bs * 2;
- const int h = getHeight() + bs * 2;
-
- static_cast<Graphics*>(graphics)->drawImageRect(0, 0, w, h, background);
}
diff --git a/src/gui/widgets/playerbox.h b/src/gui/widgets/playerbox.h
index 68dd670e..39392c63 100644
--- a/src/gui/widgets/playerbox.h
+++ b/src/gui/widgets/playerbox.h
@@ -19,20 +19,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef PLAYERBOX_H
-#define PLAYERBOX_H
+#pragma once
-#include <guichan/widgets/scrollarea.hpp>
+#include "scrollarea.h"
class Being;
-class ImageRect;
/**
* A box showing a player character.
*
* \ingroup GUI
*/
-class PlayerBox : public gcn::ScrollArea
+class PlayerBox : public ScrollArea
{
public:
/**
@@ -41,8 +39,6 @@ class PlayerBox : public gcn::ScrollArea
*/
PlayerBox(const Being *being = nullptr);
- ~PlayerBox() override;
-
/**
* Sets a new player character to be displayed by this box. Setting the
* player to <code>NULL</code> causes the box not to draw any
@@ -52,21 +48,10 @@ class PlayerBox : public gcn::ScrollArea
{ mBeing = being; }
/**
- * Draws the scroll area.
+ * Draws the scroll area and the player.
*/
void draw(gcn::Graphics *graphics) override;
- /**
- * Draws the background and border of the scroll area.
- */
- void drawFrame(gcn::Graphics *graphics) override;
-
private:
const Being *mBeing; /**< The character used for display */
-
- static float mAlpha;
- static int instances;
- static ImageRect background;
};
-
-#endif
diff --git a/src/gui/widgets/popup.cpp b/src/gui/widgets/popup.cpp
index 94d8cf85..b245b9e6 100644
--- a/src/gui/widgets/popup.cpp
+++ b/src/gui/widgets/popup.cpp
@@ -22,31 +22,32 @@
#include "gui/widgets/popup.h"
+#include "browserbox.h"
#include "graphics.h"
#include "log.h"
+#include "textbox.h"
+#include "gui/gui.h"
#include "gui/viewport.h"
-
+#include "gui/widgets/label.h"
#include "gui/widgets/windowcontainer.h"
-#include "resources/theme.h"
-
#include <guichan/exception.hpp>
-Popup::Popup(const std::string &name, const std::string &skin):
- mPopupName(name),
- mMaxWidth(graphics->getWidth()),
- mMaxHeight(graphics->getHeight())
+Popup::Popup(const std::string &name, SkinType skinType)
+ : mPopupName(name)
+ , mMaxWidth(graphics->getWidth())
+ , mMaxHeight(graphics->getHeight())
+ , mSkinType(skinType)
{
logger->log("Popup::Popup(\"%s\")", name.c_str());
if (!windowContainer)
throw GCN_EXCEPTION("Popup::Popup(): no windowContainer set");
- setPadding(6);
-
- // Loads the skin
- mSkin = Theme::instance()->load(skin);
+ auto &skin = getSkin();
+ setFrameSize(skin.frameSize);
+ setPadding(skin.padding);
// Add this window to the window container
windowContainer->add(this);
@@ -58,8 +59,6 @@ Popup::Popup(const std::string &name, const std::string &skin):
Popup::~Popup()
{
logger->log("Popup::~Popup(\"%s\")", mPopupName.c_str());
-
- mSkin->instances--;
}
void Popup::setWindowContainer(WindowContainer *wc)
@@ -67,15 +66,57 @@ void Popup::setWindowContainer(WindowContainer *wc)
windowContainer = wc;
}
-void Popup::draw(gcn::Graphics *graphics)
+void Popup::add(gcn::Widget *widget)
+{
+ Container::add(widget);
+ widgetAdded(widget);
+}
+
+void Popup::add(gcn::Widget *widget, int x, int y)
+{
+ Container::add(widget, x, y);
+ widgetAdded(widget);
+}
+
+void Popup::widgetAdded(gcn::Widget *widget) const
{
- auto *g = static_cast<Graphics*>(graphics);
+ if (const int paletteId = getSkin().palette)
+ {
+ if (auto browserBox = dynamic_cast<BrowserBox*>(widget))
+ {
+ browserBox->setPalette(paletteId);
+ }
+ else if (auto label = dynamic_cast<Label*>(widget))
+ {
+ auto &palette = gui->getTheme()->getPalette(paletteId);
+ label->setForegroundColor(palette.getColor(Theme::TEXT));
+ label->setOutlineColor(palette.getOutlineColor(Theme::TEXT));
+ }
+ else if (auto textBox = dynamic_cast<TextBox*>(widget))
+ {
+ auto &palette = gui->getTheme()->getPalette(paletteId);
+ textBox->setTextColor(&palette.getColor(Theme::TEXT));
+ textBox->setOutlineColor(palette.getOutlineColor(Theme::TEXT));
+ }
+ }
+}
- g->drawImageRect(0, 0, getWidth(), getHeight(), mSkin->getBorder());
+void Popup::draw(gcn::Graphics *graphics)
+{
+ if (getFrameSize() == 0)
+ drawFrame(graphics);
drawChildren(graphics);
}
+void Popup::drawFrame(gcn::Graphics *graphics)
+{
+ WidgetState state(this);
+ state.width += getFrameSize() * 2;
+ state.height += getFrameSize() * 2;
+ getSkin().draw(static_cast<Graphics *>(graphics), state);
+}
+
gcn::Rectangle Popup::getChildrenArea()
{
return gcn::Rectangle(getPadding(), getPadding(),
@@ -116,12 +157,12 @@ void Popup::setLocationRelativeTo(gcn::Widget *widget)
void Popup::setMinWidth(int width)
{
- mMinWidth = std::max(width, mSkin->getMinWidth());
+ mMinWidth = std::max(getSkin().getMinWidth(), width);
}
void Popup::setMinHeight(int height)
{
- mMinHeight = std::max(height, mSkin->getMinHeight());
+ mMinHeight = std::max(getSkin().getMinHeight(), height);
}
void Popup::setMaxWidth(int width)
@@ -156,6 +197,11 @@ void Popup::position(int x, int y)
requestMoveToTop();
}
+const Skin &Popup::getSkin() const
+{
+ return gui->getTheme()->getSkin(mSkinType);
+}
+
void Popup::mouseMoved(gcn::MouseEvent &event)
{
if (viewport)
diff --git a/src/gui/widgets/popup.h b/src/gui/widgets/popup.h
index c77bf814..b88cafc9 100644
--- a/src/gui/widgets/popup.h
+++ b/src/gui/widgets/popup.h
@@ -20,12 +20,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef POPUP_H
-#define POPUP_H
+#pragma once
#include "guichanfwd.h"
#include "gui/widgets/container.h"
+#include "resources/theme.h"
#include <guichan/mouselistener.hpp>
@@ -53,10 +53,10 @@ class Popup : public Container, public gcn::MouseListener
*
* @param name A human readable name for the popup. Only useful for
* debugging purposes.
- * @param skin The location where the Popup's skin XML can be found.
+ * @param skinType The skin type used when drawing the popup.
*/
- Popup(const std::string &name = std::string(),
- const std::string &skin = "window.xml");
+ explicit Popup(const std::string &name = std::string(),
+ SkinType skinType = SkinType::Popup);
/**
* Destructor. Deletes all the added widgets.
@@ -68,12 +68,21 @@ class Popup : public Container, public gcn::MouseListener
*/
static void setWindowContainer(WindowContainer *windowContainer);
+ // Container interface
+ void add(gcn::Widget *widget) override;
+ void add(gcn::Widget *widget, int x, int y) override;
+
/**
* Draws the popup.
*/
void draw(gcn::Graphics *graphics) override;
/**
+ * Draws the popup frame.
+ */
+ void drawFrame(gcn::Graphics *graphics) override;
+
+ /**
* Sets the size of this popup.
*/
void setContentSize(int width, int height);
@@ -151,15 +160,20 @@ class Popup : public Container, public gcn::MouseListener
*/
void position(int x, int y);
+ /**
+ * Returns the Skin used by this popup.
+ */
+ const Skin &getSkin() const;
+
private:
- std::string mPopupName; /**< Name of the popup */
- int mMinWidth = 100; /**< Minimum popup width */
- int mMinHeight = 40; /**< Minimum popup height */
- int mMaxWidth; /**< Maximum popup width */
- int mMaxHeight; /**< Maximum popup height */
- int mPadding; /**< Holds the padding of the popup. */
-
- Skin *mSkin; /**< Skin in use by this popup */
-};
+ void widgetAdded(gcn::Widget *widget) const;
-#endif
+ std::string mPopupName; /**< Name of the popup */
+ int mMinWidth = 100; /**< Minimum popup width */
+ int mMinHeight = 40; /**< Minimum popup height */
+ int mMaxWidth; /**< Maximum popup width */
+ int mMaxHeight; /**< Maximum popup height */
+ int mPadding; /**< Holds the padding of the popup. */
+
+ SkinType mSkinType; /**< The skin type used when drawing the popup widget. */
+};
diff --git a/src/gui/widgets/progressbar.cpp b/src/gui/widgets/progressbar.cpp
index 9d41d1af..5cf1b05a 100644
--- a/src/gui/widgets/progressbar.cpp
+++ b/src/gui/widgets/progressbar.cpp
@@ -21,23 +21,14 @@
#include "gui/widgets/progressbar.h"
-#include "configuration.h"
#include "graphics.h"
-#include "textrenderer.h"
#include "gui/gui.h"
-#include "resources/image.h"
#include "resources/theme.h"
-#include "utils/dtor.h"
-
#include <guichan/font.hpp>
-ImageRect ProgressBar::mBorder;
-int ProgressBar::mInstances = 0;
-float ProgressBar::mAlpha = 1.0;
-
ProgressBar::ProgressBar(float progress,
int width, int height,
int color):
@@ -53,36 +44,6 @@ ProgressBar::ProgressBar(float progress,
mProgress);
setSize(width, height);
-
- if (mInstances == 0)
- {
- Image *dBorders = Theme::getImageFromTheme("vscroll_grey.png");
- mBorder.grid[0] = dBorders->getSubImage(0, 0, 4, 4);
- mBorder.grid[1] = dBorders->getSubImage(4, 0, 3, 4);
- mBorder.grid[2] = dBorders->getSubImage(7, 0, 4, 4);
- mBorder.grid[3] = dBorders->getSubImage(0, 4, 4, 10);
- mBorder.grid[4] = dBorders->getSubImage(4, 4, 3, 10);
- mBorder.grid[5] = dBorders->getSubImage(7, 4, 4, 10);
- mBorder.grid[6] = dBorders->getSubImage(0, 15, 4, 4);
- mBorder.grid[7] = dBorders->getSubImage(4, 15, 3, 4);
- mBorder.grid[8] = dBorders->getSubImage(7, 15, 4, 4);
-
- mBorder.setAlpha(mAlpha);
-
- dBorders->decRef();
- }
-
- mInstances++;
-}
-
-ProgressBar::~ProgressBar()
-{
- mInstances--;
-
- if (mInstances == 0)
- {
- std::for_each(mBorder.grid, mBorder.grid + 9, dtor<Image*>());
- }
}
void ProgressBar::logic()
@@ -114,30 +75,19 @@ void ProgressBar::logic()
}
}
-void ProgressBar::updateAlpha()
-{
- float alpha = std::max(config.guiAlpha,
- Theme::instance()->getMinimumOpacity());
-
- if (mAlpha != alpha)
- {
- mAlpha = alpha;
- mBorder.setAlpha(mAlpha);
- }
-}
-
void ProgressBar::draw(gcn::Graphics *graphics)
{
- updateAlpha();
-
- mColor.a = (int) (mAlpha * 255);
+ mColor.a = gui->getTheme()->getGuiAlpha();
gcn::Rectangle rect = getDimension();
rect.x = 0;
rect.y = 0;
- render(static_cast<Graphics*>(graphics), rect, mColor,
- mProgress, mText);
+ gui->getTheme()->drawProgressBar(static_cast<Graphics *>(graphics),
+ rect,
+ mColor,
+ mProgress,
+ mText);
}
void ProgressBar::setProgress(float progress)
@@ -149,9 +99,7 @@ void ProgressBar::setProgress(float progress)
mProgress = p;
if (mProgressPalette >= 0)
- {
mColorToGo = Theme::getProgressColor(mProgressPalette, progress);
- }
}
void ProgressBar::setProgressPalette(int progressPalette)
@@ -160,9 +108,7 @@ void ProgressBar::setProgressPalette(int progressPalette)
mProgressPalette = progressPalette;
if (mProgressPalette != oldPalette && mProgressPalette >= 0)
- {
mColorToGo = Theme::getProgressColor(mProgressPalette, mProgressToGo);
- }
}
void ProgressBar::setColor(const gcn::Color &color)
@@ -172,37 +118,3 @@ void ProgressBar::setColor(const gcn::Color &color)
if (!mSmoothColorChange)
mColor = color;
}
-
-void ProgressBar::render(Graphics *graphics, const gcn::Rectangle &area,
- const gcn::Color &color, float progress,
- const std::string &text)
-{
- gcn::Font *oldFont = graphics->getFont();
- gcn::Color oldColor = graphics->getColor();
-
- graphics->drawImageRect(area, mBorder);
-
- // The bar
- if (progress > 0)
- {
- graphics->setColor(color);
- graphics->fillRectangle(gcn::Rectangle(area.x + 4, area.y + 4,
- (int) (progress * (area.width - 8)),
- area.height - 8));
- }
-
- // The label
- if (!text.empty())
- {
- const int textX = area.x + area.width / 2;
- const int textY = area.y + (area.height - boldFont->getHeight()) / 2;
-
- TextRenderer::renderText(graphics, text, textX, textY,
- gcn::Graphics::CENTER,
- Theme::getThemeColor(Theme::PROGRESS_BAR),
- gui->getFont(), true, false);
- }
-
- graphics->setFont(oldFont);
- graphics->setColor(oldColor);
-}
diff --git a/src/gui/widgets/progressbar.h b/src/gui/widgets/progressbar.h
index 2f9e665f..52904f5a 100644
--- a/src/gui/widgets/progressbar.h
+++ b/src/gui/widgets/progressbar.h
@@ -19,16 +19,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef PROGRESSBAR_H
-#define PROGRESSBAR_H
+#pragma once
#include <guichan/widget.hpp>
#include <string>
-class Graphics;
-class ImageRect;
-
/**
* A progress bar.
*
@@ -44,19 +40,12 @@ class ProgressBar : public gcn::Widget
int width = 40, int height = 7,
int color = -1);
- ~ProgressBar() override;
-
/**
* Performs progress bar logic (fading colors)
*/
void logic() override;
/**
- * Update the alpha value to the graphic components.
- */
- static void updateAlpha();
-
- /**
* Draws the progress bar.
*/
void draw(gcn::Graphics *graphics) override;
@@ -111,13 +100,6 @@ class ProgressBar : public gcn::Widget
void setSmoothColorChange(bool smoothColorChange)
{ mSmoothColorChange = smoothColorChange; }
- /**
- * Renders a progressbar with the given properties.
- */
- static void render(Graphics *graphics, const gcn::Rectangle &area,
- const gcn::Color &color, float progress,
- const std::string &text = std::string());
-
private:
float mProgress, mProgressToGo;
bool mSmoothProgress = true;
@@ -128,12 +110,4 @@ class ProgressBar : public gcn::Widget
bool mSmoothColorChange = true;
std::string mText;
-
- static ImageRect mBorder;
- static int mInstances;
- static float mAlpha;
-
- static const gcn::Color TEXT_COLOR;
};
-
-#endif
diff --git a/src/gui/widgets/progressindicator.cpp b/src/gui/widgets/progressindicator.cpp
index 496bd8a1..ccd4fd54 100644
--- a/src/gui/widgets/progressindicator.cpp
+++ b/src/gui/widgets/progressindicator.cpp
@@ -21,10 +21,10 @@
#include "progressindicator.h"
#include "graphics.h"
+#include "gui/gui.h"
#include "simpleanimation.h"
#include "resources/animation.h"
-#include "resources/imageset.h"
#include "resources/resourcemanager.h"
#include "resources/theme.h"
@@ -32,12 +32,12 @@
ProgressIndicator::ProgressIndicator()
{
- ImageSet *images = Theme::getImageSetFromTheme("progress-indicator.png",
- 32, 32);
+ const std::string path = gui->getTheme()->resolvePath("progress-indicator.png");
+ mImageSet = ResourceManager::getInstance()->getImageSet(path, 32, 32);
Animation anim;
- for (size_t i = 0; i < images->size(); ++i)
- anim.addFrame(images->get(i), 100, 0, 0);
+ for (size_t i = 0; i < mImageSet->size(); ++i)
+ anim.addFrame(mImageSet->get(i), 100, 0, 0);
mIndicator = std::make_unique<SimpleAnimation>(std::move(anim));
diff --git a/src/gui/widgets/progressindicator.h b/src/gui/widgets/progressindicator.h
index 428bbd02..4a6ea339 100644
--- a/src/gui/widgets/progressindicator.h
+++ b/src/gui/widgets/progressindicator.h
@@ -18,8 +18,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef PROGRESSINDICATOR_H
-#define PROGRESSINDICATOR_H
+#pragma once
+
+#include "resources/imageset.h"
#include <guichan/widget.hpp>
@@ -42,6 +43,5 @@ public:
private:
std::unique_ptr<SimpleAnimation> mIndicator;
+ ResourceRef<ImageSet> mImageSet;
};
-
-#endif // PROGRESSINDICATOR_H
diff --git a/src/gui/widgets/radiobutton.cpp b/src/gui/widgets/radiobutton.cpp
index 92cdacd1..ceba78eb 100644
--- a/src/gui/widgets/radiobutton.cpp
+++ b/src/gui/widgets/radiobutton.cpp
@@ -21,109 +21,43 @@
#include "gui/widgets/radiobutton.h"
-#include "configuration.h"
-#include "graphics.h"
+#include "textrenderer.h"
-#include "resources/image.h"
+#include "gui/gui.h"
#include "resources/theme.h"
-int RadioButton::instances = 0;
-float RadioButton::mAlpha = 1.0;
-Image *RadioButton::radioNormal;
-Image *RadioButton::radioChecked;
-Image *RadioButton::radioDisabled;
-Image *RadioButton::radioDisabledChecked;
-Image *RadioButton::radioNormalHi;
-Image *RadioButton::radioCheckedHi;
-
-RadioButton::RadioButton(const std::string &caption, const std::string &group,
- bool marked):
- gcn::RadioButton(caption, group, marked)
+RadioButton::RadioButton(const std::string &caption,
+ const std::string &group,
+ bool marked)
+ : gcn::RadioButton(caption, group, marked)
{
- if (instances == 0)
- {
- radioNormal = Theme::getImageFromTheme("radioout.png");
- radioChecked = Theme::getImageFromTheme("radioin.png");
- radioDisabled = Theme::getImageFromTheme("radioout.png");
- radioDisabledChecked = Theme::getImageFromTheme("radioin.png");
- radioNormalHi = Theme::getImageFromTheme("radioout_highlight.png");
- radioCheckedHi = Theme::getImageFromTheme("radioin_highlight.png");
- radioNormal->setAlpha(mAlpha);
- radioChecked->setAlpha(mAlpha);
- radioDisabled->setAlpha(mAlpha);
- radioDisabledChecked->setAlpha(mAlpha);
- radioNormalHi->setAlpha(mAlpha);
- radioCheckedHi->setAlpha(mAlpha);
- }
-
- instances++;
+ auto &skin = gui->getTheme()->getSkin(SkinType::RadioButton);
+ setWidth(skin.getMinWidth() + 2 * skin.padding + skin.spacing + getFont()->getWidth(caption));
+ setHeight(skin.getMinHeight() + 2 * skin.padding);
}
-RadioButton::~RadioButton()
+void RadioButton::draw(gcn::Graphics* graphics)
{
- instances--;
+ WidgetState widgetState(this);
+ if (mHasMouse)
+ widgetState.flags |= STATE_HOVERED;
+ if (isSelected())
+ widgetState.flags |= STATE_SELECTED;
- if (instances == 0)
- {
- radioNormal->decRef();
- radioChecked->decRef();
- radioDisabled->decRef();
- radioDisabledChecked->decRef();
- radioNormalHi->decRef();
- radioCheckedHi->decRef();
- }
-}
+ auto &skin = gui->getTheme()->getSkin(SkinType::RadioButton);
+ skin.draw(static_cast<Graphics *>(graphics), widgetState);
-void RadioButton::drawBox(gcn::Graphics* graphics)
-{
- if (config.guiAlpha != mAlpha)
+ if (auto skinState = skin.getState(widgetState.flags))
{
- mAlpha = config.guiAlpha;
- radioNormal->setAlpha(mAlpha);
- radioChecked->setAlpha(mAlpha);
- radioDisabled->setAlpha(mAlpha);
- radioDisabledChecked->setAlpha(mAlpha);
- radioNormalHi->setAlpha(mAlpha);
- radioCheckedHi->setAlpha(mAlpha);
+ auto &textFormat = skinState->textFormat;
+ TextRenderer::renderText(static_cast<Graphics *>(graphics),
+ getCaption(),
+ skin.getMinWidth() + skin.padding + skin.spacing,
+ skin.padding,
+ Graphics::LEFT,
+ textFormat.bold ? boldFont : getFont(),
+ textFormat);
}
-
- Image *box = nullptr;
-
- if (isEnabled())
- if (isSelected())
- if (mHasMouse)
- box = radioCheckedHi;
- else
- box = radioChecked;
- else
- if (mHasMouse)
- box = radioNormalHi;
- else
- box = radioNormal;
- else
- if (isSelected())
- box = radioDisabledChecked;
- else
- box = radioDisabled;
-
- if (box)
- static_cast<Graphics*>(graphics)->drawImage(box, 2, 2);
-}
-
-void RadioButton::draw(gcn::Graphics* graphics)
-{
- graphics->pushClipArea(gcn::Rectangle(1, 1, getWidth() - 1,
- getHeight() - 1));
-
- drawBox(graphics);
-
- graphics->popClipArea();
-
- graphics->setFont(getFont());
- graphics->setColor(getForegroundColor());
-
- int h = getHeight() + getHeight() / 2;
- graphics->drawText(getCaption(), h - 2, 0);
}
void RadioButton::mouseEntered(gcn::MouseEvent& event)
diff --git a/src/gui/widgets/radiobutton.h b/src/gui/widgets/radiobutton.h
index 2a96ff6e..fda43d01 100644
--- a/src/gui/widgets/radiobutton.h
+++ b/src/gui/widgets/radiobutton.h
@@ -19,55 +19,40 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef RADIOBUTTON_H
-#define RADIOBUTTON_H
+#pragma once
#include <guichan/widgets/radiobutton.hpp>
-class Image;
-
/**
* Guichan based RadioButton with custom look
*/
class RadioButton : public gcn::RadioButton
{
public:
- RadioButton(const std::string &caption,const std::string &group,
- bool marked = false);
-
- ~RadioButton() override;
+ RadioButton(const std::string &caption,
+ const std::string &group,
+ bool marked = false);
/**
- * Draws the radiobutton, not the caption.
+ * Implementation of the draw method.
*/
- void drawBox(gcn::Graphics* graphics) override;
+ void draw(gcn::Graphics *graphics) override;
/**
- * Implementation of the draw methods.
- * Thus, avoiding the rhomb around the radio button.
+ * Overridden because box is drawn in RadioButton::draw.
*/
- void draw(gcn::Graphics* graphics) override;
+ void drawBox(gcn::Graphics *graphics) override {}
/**
* Called when the mouse enteres the widget area.
*/
- void mouseEntered(gcn::MouseEvent& event) override;
+ void mouseEntered(gcn::MouseEvent &event) override;
/**
* Called when the mouse leaves the widget area.
*/
- void mouseExited(gcn::MouseEvent& event) override;
+ void mouseExited(gcn::MouseEvent &event) override;
private:
- static int instances;
- static float mAlpha;
bool mHasMouse = false;
- static Image *radioNormal;
- static Image *radioChecked;
- static Image *radioDisabled;
- static Image *radioDisabledChecked;
- static Image *radioNormalHi;
- static Image *radioCheckedHi;
};
-
-#endif // RADIOBUTTON_H
diff --git a/src/gui/widgets/resizegrip.cpp b/src/gui/widgets/resizegrip.cpp
index dd29a977..0c5a7fb5 100644
--- a/src/gui/widgets/resizegrip.cpp
+++ b/src/gui/widgets/resizegrip.cpp
@@ -21,48 +21,22 @@
#include "gui/widgets/resizegrip.h"
-#include "configuration.h"
#include "graphics.h"
-#include "resources/image.h"
+#include "gui/gui.h"
#include "resources/theme.h"
#include <guichan/graphics.hpp>
-Image *ResizeGrip::gripImage = nullptr;
-int ResizeGrip::mInstances = 0;
-float ResizeGrip::mAlpha = 1.0;
-
-ResizeGrip::ResizeGrip(const std::string &image)
-{
- if (mInstances == 0)
- {
- // Load the grip image
- gripImage = Theme::getImageFromTheme(image);
- gripImage->setAlpha(mAlpha);
- }
-
- mInstances++;
-
- setWidth(gripImage->getWidth() + 2);
- setHeight(gripImage->getHeight() + 2);
-}
-
-ResizeGrip::~ResizeGrip()
+ResizeGrip::ResizeGrip()
{
- mInstances--;
-
- if (mInstances == 0)
- gripImage->decRef();
+ auto &skin = gui->getTheme()->getSkin(SkinType::ResizeGrip);
+ setSize(skin.width, skin.height);
}
void ResizeGrip::draw(gcn::Graphics *graphics)
{
- if (config.guiAlpha != mAlpha)
- {
- mAlpha = config.guiAlpha;
- gripImage->setAlpha(mAlpha);
- }
-
- static_cast<Graphics*>(graphics)->drawImage(gripImage, 0, 0);
+ gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics),
+ SkinType::ResizeGrip,
+ WidgetState(this));
}
diff --git a/src/gui/widgets/resizegrip.h b/src/gui/widgets/resizegrip.h
index d2f8ca4d..9b4e0611 100644
--- a/src/gui/widgets/resizegrip.h
+++ b/src/gui/widgets/resizegrip.h
@@ -19,13 +19,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef RESIZEGRIP_H
-#define RESIZEGRIP_H
+#pragma once
#include <guichan/widget.hpp>
-class Image;
-
/**
* Resize grip. The resize grip is part of a resizable Window. It relies on the
* fact that uncaught mouse events are automatically routed to the parent
@@ -36,19 +33,10 @@ class Image;
class ResizeGrip : public gcn::Widget
{
public:
- ResizeGrip(const std::string &image = "resize.png");
-
- ~ResizeGrip() override;
+ ResizeGrip();
/**
* Draws the resize grip.
*/
void draw(gcn::Graphics *graphics) override;
-
- private:
- static Image *gripImage; /**< Resize grip image */
- static int mInstances; /**< Number of resize grip instances */
- static float mAlpha;
};
-
-#endif
diff --git a/src/gui/widgets/scrollarea.cpp b/src/gui/widgets/scrollarea.cpp
index 225a231d..1dec34be 100644
--- a/src/gui/widgets/scrollarea.cpp
+++ b/src/gui/widgets/scrollarea.cpp
@@ -21,24 +21,14 @@
#include "gui/widgets/scrollarea.h"
-#include "configuration.h"
#include "graphics.h"
-#include "resources/image.h"
-#include "resources/theme.h"
+#include "gui/gui.h"
-#include "utils/dtor.h"
-
-int ScrollArea::instances = 0;
-float ScrollArea::mAlpha = 1.0;
-ImageRect ScrollArea::background;
-ImageRect ScrollArea::vMarker;
-ImageRect ScrollArea::vMarkerHi;
-Image *ScrollArea::buttons[4][2];
+#include <guichan/exception.hpp>
ScrollArea::ScrollArea()
{
- addWidgetListener(this);
init();
}
@@ -51,24 +41,11 @@ ScrollArea::ScrollArea(gcn::Widget *widget):
ScrollArea::~ScrollArea()
{
delete getContent();
+}
- instances--;
-
- if (instances == 0)
- {
- std::for_each(background.grid, background.grid + 9, dtor<Image*>());
- std::for_each(vMarker.grid, vMarker.grid + 9, dtor<Image*>());
- std::for_each(vMarkerHi.grid, vMarkerHi.grid + 9, dtor<Image*>());
-
- buttons[UP][0]->decRef();
- buttons[UP][1]->decRef();
- buttons[DOWN][0]->decRef();
- buttons[DOWN][1]->decRef();
- buttons[LEFT][0]->decRef();
- buttons[LEFT][1]->decRef();
- buttons[RIGHT][0]->decRef();
- buttons[RIGHT][1]->decRef();
- }
+void ScrollArea::setShowButtons(bool showButtons)
+{
+ mShowButtons = showButtons;
}
void ScrollArea::init()
@@ -76,83 +53,27 @@ void ScrollArea::init()
// Draw background by default
setOpaque(true);
- setUpButtonScrollAmount(2);
- setDownButtonScrollAmount(2);
- setLeftButtonScrollAmount(2);
- setRightButtonScrollAmount(2);
-
- if (instances == 0)
- {
- // Load the background skin
- Image *textbox = Theme::getImageFromTheme("deepbox.png");
- const int bggridx[4] = {0, 3, 28, 31};
- const int bggridy[4] = {0, 3, 28, 31};
- int a = 0;
-
- for (int y = 0; y < 3; y++)
- {
- for (int x = 0; x < 3; x++)
- {
- background.grid[a] = textbox->getSubImage(
- bggridx[x], bggridy[y],
- bggridx[x + 1] - bggridx[x] + 1,
- bggridy[y + 1] - bggridy[y] + 1);
- a++;
- }
- }
- background.setAlpha(config.guiAlpha);
+ auto theme = gui->getTheme();
- textbox->decRef();
+ int scrollBarWidth = theme->getSkin(SkinType::ScrollAreaVBar).width;
+ if (scrollBarWidth > 0)
+ setScrollbarWidth(scrollBarWidth);
- // Load vertical scrollbar skin
- Image *vscroll = Theme::getImageFromTheme("vscroll_grey.png");
- Image *vscrollHi = Theme::getImageFromTheme("vscroll_highlight.png");
+ auto &scrollAreaSkin = theme->getSkin(SkinType::ScrollArea);
+ setShowButtons(scrollAreaSkin.showButtons);
- int vsgridx[4] = {0, 4, 7, 11};
- int vsgridy[4] = {0, 4, 15, 19};
- a = 0;
-
- for (int y = 0; y < 3; y++)
- {
- for (int x = 0; x < 3; x++)
- {
- vMarker.grid[a] = vscroll->getSubImage(
- vsgridx[x], vsgridy[y],
- vsgridx[x + 1] - vsgridx[x],
- vsgridy[y + 1] - vsgridy[y]);
- vMarkerHi.grid[a] = vscrollHi->getSubImage(
- vsgridx[x], vsgridy[y],
- vsgridx[x + 1] - vsgridx[x],
- vsgridy[y + 1] - vsgridy[y]);
- a++;
- }
- }
+ if (auto content = getContent())
+ content->setFrameSize(scrollAreaSkin.padding);
- vMarker.setAlpha(config.guiAlpha);
- vMarkerHi.setAlpha(config.guiAlpha);
-
- vscroll->decRef();
- vscrollHi->decRef();
-
- buttons[UP][0] =
- Theme::getImageFromTheme("vscroll_up_default.png");
- buttons[DOWN][0] =
- Theme::getImageFromTheme("vscroll_down_default.png");
- buttons[LEFT][0] =
- Theme::getImageFromTheme("hscroll_left_default.png");
- buttons[RIGHT][0] =
- Theme::getImageFromTheme("hscroll_right_default.png");
- buttons[UP][1] =
- Theme::getImageFromTheme("vscroll_up_pressed.png");
- buttons[DOWN][1] =
- Theme::getImageFromTheme("vscroll_down_pressed.png");
- buttons[LEFT][1] =
- Theme::getImageFromTheme("hscroll_left_pressed.png");
- buttons[RIGHT][1] =
- Theme::getImageFromTheme("hscroll_right_pressed.png");
- }
+ // The base color is only used when rendering a square in the corner where
+ // the scrollbars meet. We disable rendering of this square by setting the
+ // base color to transparent.
+ setBaseColor(gcn::Color(0, 0, 0, 0));
- instances++;
+ setUpButtonScrollAmount(5);
+ setDownButtonScrollAmount(5);
+ setLeftButtonScrollAmount(5);
+ setRightButtonScrollAmount(5);
}
void ScrollArea::logic()
@@ -201,159 +122,237 @@ void ScrollArea::logic()
}
}
-void ScrollArea::updateAlpha()
+void ScrollArea::draw(gcn::Graphics *graphics)
{
- float alpha = std::max(config.guiAlpha,
- Theme::instance()->getMinimumOpacity());
-
- if (alpha != mAlpha)
- {
- mAlpha = alpha;
+ if (getFrameSize() == 0)
+ drawFrame(graphics);
- background.setAlpha(mAlpha);
- vMarker.setAlpha(mAlpha);
- vMarkerHi.setAlpha(mAlpha);
- }
+ gcn::ScrollArea::draw(graphics);
}
-void ScrollArea::draw(gcn::Graphics *graphics)
+void ScrollArea::drawFrame(gcn::Graphics *graphics)
{
- if (mVBarVisible)
- {
- drawUpButton(graphics);
- drawDownButton(graphics);
- drawVBar(graphics);
- drawVMarker(graphics);
- }
-
- if (mHBarVisible)
- {
- drawLeftButton(graphics);
- drawRightButton(graphics);
- drawHBar(graphics);
- drawHMarker(graphics);
- }
+ if (!mOpaque)
+ return;
- if (mHBarVisible && mVBarVisible)
- {
- graphics->setColor(getBaseColor());
- graphics->fillRectangle(gcn::Rectangle(getWidth() - mScrollbarWidth,
- getHeight() - mScrollbarWidth,
- mScrollbarWidth,
- mScrollbarWidth));
- }
+ const int bs = getFrameSize();
- updateAlpha();
+ WidgetState state(this);
+ state.width += bs * 2;
+ state.height += + bs * 2;
- drawChildren(graphics);
+ gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics), SkinType::ScrollArea, state);
}
-void ScrollArea::drawFrame(gcn::Graphics *graphics)
+void ScrollArea::drawChildren(gcn::Graphics *graphics)
{
- if (mOpaque)
- {
- const int bs = getFrameSize();
- const int w = getWidth() + bs * 2;
- const int h = getHeight() + bs * 2;
+ auto g = static_cast<Graphics*>(graphics);
+ g->pushClipRect(getChildrenArea());
- static_cast<Graphics*>(graphics)->
- drawImageRect(0, 0, w, h, background);
- }
+ gcn::ScrollArea::drawChildren(graphics);
+
+ g->popClipRect();
}
void ScrollArea::setOpaque(bool opaque)
{
mOpaque = opaque;
- setFrameSize(mOpaque ? 2 : 0);
+
+ auto &skin = gui->getTheme()->getSkin(SkinType::ScrollArea);
+ setFrameSize(mOpaque ? skin.frameSize : 0);
}
-void ScrollArea::drawButton(gcn::Graphics *graphics, BUTTON_DIR dir)
+void ScrollArea::drawBackground(gcn::Graphics *graphics)
{
- int state = 0;
- gcn::Rectangle dim;
+ // background is drawn as part of the frame instead
+}
- switch (dir)
- {
- case UP:
- state = mUpButtonPressed ? 1 : 0;
- dim = getUpButtonDimension();
- break;
- case DOWN:
- state = mDownButtonPressed ? 1 : 0;
- dim = getDownButtonDimension();
- break;
- case LEFT:
- state = mLeftButtonPressed ? 1 : 0;
- dim = getLeftButtonDimension();
- break;
- case RIGHT:
- state = mRightButtonPressed ? 1 : 0;
- dim = getRightButtonDimension();
- break;
- }
+static void drawButton(gcn::Graphics *graphics,
+ SkinType skinType,
+ bool pressed,
+ const gcn::Rectangle &dim)
+{
+ WidgetState state(dim);
+ if (pressed)
+ state.flags |= STATE_SELECTED;
- static_cast<Graphics*>(graphics)->
- drawImage(buttons[dir][state], dim.x, dim.y);
+ gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics), skinType, state);
}
void ScrollArea::drawUpButton(gcn::Graphics *graphics)
{
- drawButton(graphics, UP);
+ if (!mShowButtons)
+ return;
+
+ drawButton(graphics, SkinType::ButtonUp, mUpButtonPressed, getUpButtonDimension());
}
void ScrollArea::drawDownButton(gcn::Graphics *graphics)
{
- drawButton(graphics, DOWN);
+ if (!mShowButtons)
+ return;
+
+ drawButton(graphics, SkinType::ButtonDown, mDownButtonPressed, getDownButtonDimension());
}
void ScrollArea::drawLeftButton(gcn::Graphics *graphics)
{
- drawButton(graphics, LEFT);
+ if (!mShowButtons)
+ return;
+
+ drawButton(graphics, SkinType::ButtonLeft, mLeftButtonPressed, getLeftButtonDimension());
}
void ScrollArea::drawRightButton(gcn::Graphics *graphics)
{
- drawButton(graphics, RIGHT);
+ if (!mShowButtons)
+ return;
+
+ drawButton(graphics, SkinType::ButtonRight, mRightButtonPressed, getRightButtonDimension());
}
void ScrollArea::drawVBar(gcn::Graphics *graphics)
{
- const gcn::Rectangle dim = getVerticalBarDimension();
- graphics->setColor(gcn::Color(0, 0, 0, 32));
- graphics->fillRectangle(dim);
- graphics->setColor(gcn::Color(255, 255, 255));
+ WidgetState state(getVerticalBarDimension());
+ if (mHasMouse && (mX > (getWidth() - getScrollbarWidth())))
+ state.flags |= STATE_HOVERED;
+
+ gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics), SkinType::ScrollAreaVBar, state);
}
void ScrollArea::drawHBar(gcn::Graphics *graphics)
{
- const gcn::Rectangle dim = getHorizontalBarDimension();
- graphics->setColor(gcn::Color(0, 0, 0, 32));
- graphics->fillRectangle(dim);
- graphics->setColor(gcn::Color(255, 255, 255));
+ WidgetState state(getHorizontalBarDimension());
+ if (mHasMouse && (mY > (getHeight() - getScrollbarWidth())))
+ state.flags |= STATE_HOVERED;
+
+ gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics), SkinType::ScrollAreaHBar, state);
}
void ScrollArea::drawVMarker(gcn::Graphics *graphics)
{
- gcn::Rectangle dim = getVerticalMarkerDimension();
+ WidgetState state(getVerticalMarkerDimension());
+ if (state.height == 0)
+ return;
- if ((mHasMouse) && (mX > (getWidth() - getScrollbarWidth())))
- static_cast<Graphics*>(graphics)->
- drawImageRect(dim.x, dim.y, dim.width, dim.height, vMarkerHi);
- else
- static_cast<Graphics*>(graphics)->
- drawImageRect(dim.x, dim.y, dim.width, dim.height,vMarker);
+ if (mHasMouse && (mX > (getWidth() - getScrollbarWidth())))
+ state.flags |= STATE_HOVERED;
+
+ gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics), SkinType::ScrollAreaVMarker, state);
}
void ScrollArea::drawHMarker(gcn::Graphics *graphics)
{
- gcn::Rectangle dim = getHorizontalMarkerDimension();
+ WidgetState state(getHorizontalMarkerDimension());
+ if (state.width == 0)
+ return;
+
+ if (mHasMouse && (mY > (getHeight() - getScrollbarWidth())))
+ state.flags |= STATE_HOVERED;
+
+ gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics), SkinType::ScrollAreaHMarker, state);
+}
+
+/**
+ * Code copied from gcn::ScrollArea::checkPolicies to make sure it takes the
+ * frame size of the content into account.
+ */
+void ScrollArea::checkPolicies()
+{
+ int w = getWidth();
+ int h = getHeight();
- if ((mHasMouse) && (mY > (getHeight() - getScrollbarWidth())))
- static_cast<Graphics*>(graphics)->
- drawImageRect(dim.x, dim.y, dim.width, dim.height, vMarkerHi);
- else
- static_cast<Graphics*>(graphics)->
- drawImageRect(dim.x, dim.y, dim.width, dim.height, vMarker);
+ mHBarVisible = false;
+ mVBarVisible = false;
+
+ if (!getContent())
+ {
+ mHBarVisible = (mHPolicy == SHOW_ALWAYS);
+ mVBarVisible = (mVPolicy == SHOW_ALWAYS);
+ return;
+ }
+
+ const int contentFrameSize = getContent()->getFrameSize();
+ w -= 2 * contentFrameSize;
+ h -= 2 * contentFrameSize;
+
+ if (mHPolicy == SHOW_AUTO &&
+ mVPolicy == SHOW_AUTO)
+ {
+ if (getContent()->getWidth() <= w
+ && getContent()->getHeight() <= h)
+ {
+ mHBarVisible = false;
+ mVBarVisible = false;
+ }
+
+ if (getContent()->getWidth() > w)
+ {
+ mHBarVisible = true;
+ }
+
+ if ((getContent()->getHeight() > h)
+ || (mHBarVisible && getContent()->getHeight() > h - mScrollbarWidth))
+ {
+ mVBarVisible = true;
+ }
+
+ if (mVBarVisible && getContent()->getWidth() > w - mScrollbarWidth)
+ {
+ mHBarVisible = true;
+ }
+
+ return;
+ }
+
+ switch (mHPolicy)
+ {
+ case SHOW_NEVER:
+ mHBarVisible = false;
+ break;
+
+ case SHOW_ALWAYS:
+ mHBarVisible = true;
+ break;
+
+ case SHOW_AUTO:
+ if (mVPolicy == SHOW_NEVER)
+ {
+ mHBarVisible = getContent()->getWidth() > w;
+ }
+ else // (mVPolicy == SHOW_ALWAYS)
+ {
+ mHBarVisible = getContent()->getWidth() > w - mScrollbarWidth;
+ }
+ break;
+
+ default:
+ throw GCN_EXCEPTION("Horizontal scroll policy invalid.");
+ }
+
+ switch (mVPolicy)
+ {
+ case SHOW_NEVER:
+ mVBarVisible = false;
+ break;
+
+ case SHOW_ALWAYS:
+ mVBarVisible = true;
+ break;
+
+ case SHOW_AUTO:
+ if (mHPolicy == SHOW_NEVER)
+ {
+ mVBarVisible = getContent()->getHeight() > h;
+ }
+ else // (mHPolicy == SHOW_ALWAYS)
+ {
+ mVBarVisible = getContent()->getHeight() > h - mScrollbarWidth;
+ }
+ break;
+ default:
+ throw GCN_EXCEPTION("Vertical scroll policy invalid.");
+ }
}
void ScrollArea::mouseMoved(gcn::MouseEvent& event)
@@ -372,8 +371,299 @@ void ScrollArea::mouseExited(gcn::MouseEvent& event)
mHasMouse = false;
}
-void ScrollArea::widgetResized(const gcn::Event &event)
+/**
+ * Code copied from gcn::ScrollArea::mousePressed to make it call our custom
+ * getVerticalMarkerDimension and getHorizontalMarkerDimension functions.
+ */
+void ScrollArea::mousePressed(gcn::MouseEvent &mouseEvent)
{
- getContent()->setSize(getWidth() - 2 * getFrameSize(),
- getHeight() - 2 * getFrameSize());
+ int x = mouseEvent.getX();
+ int y = mouseEvent.getY();
+
+ if (getUpButtonDimension().isPointInRect(x, y))
+ {
+ setVerticalScrollAmount(getVerticalScrollAmount()
+ - mUpButtonScrollAmount);
+ mUpButtonPressed = true;
+ }
+ else if (getDownButtonDimension().isPointInRect(x, y))
+ {
+ setVerticalScrollAmount(getVerticalScrollAmount()
+ + mDownButtonScrollAmount);
+ mDownButtonPressed = true;
+ }
+ else if (getLeftButtonDimension().isPointInRect(x, y))
+ {
+ setHorizontalScrollAmount(getHorizontalScrollAmount()
+ - mLeftButtonScrollAmount);
+ mLeftButtonPressed = true;
+ }
+ else if (getRightButtonDimension().isPointInRect(x, y))
+ {
+ setHorizontalScrollAmount(getHorizontalScrollAmount()
+ + mRightButtonScrollAmount);
+ mRightButtonPressed = true;
+ }
+ else if (getVerticalMarkerDimension().isPointInRect(x, y))
+ {
+ mIsHorizontalMarkerDragged = false;
+ mIsVerticalMarkerDragged = true;
+
+ mVerticalMarkerDragOffset = y - getVerticalMarkerDimension().y;
+ }
+ else if (getVerticalBarDimension().isPointInRect(x,y))
+ {
+ if (y < getVerticalMarkerDimension().y)
+ {
+ setVerticalScrollAmount(getVerticalScrollAmount()
+ - (int)(getChildrenArea().height * 0.95));
+ }
+ else
+ {
+ setVerticalScrollAmount(getVerticalScrollAmount()
+ + (int)(getChildrenArea().height * 0.95));
+ }
+ }
+ else if (getHorizontalMarkerDimension().isPointInRect(x, y))
+ {
+ mIsHorizontalMarkerDragged = true;
+ mIsVerticalMarkerDragged = false;
+
+ mHorizontalMarkerDragOffset = x - getHorizontalMarkerDimension().x;
+ }
+ else if (getHorizontalBarDimension().isPointInRect(x,y))
+ {
+ if (x < getHorizontalMarkerDimension().x)
+ {
+ setHorizontalScrollAmount(getHorizontalScrollAmount()
+ - (int)(getChildrenArea().width * 0.95));
+ }
+ else
+ {
+ setHorizontalScrollAmount(getHorizontalScrollAmount()
+ + (int)(getChildrenArea().width * 0.95));
+ }
+ }
+}
+
+/**
+ * Code copied from gcn::ScrollArea::mouseDragged to make it call our custom
+ * getVerticalMarkerDimension and getHorizontalMarkerDimension functions.
+ */
+void ScrollArea::mouseDragged(gcn::MouseEvent &mouseEvent)
+{
+ if (mIsVerticalMarkerDragged)
+ {
+ int pos = mouseEvent.getY() - getVerticalBarDimension().y - mVerticalMarkerDragOffset;
+ int length = getVerticalMarkerDimension().height;
+
+ gcn::Rectangle barDim = getVerticalBarDimension();
+
+ if ((barDim.height - length) > 0)
+ {
+ setVerticalScrollAmount((getVerticalMaxScroll() * pos)
+ / (barDim.height - length));
+ }
+ else
+ {
+ setVerticalScrollAmount(0);
+ }
+ }
+
+ if (mIsHorizontalMarkerDragged)
+ {
+ int pos = mouseEvent.getX() - getHorizontalBarDimension().x - mHorizontalMarkerDragOffset;
+ int length = getHorizontalMarkerDimension().width;
+
+ gcn::Rectangle barDim = getHorizontalBarDimension();
+
+ if ((barDim.width - length) > 0)
+ {
+ setHorizontalScrollAmount((getHorizontalMaxScroll() * pos)
+ / (barDim.width - length));
+ }
+ else
+ {
+ setHorizontalScrollAmount(0);
+ }
+ }
+
+ mouseEvent.consume();
+}
+
+gcn::Rectangle ScrollArea::getUpButtonDimension()
+{
+ if (!mVBarVisible || !mShowButtons)
+ return gcn::Rectangle();
+
+ return gcn::Rectangle(getWidth() - mScrollbarWidth, 0, mScrollbarWidth, mScrollbarWidth);
+}
+
+gcn::Rectangle ScrollArea::getDownButtonDimension()
+{
+ if (!mVBarVisible || !mShowButtons)
+ return gcn::Rectangle();
+
+ gcn::Rectangle dim(getWidth() - mScrollbarWidth,
+ getHeight() - mScrollbarWidth,
+ mScrollbarWidth,
+ mScrollbarWidth);
+
+ if (mHBarVisible)
+ dim.y -= mScrollbarWidth;
+
+ return dim;
+}
+
+gcn::Rectangle ScrollArea::getLeftButtonDimension()
+{
+ if (!mHBarVisible || !mShowButtons)
+ return gcn::Rectangle();
+
+ return gcn::Rectangle(0, getHeight() - mScrollbarWidth, mScrollbarWidth, mScrollbarWidth);
+}
+
+gcn::Rectangle ScrollArea::getRightButtonDimension()
+{
+ if (!mHBarVisible || !mShowButtons)
+ return gcn::Rectangle();
+
+ gcn::Rectangle dim(getWidth() - mScrollbarWidth,
+ getHeight() - mScrollbarWidth,
+ mScrollbarWidth,
+ mScrollbarWidth);
+
+ if (mVBarVisible)
+ dim.x -= mScrollbarWidth;
+
+ return dim;
+}
+
+gcn::Rectangle ScrollArea::getVerticalBarDimension()
+{
+ if (!mVBarVisible)
+ return gcn::Rectangle();
+
+ gcn::Rectangle dim(getWidth() - mScrollbarWidth,
+ getUpButtonDimension().height,
+ mScrollbarWidth,
+ getHeight()
+ - getUpButtonDimension().height
+ - getDownButtonDimension().height);
+
+ if (mHBarVisible)
+ dim.height -= mScrollbarWidth;
+
+ if (dim.height < 0)
+ dim.height = 0;
+
+ return dim;
+}
+
+gcn::Rectangle ScrollArea::getHorizontalBarDimension()
+{
+ if (!mHBarVisible)
+ return gcn::Rectangle();
+
+ gcn::Rectangle dim(getLeftButtonDimension().width,
+ getHeight() - mScrollbarWidth,
+ getWidth()
+ - getLeftButtonDimension().width
+ - getRightButtonDimension().width,
+ mScrollbarWidth);
+
+ if (mVBarVisible)
+ dim.width -= mScrollbarWidth;
+
+ if (dim.width < 0)
+ dim.width = 0;
+
+ return dim;
+}
+
+static void getMarkerValues(int barSize,
+ int maxScroll, int scrollAmount,
+ int contentHeight, int viewHeight,
+ int fixedMarkerSize, int minMarkerSize,
+ int &markerSize, int &markerPos)
+{
+ if (fixedMarkerSize == 0)
+ {
+ if (contentHeight != 0 && contentHeight > viewHeight)
+ markerSize = std::max((barSize * viewHeight) / contentHeight, minMarkerSize);
+ else
+ markerSize = barSize;
+ }
+ else
+ {
+ if (contentHeight > viewHeight)
+ markerSize = fixedMarkerSize;
+ else
+ markerSize = 0;
+ }
+
+ // Hide the marker when it doesn't fit
+ if (markerSize > barSize)
+ markerSize = 0;
+
+ if (maxScroll != 0)
+ markerPos = ((barSize - markerSize) * scrollAmount + maxScroll / 2) / maxScroll;
+ else
+ markerPos = 0;
+}
+
+gcn::Rectangle ScrollArea::getVerticalMarkerDimension()
+{
+ if (!mVBarVisible)
+ return gcn::Rectangle();
+
+ auto &markerSkin = gui->getTheme()->getSkin(SkinType::ScrollAreaVMarker);
+ const gcn::Rectangle barDim = getVerticalBarDimension();
+
+ int contentHeight = 0;
+ if (auto content = getContent())
+ contentHeight = content->getHeight() + content->getFrameSize() * 2;
+
+ int length;
+ int pos;
+
+ getMarkerValues(barDim.height,
+ getVerticalMaxScroll(),
+ getVerticalScrollAmount(),
+ contentHeight,
+ getChildrenArea().height,
+ markerSkin.height,
+ mScrollbarWidth,
+ length,
+ pos);
+
+ return gcn::Rectangle(barDim.x, barDim.y + pos, mScrollbarWidth, length);
+}
+
+gcn::Rectangle ScrollArea::getHorizontalMarkerDimension()
+{
+ if (!mHBarVisible)
+ return gcn::Rectangle();
+
+ auto &markerSkin = gui->getTheme()->getSkin(SkinType::ScrollAreaHMarker);
+ const gcn::Rectangle barDim = getHorizontalBarDimension();
+
+ int contentWidth = 0;
+ if (auto content = getContent())
+ contentWidth = content->getWidth() + content->getFrameSize() * 2;
+
+ int length;
+ int pos;
+
+ getMarkerValues(barDim.width,
+ getHorizontalMaxScroll(),
+ getHorizontalScrollAmount(),
+ contentWidth,
+ getChildrenArea().width,
+ markerSkin.width,
+ mScrollbarWidth,
+ length,
+ pos);
+
+ return gcn::Rectangle(barDim.x + pos, barDim.y, length, mScrollbarWidth);
}
diff --git a/src/gui/widgets/scrollarea.h b/src/gui/widgets/scrollarea.h
index 2fae2d4b..0ba10578 100644
--- a/src/gui/widgets/scrollarea.h
+++ b/src/gui/widgets/scrollarea.h
@@ -19,14 +19,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SCROLLAREA_H
-#define SCROLLAREA_H
+#pragma once
#include <guichan/widgets/scrollarea.hpp>
-#include <guichan/widgetlistener.hpp>
-
-class Image;
-class ImageRect;
/**
* A scroll area.
@@ -35,9 +30,11 @@ class ImageRect;
* content. However, it won't delete a previously set content widget when
* setContent is called!
*
+ * Also overrides several functions to support fixed-size scroll bar markers.
+ *
* \ingroup GUI
*/
-class ScrollArea : public gcn::ScrollArea, public gcn::WidgetListener
+class ScrollArea : public gcn::ScrollArea
{
public:
/**
@@ -59,18 +56,18 @@ class ScrollArea : public gcn::ScrollArea, public gcn::WidgetListener
~ScrollArea() override;
/**
- * Logic function optionally adapts width or height of contents. This
- * depends on the scrollbar settings.
+ * Sets whether the scroll bar buttons are shown.
*/
- void logic() override;
+ void setShowButtons(bool showButtons);
/**
- * Update the alpha value to the graphic components.
+ * Logic function optionally adapts width or height of contents. This
+ * depends on the scrollbar settings.
*/
- static void updateAlpha();
+ void logic() override;
/**
- * Draws the scroll area.
+ * Overridden to draw the frame if its size is 0.
*/
void draw(gcn::Graphics *graphics) override;
@@ -80,6 +77,11 @@ class ScrollArea : public gcn::ScrollArea, public gcn::WidgetListener
void drawFrame(gcn::Graphics *graphics) override;
/**
+ * Applies clipping to the contents.
+ */
+ void drawChildren(gcn::Graphics *graphics) override;
+
+ /**
* Sets whether the widget should draw its background or not.
*/
void setOpaque(bool opaque);
@@ -92,34 +94,28 @@ class ScrollArea : public gcn::ScrollArea, public gcn::WidgetListener
/**
* Called when the mouse moves in the widget area.
*/
- void mouseMoved(gcn::MouseEvent& event) override;
+ void mouseMoved(gcn::MouseEvent &event) override;
/**
* Called when the mouse enteres the widget area.
*/
- void mouseEntered(gcn::MouseEvent& event) override;
+ void mouseEntered(gcn::MouseEvent &event) override;
/**
* Called when the mouse leaves the widget area.
*/
- void mouseExited(gcn::MouseEvent& event) override;
+ void mouseExited(gcn::MouseEvent &event) override;
- void widgetResized(const gcn::Event &event) override;
+ void mousePressed(gcn::MouseEvent &mouseEvent) override;
+ void mouseDragged(gcn::MouseEvent &mouseEvent) override;
protected:
- enum BUTTON_DIR {
- UP,
- DOWN,
- LEFT,
- RIGHT
- };
-
/**
* Initializes the scroll area.
*/
void init();
- void drawButton(gcn::Graphics *graphics, BUTTON_DIR dir);
+ void drawBackground(gcn::Graphics *graphics) override;
void drawUpButton(gcn::Graphics *graphics) override;
void drawDownButton(gcn::Graphics *graphics) override;
void drawLeftButton(gcn::Graphics *graphics) override;
@@ -129,17 +125,31 @@ class ScrollArea : public gcn::ScrollArea, public gcn::WidgetListener
void drawVMarker(gcn::Graphics *graphics) override;
void drawHMarker(gcn::Graphics *graphics) override;
- static int instances;
- static float mAlpha;
- static ImageRect background;
- static ImageRect vMarker;
- static ImageRect vMarkerHi;
- static Image *buttons[4][2];
+ void checkPolicies() override;
+
+ /**
+ * Shadowing these functions from gcn::ScrollArea with versions that
+ * support hiding the buttons. We need to make sure we always use these
+ * versions.
+ */
+ gcn::Rectangle getUpButtonDimension();
+ gcn::Rectangle getDownButtonDimension();
+ gcn::Rectangle getLeftButtonDimension();
+ gcn::Rectangle getRightButtonDimension();
+ gcn::Rectangle getVerticalBarDimension();
+ gcn::Rectangle getHorizontalBarDimension();
+
+ /**
+ * Shadowing these functions from gcn::ScrollArea with versions that
+ * supports fixed-size scroll bar markers. We need to make sure we
+ * always use these versions.
+ */
+ gcn::Rectangle getVerticalMarkerDimension();
+ gcn::Rectangle getHorizontalMarkerDimension();
int mX = 0;
int mY = 0;
bool mHasMouse = false;
bool mOpaque = true;
+ bool mShowButtons = true;
};
-
-#endif
diff --git a/src/gui/widgets/setuptab.h b/src/gui/widgets/setuptab.h
index 0cc35a98..78cef5b2 100644
--- a/src/gui/widgets/setuptab.h
+++ b/src/gui/widgets/setuptab.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GUI_SETUPTAB_H
-#define GUI_SETUPTAB_H
+#pragma once
#include "gui/widgets/container.h"
@@ -58,5 +57,3 @@ protected:
private:
std::string mName;
};
-
-#endif
diff --git a/src/gui/widgets/shopitems.h b/src/gui/widgets/shopitems.h
index e213f67c..1b6e1727 100644
--- a/src/gui/widgets/shopitems.h
+++ b/src/gui/widgets/shopitems.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SHOP_H
-#define SHOP_H
+#pragma once
#include <guichan/listmodel.hpp>
@@ -111,5 +110,3 @@ class ShopItems : public gcn::ListModel
/** Look for duplicate entries on addition. */
bool mMergeDuplicates;
};
-
-#endif // SHOP_H
diff --git a/src/gui/widgets/shoplistbox.cpp b/src/gui/widgets/shoplistbox.cpp
index 31c733a6..e2313c85 100644
--- a/src/gui/widgets/shoplistbox.cpp
+++ b/src/gui/widgets/shoplistbox.cpp
@@ -71,14 +71,13 @@ void ShopListBox::draw(gcn::Graphics *gcnGraphics)
return;
const int alpha = (int)(config.guiAlpha * 255.0f);
- const gcn::Color &highlightColor =
- Theme::getThemeColor(Theme::HIGHLIGHT, alpha);
- const gcn::Color &backgroundColor =
- Theme::getThemeColor(Theme::BACKGROUND, alpha);
- const gcn::Color &warningColor =
- Theme::getThemeColor(Theme::SHOP_WARNING, alpha);
- const gcn::Color &textColor =
- Theme::getThemeColor(Theme::TEXT);
+ auto highlightColor = Theme::getThemeColor(Theme::HIGHLIGHT);
+ auto backgroundColor = Theme::getThemeColor(Theme::BACKGROUND);
+ auto warningColor = Theme::getThemeColor(Theme::SHOP_WARNING);
+ auto textColor = Theme::getThemeColor(Theme::TEXT);
+ highlightColor.a = alpha;
+ backgroundColor.a = alpha;
+ warningColor.a = alpha;
auto *graphics = static_cast<Graphics*>(gcnGraphics);
@@ -168,8 +167,7 @@ void ShopListBox::mouseMoved(gcn::MouseEvent &event)
}
else
{
- Item *item = mShopItems->at(index);
- if (item)
+ if (Item *item = mShopItems->at(index))
{
mItemPopup->setItem(item->getInfo());
mItemPopup->position(viewport->getMouseX(), viewport->getMouseY());
diff --git a/src/gui/widgets/shoplistbox.h b/src/gui/widgets/shoplistbox.h
index 4dbd756b..f6a1b12a 100644
--- a/src/gui/widgets/shoplistbox.h
+++ b/src/gui/widgets/shoplistbox.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SHOPLISTBOX_H
-#define SHOPLISTBOX_H
+#pragma once
#include "gui/widgets/listbox.h"
@@ -97,5 +96,3 @@ class ShopListBox : public ListBox
bool mPriceCheck;
};
-
-#endif // SHOPLISTBOX_H
diff --git a/src/gui/widgets/shortcutcontainer.cpp b/src/gui/widgets/shortcutcontainer.cpp
index 5925752e..9271b1f4 100644
--- a/src/gui/widgets/shortcutcontainer.cpp
+++ b/src/gui/widgets/shortcutcontainer.cpp
@@ -21,10 +21,18 @@
#include "gui/widgets/shortcutcontainer.h"
-float ShortcutContainer::mAlpha = 1.0;
+#include "gui/gui.h"
+
+#include "resources/theme.h"
ShortcutContainer::ShortcutContainer()
{
+ addMouseListener(this);
+ addWidgetListener(this);
+
+ auto &skin = gui->getTheme()->getSkin(SkinType::ShortcutBox);
+ mBoxWidth = skin.width;
+ mBoxHeight = skin.height;
}
void ShortcutContainer::widgetResized(const gcn::Event &event)
diff --git a/src/gui/widgets/shortcutcontainer.h b/src/gui/widgets/shortcutcontainer.h
index cab20f27..35a88d7f 100644
--- a/src/gui/widgets/shortcutcontainer.h
+++ b/src/gui/widgets/shortcutcontainer.h
@@ -19,15 +19,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SHORTCUTCONTAINER_H
-#define SHORTCUTCONTAINER_H
+#pragma once
#include <guichan/mouselistener.hpp>
#include <guichan/widget.hpp>
#include <guichan/widgetlistener.hpp>
-class Image;
-
/**
* A generic shortcut container.
*
@@ -45,20 +42,18 @@ class ShortcutContainer : public gcn::Widget,
*/
void draw(gcn::Graphics *graphics) override = 0;
+ // Overridden to disable drawing of the frame
+ void drawFrame(gcn::Graphics *graphics) override {}
+
/**
* Invoked when a widget changes its size. This is used to determine
* the new height of the container.
*/
void widgetResized(const gcn::Event &event) override;
- int getMaxItems() const
- { return mMaxItems; }
-
- int getBoxWidth() const
- { return mBoxWidth; }
-
- int getBoxHeight() const
- { return mBoxHeight; }
+ int getMaxItems() const { return mMaxItems; }
+ int getBoxWidth() const { return mBoxWidth; }
+ int getBoxHeight() const { return mBoxHeight; }
protected:
/**
@@ -70,10 +65,6 @@ class ShortcutContainer : public gcn::Widget,
*/
int getIndexFromGrid(int pointX, int pointY) const;
- Image *mBackgroundImg;
-
- static float mAlpha;
-
int mMaxItems = 0;
int mBoxWidth = 0;
int mBoxHeight = 0;
@@ -82,5 +73,3 @@ class ShortcutContainer : public gcn::Widget,
int mGridWidth = 1;
int mGridHeight = 1;
};
-
-#endif
diff --git a/src/gui/widgets/slider.cpp b/src/gui/widgets/slider.cpp
index a7ba37e8..bad10c15 100644
--- a/src/gui/widgets/slider.cpp
+++ b/src/gui/widgets/slider.cpp
@@ -21,19 +21,11 @@
#include "gui/widgets/slider.h"
-#include "configuration.h"
#include "graphics.h"
-#include "resources/image.h"
+#include "gui/gui.h"
#include "resources/theme.h"
-Image *Slider::hStart, *Slider::hMid, *Slider::hEnd, *Slider::hGrip;
-Image *Slider::vStart, *Slider::vMid, *Slider::vEnd, *Slider::vGrip;
-Image *Slider::hStartHi, *Slider::hMidHi, *Slider::hEndHi, *Slider::hGripHi;
-Image *Slider::vStartHi, *Slider::vMidHi, *Slider::vEndHi, *Slider::vGripHi;
-float Slider::mAlpha = 1.0;
-int Slider::mInstances = 0;
-
Slider::Slider(double scaleEnd):
gcn::Slider(scaleEnd)
{
@@ -46,154 +38,30 @@ Slider::Slider(double scaleStart, double scaleEnd):
init();
}
-Slider::~Slider()
-{
- mInstances--;
-
- if (mInstances == 0)
- {
- delete hStart;
- delete hMid;
- delete hEnd;
- delete hGrip;
- delete vStart;
- delete vMid;
- delete vEnd;
- delete vGrip;
- delete hStartHi;
- delete hMidHi;
- delete hEndHi;
- delete hGripHi;
- delete vStartHi;
- delete vMidHi;
- delete vEndHi;
- delete vGripHi;
- }
-}
-
void Slider::init()
{
- int x, y, w, h,o1,o2;
- setFrameSize(0);
-
- // Load resources
- if (mInstances == 0)
- {
- Image *slider = Theme::getImageFromTheme("slider.png");
- Image *sliderHi = Theme::getImageFromTheme("slider_hilight.png");
-
- x = 0; y = 0;
- w = 15; h = 6;
- o1 = 4; o2 = 11;
- hStart = slider->getSubImage(x, y, o1 - x, h);
- hMid = slider->getSubImage(o1, y, o2 - o1, h);
- hEnd = slider->getSubImage(o2, y, w - o2 + x, h);
- hStartHi = sliderHi->getSubImage(x, y, o1 - x, h);
- hMidHi = sliderHi->getSubImage(o1, y, o2 - o1, h);
- hEndHi = sliderHi->getSubImage(o2, y, w - o2 + x, h);
-
- x = 6; y = 8;
- w = 9; h = 10;
- hGrip = slider->getSubImage(x, y, w, h);
- hGripHi = sliderHi->getSubImage(x, y, w, h);
-
- x = 0; y = 6;
- w = 6; h = 21;
- o1 = 10; o2 = 18;
- vStart = slider->getSubImage(x, y, w, o1 - y);
- vMid = slider->getSubImage(x, o1, w, o2 - o1);
- vEnd = slider->getSubImage(x, o2, w, h - o2 + y);
- vStartHi = sliderHi->getSubImage(x, y, w, o1 - y);
- vMidHi = sliderHi->getSubImage(x, o1, w, o2 - o1);
- vEndHi = sliderHi->getSubImage(x, o2, w, h - o2 + y);
-
- x = 6; y = 8;
- w = 9; h = 10;
- vGrip = slider->getSubImage(x, y, w, h);
- vGripHi = sliderHi->getSubImage(x, y, w, h);
-
- slider->decRef();
- sliderHi->decRef();
- }
-
- mInstances++;
-
- setMarkerLength(hGrip->getWidth());
-}
-
-void Slider::updateAlpha()
-{
- float alpha = std::max(config.guiAlpha,
- Theme::instance()->getMinimumOpacity());
-
- if (alpha != mAlpha)
- {
- mAlpha = alpha;
- hStart->setAlpha(mAlpha);
- hMid->setAlpha(mAlpha);
- hEnd->setAlpha(mAlpha);
- hGrip->setAlpha(mAlpha);
- hStartHi->setAlpha(mAlpha);
- hMidHi->setAlpha(mAlpha);
- hEndHi->setAlpha(mAlpha);
- hGripHi->setAlpha(mAlpha);
-
- vStart->setAlpha(mAlpha);
- vMid->setAlpha(mAlpha);
- vEnd->setAlpha(mAlpha);
- vGrip->setAlpha(mAlpha);
- vStartHi->setAlpha(mAlpha);
- vMidHi->setAlpha(mAlpha);
- vEndHi->setAlpha(mAlpha);
- vGripHi->setAlpha(mAlpha);
- }
-
+ auto theme = gui->getTheme();
+ auto &sliderSkin = theme->getSkin(SkinType::Slider);
+ auto &sliderHandleSkin = theme->getSkin(SkinType::SliderHandle);
+ setFrameSize(sliderSkin.frameSize);
+ setMarkerLength(sliderHandleSkin.getMinWidth());
+
+ setWidth(100);
+ setHeight(sliderSkin.getMinHeight() + 2 * sliderSkin.padding);
}
void Slider::draw(gcn::Graphics *graphics)
{
- int w = getWidth();
- int h = getHeight();
- int x = 0;
- int y = mHasMouse?(h - hStartHi->getHeight()) / 2:(h - hStart->getHeight()) / 2;
-
- updateAlpha();
-
- if (!mHasMouse)
- {
- static_cast<Graphics*>(graphics)->drawImage(hStart, x, y);
-
- w -= hStart->getWidth() + hEnd->getWidth();
- x += hStart->getWidth();
-
- static_cast<Graphics*>(graphics)->
- drawImagePattern(hMid, x, y, w, hMid->getHeight());
+ WidgetState state(this);
+ if (mHasMouse)
+ state.flags |= STATE_HOVERED;
- x += w;
- static_cast<Graphics*>(graphics)->drawImage(hEnd, x, y);
- }
- else
- {
- static_cast<Graphics*>(graphics)->drawImage(hStartHi, x, y);
+ auto theme = gui->getTheme();
+ theme->drawSkin(static_cast<Graphics*>(graphics), SkinType::Slider, state);
- w -= hStartHi->getWidth() + hEndHi->getWidth();
- x += hStartHi->getWidth();
-
- static_cast<Graphics*>(graphics)->
- drawImagePattern(hMidHi, x, y, w, hMidHi->getHeight());
-
- x += w;
- static_cast<Graphics*>(graphics)->drawImage(hEndHi, x, y);
- }
-
- drawMarker(graphics);
-}
-
-void Slider::drawMarker(gcn::Graphics *graphics)
-{
- static_cast<Graphics*>(graphics)->
- drawImage(mHasMouse?hGripHi:hGrip, getMarkerPosition(),
- (getHeight() - (mHasMouse?hGripHi:hGrip)->getHeight()) / 2);
+ WidgetState handleState(state);
+ handleState.x += getMarkerPosition();
+ theme->drawSkin(static_cast<Graphics*>(graphics), SkinType::SliderHandle, handleState);
}
void Slider::mouseEntered(gcn::MouseEvent& event)
@@ -205,4 +73,3 @@ void Slider::mouseExited(gcn::MouseEvent& event)
{
mHasMouse = false;
}
-
diff --git a/src/gui/widgets/slider.h b/src/gui/widgets/slider.h
index 3896cb52..52b3b3af 100644
--- a/src/gui/widgets/slider.h
+++ b/src/gui/widgets/slider.h
@@ -19,13 +19,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SLIDER_H
-#define SLIDER_H
+#pragma once
#include <guichan/widgets/slider.hpp>
-class Image;
-
/**
* Slider widget. Same as the Guichan slider but with custom look.
*
@@ -47,22 +44,16 @@ class Slider : public gcn::Slider
*/
Slider(double scaleStart, double scaleEnd);
- ~Slider() override;
-
- /**
- * Update the alpha value to the graphic components.
- */
- static void updateAlpha();
-
/**
* Draws the slider.
*/
void draw(gcn::Graphics *graphics) override;
- /**
- * Draws the marker.
- */
- void drawMarker(gcn::Graphics *graphics) override;
+ // Overridden to disable drawing of the frame
+ void drawFrame(gcn::Graphics *graphics) override {}
+
+ // Marker is drawn in Slider::draw
+ void drawMarker(gcn::Graphics *graphics) override {}
/**
* Called when the mouse enteres the widget area.
@@ -80,13 +71,5 @@ class Slider : public gcn::Slider
*/
void init();
- static Image *hStart, *hMid, *hEnd, *hGrip;
- static Image *vStart, *vMid, *vEnd, *vGrip;
- static Image *hStartHi, *hMidHi, *hEndHi, *hGripHi;
- static Image *vStartHi, *vMidHi, *vEndHi, *vGripHi;
bool mHasMouse = false;
- static float mAlpha;
- static int mInstances;
};
-
-#endif
diff --git a/src/gui/widgets/spacer.h b/src/gui/widgets/spacer.h
index f6a210dc..2fda6e8c 100644
--- a/src/gui/widgets/spacer.h
+++ b/src/gui/widgets/spacer.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef SPACER_H
-#define SPACER_H
+#pragma once
#include "guichan/graphics.hpp"
#include "guichan/widget.hpp"
@@ -48,5 +47,3 @@ class Spacer : public gcn::Widget
*/
void draw(gcn::Graphics *g) override {}
};
-
-#endif // SPACER_H
diff --git a/src/gui/widgets/tab.cpp b/src/gui/widgets/tab.cpp
index 64f49eac..b2779c4f 100644
--- a/src/gui/widgets/tab.cpp
+++ b/src/gui/widgets/tab.cpp
@@ -21,149 +21,90 @@
#include "gui/widgets/tab.h"
-#include "configuration.h"
#include "graphics.h"
+#include "gui/gui.h"
+#include "gui/widgets/label.h"
#include "gui/widgets/tabbedarea.h"
-#include "resources/image.h"
#include "resources/theme.h"
-#include "utils/dtor.h"
-
#include <guichan/widgets/label.hpp>
-int Tab::mInstances = 0;
-float Tab::mAlpha = 1.0;
-
-enum {
- TAB_STANDARD, // 0
- TAB_HIGHLIGHTED, // 1
- TAB_SELECTED, // 2
- TAB_UNUSED, // 3
- TAB_COUNT // 4 - Must be last.
-};
-
-struct TabData
-{
- char const *file;
- int gridX[4];
- int gridY[4];
-};
-
-static TabData const data[TAB_COUNT] = {
- { "tab.png", {0, 9, 16, 25}, {0, 13, 19, 20} },
- { "tab_hilight.png", {0, 9, 16, 25}, {0, 13, 19, 20} },
- { "tabselected.png", {0, 9, 16, 25}, {0, 4, 12, 20} },
- { "tab.png", {0, 9, 16, 25}, {0, 13, 19, 20} }
-};
-
-ImageRect Tab::tabImg[TAB_COUNT];
-
-Tab::Tab() :
- mTabColor(&Theme::getThemeColor(Theme::TAB))
-{
- init();
-}
-
-Tab::~Tab()
-{
- mInstances--;
-
- if (mInstances == 0)
- {
- for (auto &imgRect : tabImg)
- {
- std::for_each(imgRect.grid, imgRect.grid + 9, dtor<Image*>());
- }
- }
-}
-
-void Tab::init()
+Tab::Tab()
{
setFocusable(false);
- setFrameSize(0);
- mFlash = false;
- if (mInstances == 0)
- {
- // Load the skin
- Image *tab[TAB_COUNT];
-
- for (int mode = 0; mode < TAB_COUNT; mode++)
- {
- tab[mode] = Theme::getImageFromTheme(data[mode].file);
- int a = 0;
- for (int y = 0; y < 3; y++)
- {
- for (int x = 0; x < 3; x++)
- {
- tabImg[mode].grid[a] = tab[mode]->getSubImage(
- data[mode].gridX[x], data[mode].gridY[y],
- data[mode].gridX[x + 1] - data[mode].gridX[x] + 1,
- data[mode].gridY[y + 1] - data[mode].gridY[y] + 1);
- a++;
- }
- }
- tabImg[mode].setAlpha(mAlpha);
- tab[mode]->decRef();
- }
- }
- mInstances++;
+ // Replace the label with customized version
+ delete mLabel;
+ mLabel = new Label();
+ add(mLabel);
+
+ auto &skin = gui->getTheme()->getSkin(SkinType::Tab);
+ setFrameSize(skin.frameSize);
+ mPadding = skin.padding;
+ mLabel->setPosition(mPadding, mPadding);
}
-void Tab::updateAlpha()
+void Tab::setCaption(const std::string &caption)
{
- float alpha = std::max(config.guiAlpha,
- Theme::instance()->getMinimumOpacity());
+ mLabel->setCaption(caption);
+ mLabel->adjustSize();
- // TODO We don't need to do this for every tab on every draw
- // Maybe use a config listener to do it as the value changes.
- if (alpha != mAlpha)
- {
- mAlpha = alpha;
+ setSize(mLabel->getWidth() + mPadding * 2,
+ mLabel->getHeight() + mPadding * 2);
- for (auto &t : tabImg)
- {
- t.setAlpha(mAlpha);
- }
- }
+ if (mTabbedArea)
+ static_cast<TabbedArea*>(mTabbedArea)->adjustTabPositions();
}
void Tab::draw(gcn::Graphics *graphics)
{
- int mode = TAB_STANDARD;
+ if (getFrameSize() == 0)
+ drawFrame(graphics);
- // check which type of tab to draw
- if (mTabbedArea)
+ // if tab is selected, it doesnt need to highlight activity
+ if (mTabbedArea && mTabbedArea->isTabSelected(this))
+ mFlash = false;
+
+ uint8_t flags = 0;
+ if (mHasMouse)
+ flags |= STATE_HOVERED;
+ if (mTabbedArea && mTabbedArea->isTabSelected(this))
+ flags |= STATE_SELECTED;
+
+ auto &skin = gui->getTheme()->getSkin(SkinType::Tab);
+ if (auto state = skin.getState(flags))
{
- mLabel->setForegroundColor(*mTabColor);
- if (mTabbedArea->isTabSelected(this))
- {
- mode = TAB_SELECTED;
- // if tab is selected, it doesnt need to highlight activity
- mFlash = false;
- }
- else if (mHasMouse)
- {
- mode = TAB_HIGHLIGHTED;
- }
+ gcn::Color foregroundColor = state->textFormat.color;
if (mFlash)
- {
- mLabel->setForegroundColor(Theme::getThemeColor(Theme::TAB_FLASH));
- }
+ foregroundColor = Theme::getThemeColor(Theme::TAB_FLASH);
+ else if (mTabColor)
+ foregroundColor = *mTabColor;
+
+ auto label = static_cast<Label*>(mLabel);
+ label->setForegroundColor(foregroundColor);
+ label->setOutlineColor(state->textFormat.outlineColor);
+ label->setShadowColor(state->textFormat.shadowColor);
}
- updateAlpha();
-
- // draw tab
- static_cast<Graphics*>(graphics)->
- drawImageRect(0, 0, getWidth(), getHeight(), tabImg[mode]);
-
// draw label
drawChildren(graphics);
}
+void Tab::drawFrame(gcn::Graphics *graphics)
+{
+ WidgetState state(this);
+ state.width += getFrameSize() * 2;
+ state.height += getFrameSize() * 2;
+ if (mHasMouse)
+ state.flags |= STATE_HOVERED;
+ if (mTabbedArea && mTabbedArea->isTabSelected(this))
+ state.flags |= STATE_SELECTED;
+
+ gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics), SkinType::Tab, state);
+}
+
void Tab::setTabColor(const gcn::Color *color)
{
mTabColor = color;
diff --git a/src/gui/widgets/tab.h b/src/gui/widgets/tab.h
index 86650257..534abaff 100644
--- a/src/gui/widgets/tab.h
+++ b/src/gui/widgets/tab.h
@@ -19,12 +19,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TAB_H
-#define TAB_H
+#pragma once
#include <guichan/widgets/tab.hpp>
-class ImageRect;
class TabbedArea;
/**
@@ -35,19 +33,25 @@ class Tab : public gcn::Tab
{
public:
Tab();
- ~Tab() override;
/**
- * Update the alpha value to the graphic components.
+ * Sets the caption of the tab. Shadowing gcn::Tab::setCaption, which
+ * shouldn't be used because it calls gcn::Tab::adjustSize, which does
+ * not take into account the padding.
*/
- static void updateAlpha();
+ void setCaption(const std::string& caption);
/**
- * Draw the tabbed area.
+ * Draw the tab.
*/
void draw(gcn::Graphics *graphics) override;
/**
+ * Draw the tab frame.
+ */
+ void drawFrame(gcn::Graphics *graphics) override;
+
+ /**
* Set the normal color fo the tab's text.
*/
void setTabColor(const gcn::Color *color);
@@ -62,15 +66,7 @@ class Tab : public gcn::Tab
virtual void setCurrent() {}
private:
- /** Load images if no other instances exist yet */
- void init();
-
- static ImageRect tabImg[4]; /**< Tab state graphics */
- static int mInstances; /**< Number of tab instances */
- static float mAlpha;
-
- const gcn::Color *mTabColor;
- bool mFlash;
+ const gcn::Color *mTabColor = nullptr;
+ bool mFlash = false;
+ int mPadding = 8;
};
-
-#endif
diff --git a/src/gui/widgets/tabbedarea.cpp b/src/gui/widgets/tabbedarea.cpp
index af0c11cb..3609791a 100644
--- a/src/gui/widgets/tabbedarea.cpp
+++ b/src/gui/widgets/tabbedarea.cpp
@@ -21,6 +21,8 @@
#include "gui/widgets/tabbedarea.h"
+#include "graphics.h"
+
#include "gui/widgets/tab.h"
#include <guichan/widgets/container.hpp>
@@ -30,13 +32,13 @@ TabbedArea::TabbedArea()
mWidgetContainer->setOpaque(false);
addWidgetListener(this);
- mArrowButton[0] = new Button(std::string(), "shift_left", this);
- mArrowButton[1] = new Button(std::string(), "shift_right", this);
+ mArrowButton[0] = std::make_unique<Button>(std::string(), "shift_left", this);
+ mArrowButton[1] = std::make_unique<Button>(std::string(), "shift_right", this);
mArrowButton[0]->setButtonIcon("tab_arrows_left.png");
mArrowButton[1]->setButtonIcon("tab_arrows_right.png");
- add(mArrowButton[0]);
- add(mArrowButton[1]);
+ add(mArrowButton[0].get());
+ add(mArrowButton[1].get());
widgetResized(nullptr);
}
@@ -61,7 +63,12 @@ void TabbedArea::draw(gcn::Graphics *graphics)
if (mTabs.empty())
return;
+ auto g = static_cast<Graphics*>(graphics);
+ g->pushClipRect(getChildrenArea());
+
drawChildren(graphics);
+
+ g->popClipRect();
}
gcn::Widget *TabbedArea::getWidget(const std::string &name) const
@@ -105,7 +112,7 @@ void TabbedArea::addTab(const std::string &caption, gcn::Widget *widget)
addTab(tab, widget);
}
-void TabbedArea::removeTab(Tab *tab)
+void TabbedArea::removeTab(gcn::Tab *tab)
{
if (tab == mSelectedTab)
{
@@ -206,9 +213,8 @@ void TabbedArea::updateTabsWidth()
{
mTabsWidth = 0;
for (const auto &[tab, _] : mTabs)
- {
mTabsWidth += tab->getWidth();
- }
+
updateVisibleTabsWidth();
}
@@ -216,9 +222,7 @@ void TabbedArea::updateVisibleTabsWidth()
{
mVisibleTabsWidth = 0;
for (unsigned int i = mTabScrollIndex; i < mTabs.size(); ++i)
- {
mVisibleTabsWidth += mTabs[i].first->getWidth();
- }
}
void TabbedArea::adjustTabPositions()
@@ -265,7 +269,7 @@ void TabbedArea::action(const gcn::ActionEvent& actionEvent)
{
if (actionEvent.getId() == "shift_left")
{
- if (mTabScrollIndex)
+ if (mTabScrollIndex > 0)
--mTabScrollIndex;
}
else if (actionEvent.getId() == "shift_right")
@@ -282,33 +286,18 @@ void TabbedArea::action(const gcn::ActionEvent& actionEvent)
void TabbedArea::updateArrowEnableState()
{
updateTabsWidth();
- if (mTabsWidth > getWidth() - 2)
- {
- mArrowButton[0]->setVisible(true);
- mArrowButton[1]->setVisible(true);
- }
- else
- {
- mArrowButton[0]->setVisible(false);
- mArrowButton[1]->setVisible(false);
+
+ const bool arrowButtonsVisible = mTabsWidth > getWidth() - 2;
+ mArrowButton[0]->setVisible(arrowButtonsVisible);
+ mArrowButton[1]->setVisible(arrowButtonsVisible);
+
+ if (!arrowButtonsVisible)
mTabScrollIndex = 0;
- }
- // Left arrow consistency check
- if (!mTabScrollIndex)
- mArrowButton[0]->setEnabled(false);
- else
- mArrowButton[0]->setEnabled(true);
+ mArrowButton[0]->setEnabled(mTabScrollIndex > 0);
// Right arrow consistency check
- if (mVisibleTabsWidth < getWidth() - 2
- - mArrowButton[0]->getWidth()
- - mArrowButton[1]->getWidth())
- {
- mArrowButton[1]->setEnabled(false);
- }
- else
- {
- mArrowButton[1]->setEnabled(true);
- }
+ const int availableWidth = getWidth() - 2 - mArrowButton[0]->getWidth()
+ - mArrowButton[1]->getWidth();
+ mArrowButton[1]->setEnabled(mVisibleTabsWidth >= availableWidth);
}
diff --git a/src/gui/widgets/tabbedarea.h b/src/gui/widgets/tabbedarea.h
index 8e6dcb5f..5d0ccfcc 100644
--- a/src/gui/widgets/tabbedarea.h
+++ b/src/gui/widgets/tabbedarea.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TABBEDAREA_H
-#define TABBEDAREA_H
+#pragma once
#include <guichan/widget.hpp>
#include <guichan/widgetlistener.hpp>
@@ -29,6 +28,7 @@
#include "gui/widgets/button.h"
+#include <memory>
#include <string>
class Tab;
@@ -36,7 +36,7 @@ class Tab;
/**
* A tabbed area, the same as the guichan tabbed area in 0.8, but extended
*/
-class TabbedArea : public gcn::TabbedArea, public gcn::WidgetListener
+class TabbedArea final : public gcn::TabbedArea, public gcn::WidgetListener
{
public:
TabbedArea();
@@ -86,12 +86,12 @@ class TabbedArea : public gcn::TabbedArea, public gcn::WidgetListener
void addTab(const std::string &caption, gcn::Widget *widget) override;
/**
- * Overload the remove tab function as it's broken in guichan 0.8.
+ * Override the remove tab function as it's broken in guichan 0.8.
*/
- void removeTab(Tab *tab);
+ void removeTab(gcn::Tab *tab) override;
/**
- * Overload the logic function since it's broken in guichan 0.8.
+ * Override the logic function since it's broken in guichan 0.8.
*/
void logic() override;
@@ -115,7 +115,7 @@ class TabbedArea : public gcn::TabbedArea, public gcn::WidgetListener
private:
/** The tab arrows */
- Button *mArrowButton[2];
+ std::unique_ptr<Button> mArrowButton[2];
/** Check whether the arrow should be clickable */
void updateArrowEnableState();
@@ -151,5 +151,3 @@ class TabbedArea : public gcn::TabbedArea, public gcn::WidgetListener
*/
unsigned mTabScrollIndex = 0;
};
-
-#endif
diff --git a/src/gui/widgets/table.cpp b/src/gui/widgets/table.cpp
index 905bb166..909617a0 100644
--- a/src/gui/widgets/table.cpp
+++ b/src/gui/widgets/table.cpp
@@ -21,8 +21,7 @@
#include "gui/widgets/table.h"
-#include "configuration.h"
-
+#include "gui/gui.h"
#include "gui/sdlinput.h"
#include "resources/theme.h"
@@ -33,13 +32,10 @@
#include <guichan/graphics.hpp>
#include <guichan/key.hpp>
-float GuiTable::mAlpha = 1.0;
-
class GuiTableActionListener : public gcn::ActionListener
{
public:
- GuiTableActionListener(GuiTable *_table, gcn::Widget *_widget, int _row, int _column);
-
+ GuiTableActionListener(GuiTable *table, gcn::Widget *widget, int row, int column);
~GuiTableActionListener() override;
void action(const gcn::ActionEvent& actionEvent) override;
@@ -81,18 +77,12 @@ void GuiTableActionListener::action(const gcn::ActionEvent& actionEvent)
}
-GuiTable::GuiTable(TableModel *initial_model, gcn::Color background,
+GuiTable::GuiTable(TableModel *initialModel, gcn::Color background,
bool opacity) :
- mLinewiseMode(false),
- mWrappingEnabled(false),
mOpaque(opacity),
- mBackgroundColor(background),
- mModel(nullptr),
- mSelectedRow(0),
- mSelectedColumn(0),
- mTopWidget(nullptr)
+ mBackgroundColor(background)
{
- setModel(initial_model);
+ setModel(initialModel);
setFocusable(true);
addMouseListener(this);
@@ -269,16 +259,19 @@ void GuiTable::draw(gcn::Graphics* graphics)
if (!mModel)
return;
- if (config.guiAlpha != mAlpha)
- mAlpha = config.guiAlpha;
+ const auto guiAlpha = gui->getTheme()->getGuiAlpha();
if (mOpaque)
{
- graphics->setColor(Theme::getThemeColor(Theme::BACKGROUND,
- (int)(mAlpha * 255.0f)));
+ auto backgroundColor = Theme::getThemeColor(Theme::BACKGROUND);
+ backgroundColor.a = guiAlpha;
+ graphics->setColor(backgroundColor);
graphics->fillRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight()));
}
+ auto highlightColor = Theme::getThemeColor(Theme::HIGHLIGHT);
+ highlightColor.a = guiAlpha;
+
// First, determine how many rows we need to draw, and where we should start.
int first_row = -(getY() / getRowHeight());
@@ -320,8 +313,7 @@ void GuiTable::draw(gcn::Graphics* graphics)
widget->setDimension(bounds);
- graphics->setColor(Theme::getThemeColor(Theme::HIGHLIGHT,
- (int)(mAlpha * 255.0f)));
+ graphics->setColor(highlightColor);
if (mLinewiseMode && r == mSelectedRow && c == 0)
{
@@ -368,7 +360,7 @@ void GuiTable::moveToBottom(gcn::Widget *widget)
mTopWidget = nullptr;
}
-gcn::Rectangle GuiTable::getChildrenArea() const
+gcn::Rectangle GuiTable::getChildrenArea()
{
return gcn::Rectangle(0, 0, getWidth(), getHeight());
}
@@ -487,7 +479,7 @@ void GuiTable::modelUpdated(bool completed)
}
}
-gcn::Widget *GuiTable::getWidgetAt(int x, int y) const
+gcn::Widget *GuiTable::getWidgetAt(int x, int y)
{
int row = getRowForY(y);
int column = getColumnForX(x);
@@ -497,14 +489,12 @@ gcn::Widget *GuiTable::getWidgetAt(int x, int y) const
if (row > -1 && column > -1)
{
- gcn::Widget *w = mModel->getElementAt(row, column);
- if (w && w->isFocusable())
- return w;
- else
- return nullptr; // Grab the event locally
+ if (gcn::Widget *w = mModel->getElementAt(row, column))
+ if (w->isFocusable())
+ return w;
}
- else
- return nullptr;
+
+ return nullptr; // Grab the event locally
}
int GuiTable::getRowForY(int y) const
@@ -516,8 +506,8 @@ int GuiTable::getRowForY(int y) const
if (row < 0 || row >= mModel->getRows())
return -1;
- else
- return row;
+
+ return row;
}
int GuiTable::getColumnForX(int x) const
@@ -534,24 +524,23 @@ int GuiTable::getColumnForX(int x) const
if (column < 0 || column >= mModel->getColumns())
return -1;
- else
- return column;
+
+ return column;
}
void GuiTable::_setFocusHandler(gcn::FocusHandler* focusHandler)
{
gcn::Widget::_setFocusHandler(focusHandler);
- if (mModel)
+ if (!mModel)
+ return;
+
+ for (int r = 0; r < mModel->getRows(); ++r)
{
- for (int r = 0; r < mModel->getRows(); ++r)
+ for (int c = 0; c < mModel->getColumns(); ++c)
{
- for (int c = 0; c < mModel->getColumns(); ++c)
- {
- gcn::Widget *w = mModel->getElementAt(r, c);
- if (w)
- w->_setFocusHandler(focusHandler);
- }
+ if (gcn::Widget *w = mModel->getElementAt(r, c))
+ w->_setFocusHandler(focusHandler);
}
}
}
diff --git a/src/gui/widgets/table.h b/src/gui/widgets/table.h
index a9202022..88350928 100644
--- a/src/gui/widgets/table.h
+++ b/src/gui/widgets/table.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TABLE_H
-#define TABLE_H
+#pragma once
#include "tablemodel.h"
@@ -41,16 +40,16 @@ class GuiTableActionListener;
*
* \ingroup GUI
*/
-class GuiTable : public gcn::Widget,
- public gcn::MouseListener,
- public gcn::KeyListener,
- public TableModelListener
+class GuiTable final : public gcn::Widget,
+ public gcn::MouseListener,
+ public gcn::KeyListener,
+ public TableModelListener
{
// so that the action listener can call distributeActionEvent
friend class GuiTableActionListener;
public:
- GuiTable(TableModel * initial_model = nullptr, gcn::Color background = 0xffffff,
+ GuiTable(TableModel *initialModel = nullptr, gcn::Color background = 0xffffff,
bool opacity = true);
~GuiTable() override;
@@ -85,7 +84,7 @@ public:
void setWrappingEnabled(bool wrappingEnabled)
{mWrappingEnabled = wrappingEnabled;}
- gcn::Rectangle getChildrenArea() const;
+ gcn::Rectangle getChildrenArea() override;
/**
* Toggle whether to use linewise selection mode, in which the table selects
@@ -103,7 +102,10 @@ public:
// Inherited from Widget
void draw(gcn::Graphics* graphics) override;
- virtual gcn::Widget *getWidgetAt(int x, int y) const;
+ // Overridden to disable drawing of the frame
+ void drawFrame(gcn::Graphics* graphics) override {}
+
+ gcn::Widget *getWidgetAt(int x, int y) override;
void moveToTop(gcn::Widget *child) override;
@@ -120,7 +122,7 @@ public:
*
* @param opaque True if the table should be opaque, false otherwise.
*/
- virtual void setOpaque(bool opaque) {mOpaque = opaque;}
+ void setOpaque(bool opaque) {mOpaque = opaque;}
/**
* Checks if the table is opaque, that is if the table area displays its
@@ -128,7 +130,7 @@ public:
*
* @return True if the table is opaque, false otherwise.
*/
- virtual bool isOpaque() const {return mOpaque;}
+ bool isOpaque() const {return mOpaque;}
// Inherited from MouseListener
void mousePressed(gcn::MouseEvent& mouseEvent) override;
@@ -144,42 +146,35 @@ public:
protected:
/** Frees all action listeners on inner widgets. */
- virtual void uninstallActionListeners();
+ void uninstallActionListeners();
/** Installs all action listeners on inner widgets. */
- virtual void installActionListeners();
+ void installActionListeners();
- virtual int getRowHeight() const;
- virtual int getColumnWidth(int i) const;
+ int getRowHeight() const;
+ int getColumnWidth(int i) const;
private:
int getRowForY(int y) const; // -1 on error
int getColumnForX(int x) const; // -1 on error
void recomputeDimensions();
- bool mLinewiseMode;
- bool mWrappingEnabled;
- bool mOpaque;
- static float mAlpha;
+ bool mLinewiseMode = false;
+ bool mWrappingEnabled = false;
+ bool mOpaque;
/**
* Holds the background color of the table.
*/
gcn::Color mBackgroundColor;
- TableModel *mModel;
+ TableModel *mModel = nullptr;
- int mSelectedRow;
- int mSelectedColumn;
-
- /** Number of frames to skip upwards when drawing the selected widget. */
- int mPopFramesNr;
+ int mSelectedRow = 0;
+ int mSelectedColumn = 0;
/** If someone moves a fresh widget to the top, we must display it. */
- gcn::Widget *mTopWidget;
+ gcn::Widget *mTopWidget = nullptr;
/** Vector for compactness; used as a list in practice. */
std::vector<GuiTableActionListener *> mActionListeners;
};
-
-
-#endif // TABLE_H
diff --git a/src/gui/widgets/tablemodel.h b/src/gui/widgets/tablemodel.h
index d4274e39..2ba36556 100644
--- a/src/gui/widgets/tablemodel.h
+++ b/src/gui/widgets/tablemodel.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TABLE_MODEL_H
-#define TABLE_MODEL_H
+#pragma once
#include <guichanfwd.h>
@@ -143,5 +142,3 @@ protected:
std::vector<gcn::Widget *> mTableModel;
std::vector<int> mWidths;
};
-
-#endif // TABLE_MODEL_H
diff --git a/src/gui/widgets/textbox.cpp b/src/gui/widgets/textbox.cpp
index 419fa16e..6cc514fe 100644
--- a/src/gui/widgets/textbox.cpp
+++ b/src/gui/widgets/textbox.cpp
@@ -21,15 +21,20 @@
#include "gui/widgets/textbox.h"
+#include "gui/gui.h"
#include "resources/theme.h"
+#include "textrenderer.h"
#include <guichan/font.hpp>
#include <sstream>
-TextBox::TextBox() :
- mTextColor(&Theme::getThemeColor(Theme::TEXT))
+TextBox::TextBox()
{
+ auto &palette = gui->getTheme()->getPalette(0);
+ mTextColor = &palette.getColor(Theme::TEXT);
+ mOutlineColor = palette.getOutlineColor(Theme::TEXT);
+
setOpaque(false);
setFrameSize(0);
mMinWidth = getWidth();
@@ -147,3 +152,42 @@ void TextBox::setTextWrapped(const std::string &text, int minDimension)
gcn::TextBox::setText(wrappedStream.str());
}
+
+/**
+ * Overridden so we can customize the color and outline of the text.
+ */
+void TextBox::draw(gcn::Graphics *graphics)
+{
+ unsigned int i;
+
+ if (mOpaque)
+ {
+ graphics->setColor(getBackgroundColor());
+ graphics->fillRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight()));
+ }
+
+ if (isFocused() && isEditable())
+ {
+ drawCaret(graphics,
+ getFont()->getWidth(mTextRows[mCaretRow].substr(0, mCaretColumn)),
+ mCaretRow * getFont()->getHeight());
+ }
+
+ graphics->setColor(*mTextColor);
+ graphics->setFont(getFont());
+
+ for (i = 0; i < mTextRows.size(); i++)
+ {
+ // Move the text one pixel so we can have a caret before a letter.
+ TextRenderer::renderText(graphics,
+ mTextRows[i],
+ 1,
+ i * getFont()->getHeight(),
+ gcn::Graphics::LEFT,
+ *mTextColor,
+ getFont(),
+ mOutlineColor.has_value(),
+ false,
+ mOutlineColor);
+ }
+}
diff --git a/src/gui/widgets/textbox.h b/src/gui/widgets/textbox.h
index bcf09ee2..49a5a2ad 100644
--- a/src/gui/widgets/textbox.h
+++ b/src/gui/widgets/textbox.h
@@ -19,11 +19,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TEXTBOX_H
-#define TEXTBOX_H
+#pragma once
#include <guichan/widgets/textbox.hpp>
+#include <optional>
+
/**
* A text box, meant to be used inside a scroll area. Same as the Guichan text
* box except this one doesn't have a background or border, instead completely
@@ -39,6 +40,9 @@ class TextBox : public gcn::TextBox
void setTextColor(const gcn::Color *color)
{ mTextColor = color; }
+ void setOutlineColor(const std::optional<gcn::Color> &color)
+ { mOutlineColor = color; }
+
/**
* Sets the text after wrapping it to the current width of the widget.
*/
@@ -52,15 +56,10 @@ class TextBox : public gcn::TextBox
/**
* Draws the text.
*/
- void draw(gcn::Graphics *graphics) override
- {
- setForegroundColor(*mTextColor);
- gcn::TextBox::draw(graphics);
- }
+ void draw(gcn::Graphics *graphics) override;
private:
int mMinWidth;
const gcn::Color *mTextColor;
+ std::optional<gcn::Color> mOutlineColor;
};
-
-#endif
diff --git a/src/gui/widgets/textfield.cpp b/src/gui/widgets/textfield.cpp
index dd0adecd..6c866477 100644
--- a/src/gui/widgets/textfield.cpp
+++ b/src/gui/widgets/textfield.cpp
@@ -21,107 +21,63 @@
#include "gui/widgets/textfield.h"
-#include "configuration.h"
#include "graphics.h"
+#include "gui/gui.h"
#include "gui/sdlinput.h"
-#include "resources/image.h"
#include "resources/theme.h"
#include "utils/copynpaste.h"
-#include "utils/dtor.h"
#include "utils/stringutils.h"
#include <guichan/font.hpp>
#include <SDL.h>
-#undef DELETE //Win32 compatibility hack
-
-int TextField::instances = 0;
-float TextField::mAlpha = 1.0;
-ImageRect TextField::skin;
-
-TextField::TextField(const std::string &text, bool loseFocusOnTab):
- gcn::TextField(text)
-{
- setFrameSize(2);
-
- mLoseFocusOnTab = loseFocusOnTab;
-
- if (instances == 0)
- {
- // Load the skin
- Image *textbox = Theme::getImageFromTheme("deepbox.png");
- int gridx[4] = {0, 3, 28, 31};
- int gridy[4] = {0, 3, 28, 31};
- int a = 0;
-
- for (int y = 0; y < 3; y++)
- {
- for (int x = 0; x < 3; x++)
- {
- skin.grid[a] = textbox->getSubImage(
- gridx[x], gridy[y],
- gridx[x + 1] - gridx[x] + 1,
- gridy[y + 1] - gridy[y] + 1);
- a++;
- }
- }
- skin.setAlpha(config.guiAlpha);
-
- textbox->decRef();
- }
-
- instances++;
-}
-
-TextField::~TextField()
+TextField::TextField(const std::string &text, bool loseFocusOnTab)
+ : gcn::TextField(text)
+ , mLoseFocusOnTab(loseFocusOnTab)
{
- instances--;
-
- if (instances == 0)
- std::for_each(skin.grid, skin.grid + 9, dtor<Image*>());
-}
+ auto &skin = gui->getTheme()->getSkin(SkinType::TextField);
+ setFrameSize(skin.frameSize);
+ mPadding = skin.padding;
-void TextField::updateAlpha()
-{
- float alpha = std::max(config.guiAlpha,
- Theme::instance()->getMinimumOpacity());
-
- if (alpha != mAlpha)
- {
- mAlpha = alpha;
- skin.setAlpha(mAlpha);
- }
+ setWidth(getFont()->getWidth(mText) + 2 * mPadding);
+ setHeight(getFont()->getHeight() + 2 * mPadding);
+ fixScroll();
}
void TextField::draw(gcn::Graphics *graphics)
{
- updateAlpha();
+ if (getFrameSize() == 0)
+ drawFrame(graphics);
+
+ auto g = static_cast<Graphics *>(graphics);
+ g->pushClipRect(gcn::Rectangle(0, 0, getWidth(), getHeight()));
if (isFocused())
{
drawCaret(graphics,
- getFont()->getWidth(mText.substr(0, mCaretPosition)) -
- mXScroll);
+ getFont()->getWidth(mText.substr(0, mCaretPosition)) - mXScroll);
}
graphics->setColor(Theme::getThemeColor(Theme::TEXT));
graphics->setFont(getFont());
- graphics->drawText(mText, 1 - mXScroll, 1);
+ graphics->drawText(mText, mPadding - mXScroll, mPadding);
+
+ g->popClipRect();
}
void TextField::drawFrame(gcn::Graphics *graphics)
{
- //updateAlpha(); -> Not useful...
+ const int bs = getFrameSize();
- int bs = getFrameSize();
- int w = getWidth() + bs * 2;
- int h = getHeight() + bs * 2;
+ WidgetState state(this);
+ state.width += bs * 2;
+ state.height += bs * 2;
- static_cast<Graphics*>(graphics)->drawImageRect(0, 0, w, h, skin);
+ gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics), SkinType::TextField, state);
}
void TextField::setNumeric(bool numeric)
@@ -156,6 +112,12 @@ int TextField::getValue() const
return value;
}
+void TextField::drawCaret(gcn::Graphics *graphics, int x)
+{
+ graphics->setColor(Theme::getThemeColor(Theme::CARET));
+ graphics->drawLine(mPadding + x, mPadding, mPadding + x, getHeight() - mPadding);
+}
+
void TextField::keyPressed(gcn::KeyEvent &keyEvent)
{
switch (keyEvent.getKey().getValue())
diff --git a/src/gui/widgets/textfield.h b/src/gui/widgets/textfield.h
index 9235f4b8..b84dd723 100644
--- a/src/gui/widgets/textfield.h
+++ b/src/gui/widgets/textfield.h
@@ -19,16 +19,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TEXTFIELD_H
-#define TEXTFIELD_H
+#pragma once
#include <guichan/widgets/textfield.hpp>
#include <vector>
class TextInput;
-class ImageRect;
-class TextField;
struct TextHistory
{
@@ -79,7 +76,6 @@ class TextField : public gcn::TextField
*/
TextField(const std::string &text = std::string(),
bool loseFocusOnTab = true);
- ~TextField() override;
/**
* Draws the text field.
@@ -87,11 +83,6 @@ class TextField : public gcn::TextField
void draw(gcn::Graphics *graphics) override;
/**
- * Update the alpha value to the graphic components.
- */
- static void updateAlpha();
-
- /**
* Draws the background and border.
*/
void drawFrame(gcn::Graphics *graphics) override;
@@ -139,42 +130,41 @@ class TextField : public gcn::TextField
* Sets the TextField's source of autocomplete. Passing null will
* disable autocomplete.
*/
- void setAutoComplete(AutoCompleteLister *lister)
- { mAutoComplete = lister; }
+ void setAutoComplete(AutoCompleteLister *lister)
+ { mAutoComplete = lister; }
- /**
+ /**
* Returns the TextField's source of autocomplete.
*/
- AutoCompleteLister *getAutoComplete() const
- { return mAutoComplete; }
+ AutoCompleteLister *getAutoComplete() const
+ { return mAutoComplete; }
- /**
+ /**
* Sets the TextField's source of input history.
*/
- void setHistory(TextHistory *history)
- { mHistory = history; }
+ void setHistory(TextHistory *history)
+ { mHistory = history; }
- /**
+ /**
* Returns the TextField's source of input history.
*/
- TextHistory *getHistory() const
- { return mHistory; }
+ TextHistory *getHistory() const
+ { return mHistory; }
+
+ protected:
+ void drawCaret(gcn::Graphics *graphics, int x) override;
private:
void autoComplete();
void handlePaste();
- static int instances;
- static float mAlpha;
- static ImageRect skin;
bool mNumeric = false;
- int mMinimum;
- int mMaximum;
+ int mMinimum = 0;
+ int mMaximum = 0;
bool mLoseFocusOnTab;
+ int mPadding = 1;
AutoCompleteLister *mAutoComplete = nullptr;
TextHistory *mHistory = nullptr; /**< Text history. */
};
-
-#endif
diff --git a/src/gui/widgets/textpreview.cpp b/src/gui/widgets/textpreview.cpp
index f9e85052..2f80bd23 100644
--- a/src/gui/widgets/textpreview.cpp
+++ b/src/gui/widgets/textpreview.cpp
@@ -29,49 +29,19 @@
#include <typeinfo>
-float TextPreview::mAlpha = 1.0;
-
-TextPreview::TextPreview(const std::string &text):
- mText(text)
+TextPreview::TextPreview(const std::string &text)
+ : mText(text)
{
mFont = gui->getFont();
mTextColor = &Theme::getThemeColor(Theme::TEXT);
- mBGColor = &Theme::getThemeColor(Theme::BACKGROUND);
}
void TextPreview::draw(gcn::Graphics* graphics)
{
- if (config.guiAlpha != mAlpha)
- mAlpha = config.guiAlpha;
-
- int alpha = (int) (mAlpha * 255.0f);
-
- if (!mTextAlpha)
- alpha = 255;
-
- if (mOpaque)
- {
- graphics->setColor(gcn::Color((int) mBGColor->r,
- (int) mBGColor->g,
- (int) mBGColor->b,
- (int)(mAlpha * 255.0f)));
- graphics->fillRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight()));
- }
-
- if (mTextBGColor && typeid(*mFont) == typeid(TrueTypeFont))
- {
- auto *font = static_cast<TrueTypeFont*>(mFont);
- int x = font->getWidth(mText) + 1 + 2 * ((mOutline || mShadow) ? 1 :0);
- int y = font->getHeight() + 1 + 2 * ((mOutline || mShadow) ? 1 : 0);
- graphics->setColor(gcn::Color((int) mTextBGColor->r,
- (int) mTextBGColor->g,
- (int) mTextBGColor->b,
- (int)(mAlpha * 255.0f)));
- graphics->fillRectangle(gcn::Rectangle(1, 1, x, y));
- }
-
TextRenderer::renderText(graphics, mText, 2, 2, gcn::Graphics::LEFT,
- gcn::Color(mTextColor->r, mTextColor->g,
- mTextColor->b, alpha),
+ gcn::Color(mTextColor->r,
+ mTextColor->g,
+ mTextColor->b,
+ 255),
mFont, mOutline, mShadow);
}
diff --git a/src/gui/widgets/textpreview.h b/src/gui/widgets/textpreview.h
index 7e88248f..8246a200 100644
--- a/src/gui/widgets/textpreview.h
+++ b/src/gui/widgets/textpreview.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef TEXTPREVIEW_H
-#define TEXTPREVIEW_H
+#pragma once
#include <guichan/color.hpp>
#include <guichan/font.hpp>
@@ -45,37 +44,6 @@ class TextPreview : public gcn::Widget
}
/**
- * Sets the text to use the set alpha value.
- *
- * @param alpha whether to use alpha values for the text or not
- */
- void useTextAlpha(bool alpha)
- {
- mTextAlpha = alpha;
- }
-
- /**
- * Sets the color the text background is drawn in. This is only the
- * rectangle directly behind the text, not to full widget.
- *
- * @param color the color to set
- */
- void setTextBGColor(const gcn::Color *color)
- {
- mTextBGColor = color;
- }
-
- /**
- * Sets the background color of the widget.
- *
- * @param color the color to set
- */
- void setBGColor(const gcn::Color *color)
- {
- mBGColor = color;
- }
-
- /**
* Sets the font to render the text in.
*
* @param font the font to use.
@@ -112,31 +80,10 @@ class TextPreview : public gcn::Widget
*/
void draw(gcn::Graphics *graphics) override;
- /**
- * Set opacity for this widget (whether or not to show the background
- * color)
- *
- * @param opaque Whether the widget should be opaque or not
- */
- void setOpaque(bool opaque) { mOpaque = opaque; }
-
- /**
- * Gets opacity for this widget (whether or not the background color
- * is shown below the widget)
- */
- bool isOpaque() const { return mOpaque; }
-
private:
gcn::Font *mFont;
std::string mText;
const gcn::Color *mTextColor;
- const gcn::Color *mBGColor;
- const gcn::Color *mTextBGColor = nullptr;
- static float mAlpha;
- bool mTextAlpha = false;
- bool mOpaque = false;
bool mShadow = false;
bool mOutline = false;
};
-
-#endif
diff --git a/src/gui/widgets/vertcontainer.h b/src/gui/widgets/vertcontainer.h
index b66957d3..a684453f 100644
--- a/src/gui/widgets/vertcontainer.h
+++ b/src/gui/widgets/vertcontainer.h
@@ -18,8 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef GUI_VERTCONTAINER_H
-#define GUI_VERTCONTAINER_H
+#pragma once
#include "gui/widgets/container.h"
@@ -42,5 +41,3 @@ class VertContainer : public Container, public gcn::WidgetListener
int mSpacing;
int mCount = 0;
};
-
-#endif
diff --git a/src/gui/widgets/whispertab.cpp b/src/gui/widgets/whispertab.cpp
index 636f48dd..28181971 100644
--- a/src/gui/widgets/whispertab.cpp
+++ b/src/gui/widgets/whispertab.cpp
@@ -36,7 +36,7 @@ WhisperTab::WhisperTab(const std::string &nick) :
ChatTab(nick),
mNick(nick)
{
- setTabColor(&Theme::getThemeColor(Theme::WHISPER));
+ setTabColor(&Theme::getThemeColor(Theme::WHISPER_TAB));
}
WhisperTab::~WhisperTab()
diff --git a/src/gui/widgets/whispertab.h b/src/gui/widgets/whispertab.h
index 0f01bacc..1a0a4a0f 100644
--- a/src/gui/widgets/whispertab.h
+++ b/src/gui/widgets/whispertab.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef WHISPERTAB_H
-#define WHISPERTAB_H
+#pragma once
#include "chattab.h"
@@ -63,5 +62,3 @@ class WhisperTab : public ChatTab
private:
std::string mNick;
};
-
-#endif // CHANNELTAB_H
diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp
index 8bf9d081..e57918b7 100644
--- a/src/gui/widgets/window.cpp
+++ b/src/gui/widgets/window.cpp
@@ -23,6 +23,7 @@
#include "configuration.h"
#include "log.h"
+#include "textrenderer.h"
#include "gui/gui.h"
#include "gui/viewport.h"
@@ -31,9 +32,6 @@
#include "gui/widgets/resizegrip.h"
#include "gui/widgets/windowcontainer.h"
-#include "resources/image.h"
-#include "resources/theme.h"
-
#include <guichan/exception.hpp>
#include <guichan/focushandler.hpp>
@@ -43,13 +41,17 @@
int Window::instances = 0;
int Window::mouseResize = 0;
-Window::Window(const std::string &caption, bool modal, Window *parent,
- const std::string &skin):
- gcn::Window(caption),
- mParent(parent),
- mModal(modal),
- mMaxWinWidth(graphics->getWidth()),
- mMaxWinHeight(graphics->getHeight())
+Window::Window(const std::string &caption, bool modal, Window *parent)
+ : Window(SkinType::Window, caption, modal, parent)
+{}
+
+Window::Window(SkinType skinType, const std::string &caption, bool modal, Window *parent)
+ : gcn::Window(caption)
+ , mParent(parent)
+ , mModal(modal)
+ , mSkinType(skinType)
+ , mMaxWinWidth(graphics->getWidth())
+ , mMaxWinHeight(graphics->getHeight())
{
logger->log("Window::Window(\"%s\")", caption.c_str());
@@ -58,19 +60,17 @@ Window::Window(const std::string &caption, bool modal, Window *parent,
instances++;
- setFrameSize(0);
- setPadding(3);
- setTitleBarHeight(20);
-
- // Loads the skin
- mSkin = Theme::instance()->load(skin);
+ auto &skin = getSkin();
+ setFrameSize(skin.frameSize);
+ setPadding(skin.padding);
+ setTitleBarHeight(skin.titleBarHeight);
// Add this window to the window container
windowContainer->add(this);
if (mModal)
{
- gui->setCursorType(Cursor::POINTER);
+ gui->setCursorType(Cursor::Pointer);
requestModalFocus();
}
@@ -94,8 +94,6 @@ Window::~Window()
removeWidgetListener(this);
instances--;
-
- mSkin->instances--;
}
void Window::setWindowContainer(WindowContainer *wc)
@@ -105,44 +103,57 @@ void Window::setWindowContainer(WindowContainer *wc)
void Window::draw(gcn::Graphics *graphics)
{
- auto *g = static_cast<Graphics*>(graphics);
+ if (getFrameSize() == 0)
+ drawFrame(graphics);
- g->drawImageRect(0, 0, getWidth(), getHeight(), mSkin->getBorder());
-
- // Draw title
- if (mShowTitle)
- {
- g->setColor(Theme::getThemeColor(Theme::TEXT));
- g->setFont(getFont());
- g->drawText(getCaption(), 7, 5, gcn::Graphics::LEFT);
- }
+ auto g = static_cast<Graphics*>(graphics);
- // Draw Close Button
if (mCloseButton)
{
- g->drawImage(mSkin->getCloseImage(),
- getWidth() - mSkin->getCloseImage()->getWidth() - getPadding(),
- getPadding());
+ WidgetState state(getCloseButtonRect(), mCloseButtonHovered ? STATE_HOVERED : 0);
+ gui->getTheme()->drawSkin(g, SkinType::ButtonClose, state);
}
- // Draw Sticky Button
if (mStickyButton)
{
- Image *button = mSkin->getStickyImage(mSticky);
- int x = getWidth() - button->getWidth() - getPadding();
- if (mCloseButton)
- x -= mSkin->getCloseImage()->getWidth();
-
- g->drawImage(button, x, getPadding());
+ WidgetState state(getStickyButtonRect(), mSticky ? STATE_SELECTED : 0);
+ gui->getTheme()->drawSkin(g, SkinType::ButtonSticky, state);
}
drawChildren(graphics);
}
+void Window::drawFrame(gcn::Graphics *graphics)
+{
+ auto g = static_cast<Graphics*>(graphics);
+
+ WidgetState widgetState(this);
+ widgetState.width += getFrameSize() * 2;
+ widgetState.height += getFrameSize() * 2;
+
+ auto &skin = getSkin();
+ skin.draw(g, widgetState);
+
+ if (mShowTitle)
+ {
+ if (auto skinState = skin.getState(widgetState.flags))
+ {
+ auto &textFormat = skinState->textFormat;
+ TextRenderer::renderText(g,
+ getCaption(),
+ getFrameSize() + skin.titleOffsetX,
+ getFrameSize() + skin.titleOffsetY,
+ gcn::Graphics::LEFT,
+ textFormat.bold ? boldFont : getFont(),
+ textFormat);
+ }
+ }
+}
+
void Window::setContentSize(int width, int height)
{
- width = width + 2 * getPadding();
- height = height + getPadding() + getTitleBarHeight();
+ width += 2 * getPadding();
+ height += getPadding() + getTitleBarHeight();
if (getMinWidth() > width)
width = getMinWidth();
@@ -156,6 +167,16 @@ void Window::setContentSize(int width, int height)
setSize(width, height);
}
+void Window::setMinimumContentSize(int width, int height)
+{
+ const int padding = getPadding();
+ const int titleBarHeight = getTitleBarHeight();
+ auto &skin = getSkin();
+
+ setMinWidth(std::max(skin.getMinWidth(), width + 2 * padding));
+ setMinHeight(std::max(skin.getMinHeight(), height + padding + titleBarHeight));
+}
+
void Window::setLocationRelativeTo(gcn::Widget *widget)
{
int wx;
@@ -218,13 +239,12 @@ void Window::setLocationRelativeTo(ImageRect::ImagePosition position,
void Window::setMinWidth(int width)
{
- mMinWinWidth = width > mSkin->getMinWidth() ? width : mSkin->getMinWidth();
+ mMinWinWidth = std::max(getSkin().getMinWidth(), width);
}
void Window::setMinHeight(int height)
{
- mMinWinHeight = height > mSkin->getMinHeight() ?
- height : mSkin->getMinHeight();
+ mMinWinHeight = std::max(getSkin().getMinHeight(), height);
}
void Window::setMaxWidth(int width)
@@ -276,9 +296,7 @@ void Window::widgetResized(const gcn::Event &event)
void Window::widgetHidden(const gcn::Event &event)
{
if (gui)
- {
- gui->setCursorType(Cursor::POINTER);
- }
+ gui->setCursorType(Cursor::Pointer);
WidgetListIterator it;
@@ -341,38 +359,13 @@ void Window::mousePressed(gcn::MouseEvent &event)
const int x = event.getX();
const int y = event.getY();
- // Handle close button
- if (mCloseButton)
- {
- gcn::Rectangle closeButtonRect(
- getWidth() - mSkin->getCloseImage()->getWidth() - getPadding(),
- getPadding(),
- mSkin->getCloseImage()->getWidth(),
- mSkin->getCloseImage()->getHeight());
-
- if (closeButtonRect.isPointInRect(x, y))
- {
- close();
- }
- }
+ if (mCloseButton && getCloseButtonRect().isPointInRect(x, y))
+ close();
- // Handle sticky button
- if (mStickyButton)
- {
- Image *button = mSkin->getStickyImage(mSticky);
- int rx = getWidth() - button->getWidth() - getPadding();
- if (mCloseButton)
- rx -= mSkin->getCloseImage()->getWidth();
- gcn::Rectangle stickyButtonRect(rx, getPadding(),
- button->getWidth(), button->getHeight());
-
- if (stickyButtonRect.isPointInRect(x, y))
- {
- setSticky(!isSticky());
- }
- }
+ if (mStickyButton && getStickyButtonRect().isPointInRect(x, y))
+ setSticky(!isSticky());
- // Handle window resizing
+ // Update resizing state and disable moving if we're resizing the window
mouseResize = getResizeHandles(event);
if (mouseResize)
mMoved = false;
@@ -384,6 +377,11 @@ void Window::close()
setVisible(false);
}
+const Skin &Window::getSkin() const
+{
+ return gui->getTheme()->getSkin(mSkinType);
+}
+
void Window::mouseReleased(gcn::MouseEvent &event)
{
mouseResize = 0;
@@ -394,11 +392,15 @@ void Window::mouseReleased(gcn::MouseEvent &event)
void Window::mouseExited(gcn::MouseEvent &event)
{
if (mGrip && !mouseResize)
- gui->setCursorType(Cursor::POINTER);
+ gui->setCursorType(Cursor::Pointer);
+
+ mCloseButtonHovered = false;
}
void Window::mouseMoved(gcn::MouseEvent &event)
{
+ mCloseButtonHovered = false;
+
// Make sure BeingPopup is hidden (Viewport does not receive mouseExited)
if (viewport)
viewport->hideBeingPopup();
@@ -408,30 +410,36 @@ void Window::mouseMoved(gcn::MouseEvent &event)
if (event.isConsumed())
return;
- int resizeHandles = getResizeHandles(event);
+ mCloseButtonHovered = getCloseButtonRect().isPointInRect(event.getX(), event.getY());
+ Cursor cursor = Cursor::Pointer;
// Changes the custom mouse cursor based on its current position.
- switch (resizeHandles)
+ if (!mCloseButtonHovered)
{
+ switch (getResizeHandles(event))
+ {
case BOTTOM | RIGHT:
case TOP | LEFT:
- gui->setCursorType(Cursor::RESIZE_DOWN_RIGHT);
+ cursor = Cursor::ResizeDownRight;
break;
case BOTTOM | LEFT:
case TOP | RIGHT:
- gui->setCursorType(Cursor::RESIZE_DOWN_LEFT);
+ cursor = Cursor::ResizeDownLeft;
break;
case BOTTOM:
case TOP:
- gui->setCursorType(Cursor::RESIZE_DOWN);
+ cursor = Cursor::ResizeDown;
break;
case RIGHT:
case LEFT:
- gui->setCursorType(Cursor::RESIZE_ACROSS);
+ cursor = Cursor::ResizeAcross;
break;
default:
- gui->setCursorType(Cursor::POINTER);
+ break;
+ }
}
+
+ gui->setCursorType(cursor);
}
void Window::mouseDragged(gcn::MouseEvent &event)
@@ -675,6 +683,13 @@ int Window::getResizeHandles(gcn::MouseEvent &event)
if (inPadding && event.getSource() == this)
{
+ /**
+ * The width of the resize border. Is independent of the actual window
+ * border width, and determines mostly the size of the corner area
+ * where two borders are moved at the same time.
+ */
+ const int resizeBorderWidth = std::max(mGrip->getWidth(), 10);
+
resizeHandles |= (x >= getWidth() - resizeBorderWidth) ? RIGHT :
(x < resizeBorderWidth) ? LEFT : 0;
resizeHandles |= (y >= getHeight() - resizeBorderWidth) ? BOTTOM :
@@ -692,10 +707,55 @@ int Window::getResizeHandles(gcn::MouseEvent &event)
return resizeHandles;
}
+gcn::Rectangle Window::getCloseButtonRect() const
+{
+ if (!mCloseButton)
+ return {};
+
+ auto theme = gui->getTheme();
+
+ auto &closeSkin = theme->getSkin(SkinType::ButtonClose);
+ const int closeWidth = closeSkin.getMinWidth();
+ const int closeHeight = closeSkin.getMinHeight();
+
+ return {
+ getWidth() - closeWidth - closeSkin.padding,
+ closeSkin.padding,
+ closeWidth,
+ closeHeight
+ };
+}
+
+gcn::Rectangle Window::getStickyButtonRect() const
+{
+ if (!mStickyButton)
+ return {};
+
+ auto theme = gui->getTheme();
+
+ auto &closeSkin = theme->getSkin(SkinType::ButtonClose);
+ const int closeWidth = closeSkin.getMinWidth();
+
+ auto &stickySkin = theme->getSkin(SkinType::ButtonSticky);
+ const int stickyWidth = stickySkin.getMinWidth();
+ const int stickyHeight = stickySkin.getMinHeight();
+
+ int stickyX = getWidth() - stickyWidth - stickySkin.padding - stickySkin.spacing;
+ if (mCloseButton)
+ stickyX -= closeWidth + closeSkin.padding;
+
+ return {
+ stickyX,
+ stickySkin.padding,
+ stickyWidth,
+ stickyHeight
+ };
+}
+
int Window::getGuiAlpha()
{
float alpha = std::max(config.guiAlpha,
- Theme::instance()->getMinimumOpacity());
+ gui->getTheme()->getMinimumOpacity());
return (int) (alpha * 255.0f);
}
diff --git a/src/gui/widgets/window.h b/src/gui/widgets/window.h
index bf6f363c..6331a715 100644
--- a/src/gui/widgets/window.h
+++ b/src/gui/widgets/window.h
@@ -19,14 +19,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef WINDOW_H
-#define WINDOW_H
+#pragma once
#include "graphics.h"
#include "guichanfwd.h"
-#include <guichan/widgetlistener.hpp>
+#include "resources/theme.h"
+#include <guichan/widgetlistener.hpp>
#include <guichan/widgets/window.hpp>
class ContainerPlacer;
@@ -54,10 +54,18 @@ class Window : public gcn::Window, gcn::WidgetListener
* @param parent The parent window. This is the window standing above
* this one in the window hiearchy. When reordering,
* a window will never go below its parent window.
- * @param skin The location where the window's skin XML can be found.
*/
- Window(const std::string &caption = "Window", bool modal = false,
- Window *parent = nullptr, const std::string &skin = "window.xml");
+ Window(const std::string &caption = "Window",
+ bool modal = false,
+ Window *parent = nullptr);
+
+ /**
+ * Constructor that allows customizing the SkinType used by the window.
+ */
+ Window(SkinType skinType,
+ const std::string &caption = "Window",
+ bool modal = false,
+ Window *parent = nullptr);
/**
* Destructor. Deletes all the added widgets.
@@ -70,16 +78,26 @@ class Window : public gcn::Window, gcn::WidgetListener
static void setWindowContainer(WindowContainer *windowContainer);
/**
- * Draws the window.
+ * Draws the window contents.
*/
void draw(gcn::Graphics *graphics) override;
/**
+ * Draws the window frame.
+ */
+ void drawFrame(gcn::Graphics *graphics) override;
+
+ /**
* Sets the size of this window.
*/
void setContentSize(int width, int height);
/**
+ * Sets the minimum size of the window content.
+ */
+ void setMinimumContentSize(int width, int height);
+
+ /**
* Sets the location relative to the given widget.
*/
void setLocationRelativeTo(gcn::Widget *widget);
@@ -345,6 +363,11 @@ class Window : public gcn::Window, gcn::WidgetListener
virtual void close();
/**
+ * Returns the Skin used by this window.
+ */
+ const Skin &getSkin() const;
+
+ /**
* Gets the alpha value used by the window, in a Guichan usable format.
*/
static int getGuiAlpha();
@@ -377,6 +400,9 @@ class Window : public gcn::Window, gcn::WidgetListener
*/
int getResizeHandles(gcn::MouseEvent &event);
+ gcn::Rectangle getCloseButtonRect() const;
+ gcn::Rectangle getStickyButtonRect() const;
+
ResizeGrip *mGrip = nullptr; /**< Resize grip */
Window *mParent; /**< The parent window */
Layout *mLayout = nullptr; /**< Layout handler */
@@ -384,10 +410,12 @@ class Window : public gcn::Window, gcn::WidgetListener
bool mShowTitle = true; /**< Window has a title bar */
bool mModal; /**< Window is modal */
bool mCloseButton = false; /**< Window has a close button */
+ bool mCloseButtonHovered = false;
bool mDefaultVisible = false; /**< Window's default visibility */
bool mSaveVisible = false; /**< Window will save visibility */
bool mStickyButton = false; /**< Window has a sticky button */
bool mSticky = false; /**< Window resists hiding*/
+ SkinType mSkinType; /**< The skin type used when drawing the window. */
int mMinWinWidth = 100; /**< Minimum window width */
int mMinWinHeight = 40; /**< Minimum window height */
int mMaxWinWidth; /**< Maximum window width */
@@ -398,15 +426,4 @@ class Window : public gcn::Window, gcn::WidgetListener
int mDefaultHeight; /**< Default window height */
static int instances; /**< Number of Window instances */
-
- Skin *mSkin; /**< Skin in use by this window */
-
- /**
- * The width of the resize border. Is independent of the actual window
- * border width, and determines mostly the size of the corner area
- * where two borders are moved at the same time.
- */
- static const int resizeBorderWidth = 10;
};
-
-#endif
diff --git a/src/gui/widgets/windowcontainer.cpp b/src/gui/widgets/windowcontainer.cpp
index 36f0998f..4e350a9e 100644
--- a/src/gui/widgets/windowcontainer.cpp
+++ b/src/gui/widgets/windowcontainer.cpp
@@ -24,16 +24,15 @@
#include "gui/gui.h"
#include "gui/widgets/window.h"
-#include "utils/dtor.h"
-
#include <guichan/focushandler.hpp>
WindowContainer *windowContainer = nullptr;
void WindowContainer::logic()
{
- delete_all(mDeathList);
- mDeathList.clear();
+ for (auto widget : mScheduledDeletions)
+ delete widget;
+ mScheduledDeletions.clear();
gcn::Container::logic();
}
@@ -48,7 +47,7 @@ void WindowContainer::draw(gcn::Graphics *graphics)
void WindowContainer::scheduleDelete(gcn::Widget *widget)
{
- mDeathList.push_back(widget);
+ mScheduledDeletions.insert(widget);
}
void WindowContainer::adjustAfterResize(int oldScreenWidth,
diff --git a/src/gui/widgets/windowcontainer.h b/src/gui/widgets/windowcontainer.h
index 861839c9..ff03a903 100644
--- a/src/gui/widgets/windowcontainer.h
+++ b/src/gui/widgets/windowcontainer.h
@@ -19,11 +19,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef WINDOWCONTAINER_H
-#define WINDOWCONTAINER_H
+#pragma once
#include "gui/widgets/container.h"
+#include <set>
+
/**
* A window container. This container adds functionality for more convenient
* widget (windows in particular) destruction.
@@ -65,11 +66,9 @@ class WindowContainer : public Container
bool widgetIsVisible(gcn::Widget *widget);
/**
- * List of widgets that are scheduled to be deleted.
+ * Set of widgets that are scheduled to be deleted.
*/
- std::list<gcn::Widget *> mDeathList;
+ std::set<gcn::Widget *> mScheduledDeletions;
};
extern WindowContainer *windowContainer;
-
-#endif
diff --git a/src/gui/windowmenu.cpp b/src/gui/windowmenu.cpp
index c6e52ee7..0b2d126f 100644
--- a/src/gui/windowmenu.cpp
+++ b/src/gui/windowmenu.cpp
@@ -25,7 +25,7 @@
#include "gui/emotepopup.h"
#include "gui/skilldialog.h"
-#include "gui/specialswindow.h"
+#include "gui/abilitieswindow.h"
#include "gui/widgets/button.h"
#include "gui/widgets/window.h"
@@ -61,8 +61,8 @@ WindowMenu::WindowMenu()
addButton(N_("Skills"), x, h, "button-icon-skills.png",
KeyboardConfig::KEY_WINDOW_SKILL);
- if (specialsWindow->hasSpecials())
- addButton(N_("Specials"), x, h, "button-icon-specials.png");
+ if (abilitiesWindow->hasAbilities())
+ addButton(N_("Abilities"), x, h, "button-icon-abilities.png");
addButton(N_("Social"), x, h, "button-icon-social.png",
KeyboardConfig::KEY_WINDOW_SOCIAL);
@@ -122,9 +122,9 @@ void WindowMenu::action(const gcn::ActionEvent &event)
{
window = skillDialog;
}
- else if (event.getId() == "Specials")
+ else if (event.getId() == "Abilities")
{
- window = specialsWindow;
+ window = abilitiesWindow;
}
else if (event.getId() == "Social")
{
diff --git a/src/gui/windowmenu.h b/src/gui/windowmenu.h
index 0eabc247..b80b62b0 100644
--- a/src/gui/windowmenu.h
+++ b/src/gui/windowmenu.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef WINDOWMENU_H
-#define WINDOWMENU_H
+#pragma once
#include "keyboardconfig.h"
@@ -62,5 +61,3 @@ class WindowMenu : public Container,
EmotePopup *mEmotePopup = nullptr;
};
-
-#endif
diff --git a/src/gui/worldselectdialog.h b/src/gui/worldselectdialog.h
index a1150cb8..702a5616 100644
--- a/src/gui/worldselectdialog.h
+++ b/src/gui/worldselectdialog.h
@@ -19,8 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef WORLD_SELECT_DIALOG_H
-#define WORLD_SELECT_DIALOG_H
+#pragma once
#include "gui/widgets/window.h"
@@ -62,5 +61,3 @@ class WorldSelectDialog : public Window, public gcn::ActionListener,
gcn::Button *mChangeLoginButton;
gcn::Button *mChooseWorld;
};
-
-#endif // WORLD_SELECT_DIALOG_H