summaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-03-24 14:28:55 +0100
committerThorbjørn Lindeijer <bjorn@lindeijer.nl>2025-03-24 21:14:28 +0100
commitc600e0fae271ed25d066b01149fbc148295edde8 (patch)
tree6b57ba0988d9d38f3bf760ccc208ec8298bfbdde /src/gui
parent5274cc92c1055a3209dfae7e5346bfe52c35e4a8 (diff)
downloadmana-c600e0fae271ed25d066b01149fbc148295edde8.tar.gz
mana-c600e0fae271ed25d066b01149fbc148295edde8.tar.bz2
mana-c600e0fae271ed25d066b01149fbc148295edde8.tar.xz
mana-c600e0fae271ed25d066b01149fbc148295edde8.zip
Expanded GUI theming capabilities
* Moved previously hardcoded values for frame size, padding and title bar height to the Skin. * Added support for rendering colored rectangles (used for scroll bar background). * Scroll bar width is now determined by its skin. * Added separate skins for horizontal and vertical scroll bars and horizontal and vertical scroll markers and added a skin for the shortcut box. * Added support for hovered state on window close button.
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/equipmentwindow.cpp12
-rw-r--r--src/gui/equipmentwindow.h5
-rw-r--r--src/gui/helpwindow.cpp1
-rw-r--r--src/gui/npcdialog.cpp1
-rw-r--r--src/gui/setup_video.cpp2
-rw-r--r--src/gui/setup_video.h3
-rw-r--r--src/gui/shortcutwindow.cpp10
-rw-r--r--src/gui/updaterwindow.cpp1
-rw-r--r--src/gui/widgets/button.cpp4
-rw-r--r--src/gui/widgets/container.h3
-rw-r--r--src/gui/widgets/dropdown.cpp77
-rw-r--r--src/gui/widgets/dropdown.h7
-rw-r--r--src/gui/widgets/emoteshortcutcontainer.cpp31
-rw-r--r--src/gui/widgets/itemcontainer.h3
-rw-r--r--src/gui/widgets/itemshortcutcontainer.cpp51
-rw-r--r--src/gui/widgets/itemshortcutcontainer.h4
-rw-r--r--src/gui/widgets/listbox.h3
-rw-r--r--src/gui/widgets/popup.cpp16
-rw-r--r--src/gui/widgets/popup.h5
-rw-r--r--src/gui/widgets/resizegrip.cpp6
-rw-r--r--src/gui/widgets/scrollarea.cpp95
-rw-r--r--src/gui/widgets/scrollarea.h11
-rw-r--r--src/gui/widgets/shortcutcontainer.cpp14
-rw-r--r--src/gui/widgets/shortcutcontainer.h21
-rw-r--r--src/gui/widgets/slider.cpp10
-rw-r--r--src/gui/widgets/slider.h9
-rw-r--r--src/gui/widgets/tab.cpp43
-rw-r--r--src/gui/widgets/tab.h18
-rw-r--r--src/gui/widgets/table.cpp52
-rw-r--r--src/gui/widgets/table.h13
-rw-r--r--src/gui/widgets/textfield.cpp22
-rw-r--r--src/gui/widgets/textfield.h30
-rw-r--r--src/gui/widgets/window.cpp162
-rw-r--r--src/gui/widgets/window.h11
34 files changed, 451 insertions, 305 deletions
diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp
index 569bcf8b..ff3c6630 100644
--- a/src/gui/equipmentwindow.cpp
+++ b/src/gui/equipmentwindow.cpp
@@ -65,13 +65,14 @@ 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);
@@ -108,7 +109,6 @@ EquipmentWindow::~EquipmentWindow()
void EquipmentWindow::draw(gcn::Graphics *graphics)
{
Window::draw(graphics);
- Window::drawChildren(graphics);
// Draw equipment boxes
auto *g = static_cast<Graphics*>(graphics);
@@ -237,6 +237,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();
@@ -261,6 +263,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 a5cda4e3..f46d1175 100644
--- a/src/gui/equipmentwindow.h
+++ b/src/gui/equipmentwindow.h
@@ -54,6 +54,8 @@ class EquipmentWindow : public Window, public gcn::ActionListener
void action(const gcn::ActionEvent &event) override;
void mousePressed(gcn::MouseEvent& mouseEvent) override;
+ void mouseMoved(gcn::MouseEvent &event) override;
+ void mouseExited(gcn::MouseEvent &event) override;
/**
* Loads the correct amount of displayed equip boxes.
@@ -83,9 +85,6 @@ class EquipmentWindow : public Window, public gcn::ActionListener
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;
diff --git a/src/gui/helpwindow.cpp b/src/gui/helpwindow.cpp
index e687e817..e0e21610 100644
--- a/src/gui/helpwindow.cpp
+++ b/src/gui/helpwindow.cpp
@@ -48,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);
diff --git a/src/gui/npcdialog.cpp b/src/gui/npcdialog.cpp
index 1df40d4f..e2e7b040 100644
--- a/src/gui/npcdialog.cpp
+++ b/src/gui/npcdialog.cpp
@@ -87,7 +87,6 @@ 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);
diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp
index 38602a5c..68fb6767 100644
--- a/src/gui/setup_video.cpp
+++ b/src/gui/setup_video.cpp
@@ -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 17b82e00..969d8e8f 100644
--- a/src/gui/setup_video.h
+++ b/src/gui/setup_video.h
@@ -29,6 +29,7 @@
#include <guichan/actionlistener.hpp>
#include <guichan/keylistener.hpp>
+class DropDown;
class ResolutionListModel;
class ScaleListModel;
@@ -59,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;
diff --git a/src/gui/shortcutwindow.cpp b/src/gui/shortcutwindow.cpp
index 7d299d2c..82c7678e 100644
--- a/src/gui/shortcutwindow.cpp
+++ b/src/gui/shortcutwindow.cpp
@@ -41,7 +41,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 +53,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/updaterwindow.cpp b/src/gui/updaterwindow.cpp
index 34169195..d05a9299 100644
--- a/src/gui/updaterwindow.cpp
+++ b/src/gui/updaterwindow.cpp
@@ -140,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);
diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp
index 215cb5a0..31fab2c4 100644
--- a/src/gui/widgets/button.cpp
+++ b/src/gui/widgets/button.cpp
@@ -109,7 +109,9 @@ void Button::removeButtonIcon()
void Button::init()
{
- setFrameSize(0);
+ auto &skin = gui->getTheme()->getSkin(SkinType::Button);
+ setFrameSize(skin.frameSize);
+ setSpacing(skin.padding);
if (mInstances == 0)
{
diff --git a/src/gui/widgets/container.h b/src/gui/widgets/container.h
index 9ef805ad..fbdaa1d4 100644
--- a/src/gui/widgets/container.h
+++ b/src/gui/widgets/container.h
@@ -43,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.
diff --git a/src/gui/widgets/dropdown.cpp b/src/gui/widgets/dropdown.cpp
index 1d54efd7..45c8e53f 100644
--- a/src/gui/widgets/dropdown.cpp
+++ b/src/gui/widgets/dropdown.cpp
@@ -31,12 +31,18 @@
#include "resources/theme.h"
+#include <guichan/font.hpp>
+
DropDown::DropDown(gcn::ListModel *listModel):
gcn::DropDown::DropDown(listModel,
new ScrollArea,
new ListBox(listModel))
{
- setFrameSize(2);
+ auto &skin = gui->getTheme()->getSkin(SkinType::DropDownFrame);
+ setFrameSize(skin.frameSize);
+ mPadding = skin.padding;
+
+ setHeight(getFont()->getHeight() + 2 * mPadding);
}
DropDown::~DropDown()
@@ -59,13 +65,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->drawRectangle(
+ gcn::Rectangle(mPadding, mPadding, getWidth() - h - mPadding * 2, h - 2 * mPadding));
}
drawButton(graphics);
@@ -94,6 +103,39 @@ void DropDown::drawFrame(gcn::Graphics *graphics)
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)
{
WidgetState state(this);
@@ -177,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 53bfd0e2..a5e2e2f7 100644
--- a/src/gui/widgets/dropdown.h
+++ b/src/gui/widgets/dropdown.h
@@ -47,6 +47,8 @@ class DropDown : public gcn::DropDown
void drawFrame(gcn::Graphics *graphics) override;
+ void adjustHeight();
+
// Inherited from FocusListener
void focusLost(const gcn::Event& event) override;
@@ -70,4 +72,9 @@ class DropDown : public gcn::DropDown
* @param graphics a Graphics object to draw with.
*/
void drawButton(gcn::Graphics *graphics) override;
+
+ void dropDown() override;
+ void foldUp() override;
+
+ int mPadding = 1;
};
diff --git a/src/gui/widgets/emoteshortcutcontainer.cpp b/src/gui/widgets/emoteshortcutcontainer.cpp
index 1aef6323..06d80ec2 100644
--- a/src/gui/widgets/emoteshortcutcontainer.cpp
+++ b/src/gui/widgets/emoteshortcutcontainer.cpp
@@ -21,11 +21,12 @@
#include "gui/widgets/emoteshortcutcontainer.h"
-#include "configuration.h"
#include "emoteshortcut.h"
#include "graphics.h"
#include "keyboardconfig.h"
+#include "gui/gui.h"
+
#include "resources/emotedb.h"
#include "resources/image.h"
#include "resources/theme.h"
@@ -34,40 +35,28 @@ static const int MAX_ITEMS = 12;
EmoteShortcutContainer::EmoteShortcutContainer()
{
- addMouseListener(this);
- addWidgetListener(this);
-
- mBackgroundImg = Theme::getImageFromTheme("item_shortcut_bgr.png");
-
mMaxItems = std::min(EmoteDB::getEmoteCount(), MAX_ITEMS);
-
- if (mBackgroundImg)
- {
- mBoxHeight = mBackgroundImg->getHeight();
- mBoxWidth = mBackgroundImg->getWidth();
- }
}
void EmoteShortcutContainer::draw(gcn::Graphics *graphics)
{
- mBackgroundImg->setAlpha(config.guiAlpha);
-
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)
@@ -75,7 +64,7 @@ void EmoteShortcutContainer::draw(gcn::Graphics *graphics)
if (auto image = EmoteDB::get(emoteId).image)
{
image->setAlpha(1.0f);
- g->drawImage(image, emoteX + 2, emoteY + 10);
+ g->drawImage(image, state.x + 2, state.y + 10);
}
}
}
@@ -112,6 +101,7 @@ void EmoteShortcutContainer::mouseDragged(gcn::MouseEvent &event)
emoteShortcut->removeEmote(index);
}
}
+
if (mEmoteMoved != -1)
{
mCursorPosX = event.getX();
@@ -123,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;
diff --git a/src/gui/widgets/itemcontainer.h b/src/gui/widgets/itemcontainer.h
index 7c972347..0a8ac1e2 100644
--- a/src/gui/widgets/itemcontainer.h
+++ b/src/gui/widgets/itemcontainer.h
@@ -72,6 +72,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;
diff --git a/src/gui/widgets/itemshortcutcontainer.cpp b/src/gui/widgets/itemshortcutcontainer.cpp
index 594ad1ce..4d0641b1 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,47 +38,32 @@
#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();
-
- if (mBackgroundImg)
- {
- mBoxHeight = mBackgroundImg->getHeight();
- mBoxWidth = mBackgroundImg->getWidth();
- }
}
-ItemShortcutContainer::~ItemShortcutContainer()
-{
- delete mItemPopup;
-}
+ItemShortcutContainer::~ItemShortcutContainer() = default;
void ItemShortcutContainer::draw(gcn::Graphics *graphics)
{
- mBackgroundImg->setAlpha(config.guiAlpha);
-
auto *g = static_cast<Graphics*>(graphics);
+ auto theme = gui->getTheme();
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;
+ theme->drawSkin(g, SkinType::ShortcutBox, 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 + 2, state.y + 2, gcn::Graphics::LEFT);
if (itemShortcut->getItem(i) < 0)
continue;
@@ -101,11 +85,11 @@ void ItemShortcutContainer::draw(gcn::Graphics *graphics)
caption = "Eq.";
image->setAlpha(1.0f);
- g->drawImage(image, itemX, itemY);
+ g->drawImage(image, state.x, state.y);
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);
}
}
}
@@ -133,23 +117,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();
@@ -222,18 +203,14 @@ void ItemShortcutContainer::mouseReleased(gcn::MouseEvent &event)
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 = PlayerInfo::getInventory()->findItem(itemId))
{
mItemPopup->setItem(item->getInfo());
mItemPopup->position(viewport->getMouseX(), viewport->getMouseY());
diff --git a/src/gui/widgets/itemshortcutcontainer.h b/src/gui/widgets/itemshortcutcontainer.h
index e346b1b6..63d9e0ef 100644
--- a/src/gui/widgets/itemshortcutcontainer.h
+++ b/src/gui/widgets/itemshortcutcontainer.h
@@ -25,6 +25,8 @@
#include <guichan/mouselistener.hpp>
+#include <memory>
+
class Image;
class Item;
class ItemPopup;
@@ -68,5 +70,5 @@ class ItemShortcutContainer : public ShortcutContainer
bool mItemClicked = false;
Item *mItemMoved = nullptr;
- ItemPopup *mItemPopup;
+ std::unique_ptr<ItemPopup> mItemPopup;
};
diff --git a/src/gui/widgets/listbox.h b/src/gui/widgets/listbox.h
index d5b4e759..40bc2fbc 100644
--- a/src/gui/widgets/listbox.h
+++ b/src/gui/widgets/listbox.h
@@ -42,6 +42,9 @@ class ListBox : public gcn::ListBox
*/
void draw(gcn::Graphics *graphics) override;
+ // Overridden to disable drawing of the frame
+ void drawFrame(gcn::Graphics *graphics) override {}
+
// Inherited from KeyListener
void keyPressed(gcn::KeyEvent& keyEvent) override;
diff --git a/src/gui/widgets/popup.cpp b/src/gui/widgets/popup.cpp
index 8bbab948..b7c70fe5 100644
--- a/src/gui/widgets/popup.cpp
+++ b/src/gui/widgets/popup.cpp
@@ -42,7 +42,9 @@ Popup::Popup(const std::string &name, SkinType skinType)
if (!windowContainer)
throw GCN_EXCEPTION("Popup::Popup(): no windowContainer set");
- setPadding(6);
+ auto &skin = gui->getTheme()->getSkin(skinType);
+ setFrameSize(skin.frameSize);
+ setPadding(skin.padding);
// Add this window to the window container
windowContainer->add(this);
@@ -63,10 +65,20 @@ void Popup::setWindowContainer(WindowContainer *wc)
void Popup::draw(gcn::Graphics *graphics)
{
- gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics), mSkinType, WidgetState(this));
+ if (getFrameSize() == 0)
+ drawFrame(graphics);
+
drawChildren(graphics);
}
+void Popup::drawFrame(gcn::Graphics *graphics)
+{
+ WidgetState state(this);
+ state.width += getFrameSize() * 2;
+ state.height += getFrameSize() * 2;
+ gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics), mSkinType, state);
+}
+
gcn::Rectangle Popup::getChildrenArea()
{
return gcn::Rectangle(getPadding(), getPadding(),
diff --git a/src/gui/widgets/popup.h b/src/gui/widgets/popup.h
index 6a206672..012b55de 100644
--- a/src/gui/widgets/popup.h
+++ b/src/gui/widgets/popup.h
@@ -74,6 +74,11 @@ class Popup : public Container, public gcn::MouseListener
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);
diff --git a/src/gui/widgets/resizegrip.cpp b/src/gui/widgets/resizegrip.cpp
index 69803d07..c802a405 100644
--- a/src/gui/widgets/resizegrip.cpp
+++ b/src/gui/widgets/resizegrip.cpp
@@ -30,10 +30,8 @@
ResizeGrip::ResizeGrip()
{
- const auto theme = gui->getTheme();
- const auto minWidth = theme->getMinWidth(SkinType::ResizeGrip);
- const auto minHeight = theme->getMinHeight(SkinType::ResizeGrip);
- setSize(minWidth + 2, minHeight + 2);
+ auto &skin = gui->getTheme()->getSkin(SkinType::ResizeGrip);
+ setSize(skin.getMinWidth() + skin.padding, skin.getMinHeight() + skin.padding);
}
void ResizeGrip::draw(gcn::Graphics *graphics)
diff --git a/src/gui/widgets/scrollarea.cpp b/src/gui/widgets/scrollarea.cpp
index 62c37c64..8ee6692f 100644
--- a/src/gui/widgets/scrollarea.cpp
+++ b/src/gui/widgets/scrollarea.cpp
@@ -27,7 +27,6 @@
ScrollArea::ScrollArea()
{
- addWidgetListener(this);
init();
}
@@ -47,10 +46,24 @@ void ScrollArea::init()
// Draw background by default
setOpaque(true);
- setUpButtonScrollAmount(2);
- setDownButtonScrollAmount(2);
- setLeftButtonScrollAmount(2);
- setRightButtonScrollAmount(2);
+ auto theme = gui->getTheme();
+
+ int minWidth = theme->getSkin(SkinType::ScrollAreaVBar).getMinWidth();
+ if (minWidth > 0)
+ setScrollbarWidth(minWidth);
+
+ if (auto content = getContent())
+ content->setFrameSize(theme->getSkin(SkinType::ScrollArea).padding);
+
+ // 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));
+
+ setUpButtonScrollAmount(5);
+ setDownButtonScrollAmount(5);
+ setLeftButtonScrollAmount(5);
+ setRightButtonScrollAmount(5);
}
void ScrollArea::logic()
@@ -99,6 +112,14 @@ void ScrollArea::logic()
}
}
+void ScrollArea::draw(gcn::Graphics *graphics)
+{
+ if (getFrameSize() == 0)
+ drawFrame(graphics);
+
+ gcn::ScrollArea::draw(graphics);
+}
+
void ScrollArea::drawFrame(gcn::Graphics *graphics)
{
if (!mOpaque)
@@ -116,7 +137,9 @@ void ScrollArea::drawFrame(gcn::Graphics *graphics)
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::drawBackground(gcn::Graphics *graphics)
@@ -146,30 +169,38 @@ void ScrollArea::drawRightButton(gcn::Graphics *graphics)
void ScrollArea::drawVBar(gcn::Graphics *graphics)
{
- graphics->setColor(gcn::Color(0, 0, 0, 32));
- graphics->fillRectangle(getVerticalBarDimension());
- 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)
{
- graphics->setColor(gcn::Color(0, 0, 0, 32));
- graphics->fillRectangle(getHorizontalBarDimension());
- 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)
{
- drawMarker(static_cast<Graphics *>(graphics),
- mHasMouse && (mX > (getWidth() - getScrollbarWidth())),
- getVerticalMarkerDimension());
+ WidgetState state(getVerticalMarkerDimension());
+ 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)
{
- drawMarker(static_cast<Graphics *>(graphics),
- mHasMouse && (mY > (getHeight() - getScrollbarWidth())),
- getHorizontalMarkerDimension());
+ WidgetState state(getHorizontalMarkerDimension());
+ if (mHasMouse && (mY > (getHeight() - getScrollbarWidth())))
+ state.flags |= STATE_HOVERED;
+
+ gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics), SkinType::ScrollAreaHMarker, state);
}
void ScrollArea::drawButton(gcn::Graphics *graphics,
@@ -177,30 +208,13 @@ void ScrollArea::drawButton(gcn::Graphics *graphics,
bool pressed,
const gcn::Rectangle &dim)
{
- WidgetState state;
- state.x = dim.x;
- state.y = dim.y;
- state.width = dim.width;
- state.height = dim.height;
+ WidgetState state(dim);
if (pressed)
state.flags |= STATE_SELECTED;
gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics), skinType, state);
}
-void ScrollArea::drawMarker(gcn::Graphics *graphics, bool hovered, const gcn::Rectangle &dim)
-{
- WidgetState state;
- state.x = dim.x;
- state.y = dim.y;
- state.width = dim.width;
- state.height = dim.height;
- if (hovered)
- state.flags |= STATE_HOVERED;
-
- gui->getTheme()->drawSkin(static_cast<Graphics *>(graphics), SkinType::ScrollBar, state);
-}
-
void ScrollArea::mouseMoved(gcn::MouseEvent& event)
{
mX = event.getX();
@@ -216,12 +230,3 @@ void ScrollArea::mouseExited(gcn::MouseEvent& event)
{
mHasMouse = false;
}
-
-void ScrollArea::widgetResized(const gcn::Event &event)
-{
- if (auto content = getContent())
- {
- content->setSize(getWidth() - 2 * getFrameSize(),
- getHeight() - 2 * getFrameSize());
- }
-}
diff --git a/src/gui/widgets/scrollarea.h b/src/gui/widgets/scrollarea.h
index 17f69548..314711bf 100644
--- a/src/gui/widgets/scrollarea.h
+++ b/src/gui/widgets/scrollarea.h
@@ -23,7 +23,6 @@
#include "resources/theme.h"
-#include <guichan/widgetlistener.hpp>
#include <guichan/widgets/scrollarea.hpp>
/**
@@ -35,7 +34,7 @@
*
* \ingroup GUI
*/
-class ScrollArea : public gcn::ScrollArea, public gcn::WidgetListener
+class ScrollArea : public gcn::ScrollArea
{
public:
/**
@@ -63,6 +62,11 @@ class ScrollArea : public gcn::ScrollArea, public gcn::WidgetListener
void logic() override;
/**
+ * Overridden to draw the frame if its size is 0.
+ */
+ void draw(gcn::Graphics *graphics) override;
+
+ /**
* Draws the background and border of the scroll area.
*/
void drawFrame(gcn::Graphics *graphics) override;
@@ -92,8 +96,6 @@ class ScrollArea : public gcn::ScrollArea, public gcn::WidgetListener
*/
void mouseExited(gcn::MouseEvent& event) override;
- void widgetResized(const gcn::Event &event) override;
-
protected:
/**
* Initializes the scroll area.
@@ -114,7 +116,6 @@ class ScrollArea : public gcn::ScrollArea, public gcn::WidgetListener
SkinType skinType,
bool pressed,
const gcn::Rectangle &dim);
- static void drawMarker(gcn::Graphics *graphics, bool hovered, const gcn::Rectangle &dim);
int mX = 0;
int mY = 0;
diff --git a/src/gui/widgets/shortcutcontainer.cpp b/src/gui/widgets/shortcutcontainer.cpp
index 4bcf3860..ccf4b082 100644
--- a/src/gui/widgets/shortcutcontainer.cpp
+++ b/src/gui/widgets/shortcutcontainer.cpp
@@ -21,7 +21,19 @@
#include "gui/widgets/shortcutcontainer.h"
-ShortcutContainer::~ShortcutContainer() = default;
+#include "gui/gui.h"
+
+#include "resources/theme.h"
+
+ShortcutContainer::ShortcutContainer()
+{
+ addMouseListener(this);
+ addWidgetListener(this);
+
+ auto &skin = gui->getTheme()->getSkin(SkinType::ShortcutBox);
+ mBoxWidth = skin.getMinWidth();
+ mBoxHeight = skin.getMinHeight();
+}
void ShortcutContainer::widgetResized(const gcn::Event &event)
{
diff --git a/src/gui/widgets/shortcutcontainer.h b/src/gui/widgets/shortcutcontainer.h
index 9998e188..35a88d7f 100644
--- a/src/gui/widgets/shortcutcontainer.h
+++ b/src/gui/widgets/shortcutcontainer.h
@@ -21,8 +21,6 @@
#pragma once
-#include "resources/image.h"
-
#include <guichan/mouselistener.hpp>
#include <guichan/widget.hpp>
#include <guichan/widgetlistener.hpp>
@@ -37,28 +35,25 @@ class ShortcutContainer : public gcn::Widget,
public gcn::MouseListener
{
public:
- ShortcutContainer() = default;
- ~ShortcutContainer();
+ ShortcutContainer();
/**
* Draws the shortcuts
*/
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,8 +65,6 @@ class ShortcutContainer : public gcn::Widget,
*/
int getIndexFromGrid(int pointX, int pointY) const;
- ResourceRef<Image> mBackgroundImg;
-
int mMaxItems = 0;
int mBoxWidth = 0;
int mBoxHeight = 0;
diff --git a/src/gui/widgets/slider.cpp b/src/gui/widgets/slider.cpp
index 7ad5aa60..dd476eb9 100644
--- a/src/gui/widgets/slider.cpp
+++ b/src/gui/widgets/slider.cpp
@@ -40,8 +40,9 @@ Slider::Slider(double scaleStart, double scaleEnd):
void Slider::init()
{
- setFrameSize(0);
- setMarkerLength(gui->getTheme()->getMinWidth(SkinType::SliderHandle));
+ auto theme = gui->getTheme();
+ setFrameSize(theme->getSkin(SkinType::Slider).frameSize);
+ setMarkerLength(theme->getMinWidth(SkinType::SliderHandle));
}
void Slider::draw(gcn::Graphics *graphics)
@@ -58,11 +59,6 @@ void Slider::draw(gcn::Graphics *graphics)
theme->drawSkin(static_cast<Graphics*>(graphics), SkinType::SliderHandle, handleState);
}
-void Slider::drawMarker(gcn::Graphics *graphics)
-{
- // Marker is drawn in Slider::draw
-}
-
void Slider::mouseEntered(gcn::MouseEvent& event)
{
mHasMouse = true;
diff --git a/src/gui/widgets/slider.h b/src/gui/widgets/slider.h
index 142d3f6a..52b3b3af 100644
--- a/src/gui/widgets/slider.h
+++ b/src/gui/widgets/slider.h
@@ -49,10 +49,11 @@ class Slider : public gcn::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.
diff --git a/src/gui/widgets/tab.cpp b/src/gui/widgets/tab.cpp
index 5779b561..3bfa405f 100644
--- a/src/gui/widgets/tab.cpp
+++ b/src/gui/widgets/tab.cpp
@@ -33,27 +33,33 @@
Tab::Tab() :
mTabColor(&Theme::getThemeColor(Theme::TAB))
{
- init();
+ setFocusable(false);
+
+ auto &skin = gui->getTheme()->getSkin(SkinType::Tab);
+ setFrameSize(skin.frameSize);
+ mPadding = skin.padding;
+ mLabel->setPosition(mPadding, mPadding);
}
-void Tab::init()
+void Tab::setCaption(const std::string &caption)
{
- setFocusable(false);
- setFrameSize(0);
+ mLabel->setCaption(caption);
+ mLabel->adjustSize();
+
+ setSize(mLabel->getWidth() + mPadding * 2,
+ mLabel->getHeight() + mPadding * 2);
+
+ if (mTabbedArea)
+ static_cast<TabbedArea*>(mTabbedArea)->adjustTabPositions();
}
void Tab::draw(gcn::Graphics *graphics)
{
- WidgetState state(this);
- 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);
+ if (getFrameSize() == 0)
+ drawFrame(graphics);
// if tab is selected, it doesnt need to highlight activity
- if (state.flags & STATE_SELECTED)
+ if (mTabbedArea && mTabbedArea->isTabSelected(this))
mFlash = false;
if (mFlash)
@@ -65,6 +71,19 @@ void Tab::draw(gcn::Graphics *graphics)
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 7d1365fd..d67321c6 100644
--- a/src/gui/widgets/tab.h
+++ b/src/gui/widgets/tab.h
@@ -35,11 +35,23 @@ class Tab : public gcn::Tab
Tab();
/**
- * Draw the tabbed area.
+ * 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.
+ */
+ void setCaption(const std::string& caption);
+
+ /**
+ * 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);
@@ -54,9 +66,7 @@ class Tab : public gcn::Tab
virtual void setCurrent() {}
private:
- /** Load images if no other instances exist yet */
- void init();
-
const gcn::Color *mTabColor;
bool mFlash = false;
+ int mPadding = 8;
};
diff --git a/src/gui/widgets/table.cpp b/src/gui/widgets/table.cpp
index 905bb166..7cddc1fa 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;
@@ -269,13 +265,11 @@ 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)));
+ graphics->setColor(Theme::getThemeColor(Theme::BACKGROUND, guiAlpha));
graphics->fillRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight()));
}
@@ -320,8 +314,7 @@ void GuiTable::draw(gcn::Graphics* graphics)
widget->setDimension(bounds);
- graphics->setColor(Theme::getThemeColor(Theme::HIGHLIGHT,
- (int)(mAlpha * 255.0f)));
+ graphics->setColor(Theme::getThemeColor(Theme::HIGHLIGHT, guiAlpha));
if (mLinewiseMode && r == mSelectedRow && c == 0)
{
@@ -497,14 +490,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 +507,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 +525,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 3fc2745b..81071267 100644
--- a/src/gui/widgets/table.h
+++ b/src/gui/widgets/table.h
@@ -40,10 +40,10 @@ 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;
@@ -102,6 +102,9 @@ public:
// Inherited from Widget
void draw(gcn::Graphics* graphics) override;
+ // Overridden to disable drawing of the frame
+ void drawFrame(gcn::Graphics* graphics) override {}
+
virtual gcn::Widget *getWidgetAt(int x, int y) const;
void moveToTop(gcn::Widget *child) override;
@@ -158,8 +161,6 @@ private:
bool mWrappingEnabled;
bool mOpaque;
- static float mAlpha;
-
/**
* Holds the background color of the table.
*/
diff --git a/src/gui/widgets/textfield.cpp b/src/gui/widgets/textfield.cpp
index 46fa18ae..04955ec8 100644
--- a/src/gui/widgets/textfield.cpp
+++ b/src/gui/widgets/textfield.cpp
@@ -39,21 +39,29 @@ TextField::TextField(const std::string &text, bool loseFocusOnTab)
: gcn::TextField(text)
, mLoseFocusOnTab(loseFocusOnTab)
{
- setFrameSize(2);
+ auto &skin = gui->getTheme()->getSkin(SkinType::TextField);
+ setFrameSize(skin.frameSize);
+ mPadding = skin.padding;
+
+ setWidth(getFont()->getWidth(mText) + 2 * mPadding);
+ setHeight(getFont()->getHeight() + 2 * mPadding);
+ fixScroll();
}
void TextField::draw(gcn::Graphics *graphics)
{
+ if (getFrameSize() == 0)
+ drawFrame(graphics);
+
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);
}
void TextField::drawFrame(gcn::Graphics *graphics)
@@ -99,6 +107,12 @@ int TextField::getValue() const
return value;
}
+void TextField::drawCaret(gcn::Graphics *graphics, int x)
+{
+ graphics->setColor(getForegroundColor());
+ 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 8ea8ec30..b84dd723 100644
--- a/src/gui/widgets/textfield.h
+++ b/src/gui/widgets/textfield.h
@@ -130,35 +130,39 @@ 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();
bool mNumeric = false;
- int mMinimum;
- int mMaximum;
+ int mMinimum = 0;
+ int mMaximum = 0;
bool mLoseFocusOnTab;
+ int mPadding = 1;
AutoCompleteLister *mAutoComplete = nullptr;
diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp
index d47e1a29..fe31c4b0 100644
--- a/src/gui/widgets/window.cpp
+++ b/src/gui/widgets/window.cpp
@@ -56,9 +56,10 @@ Window::Window(const std::string &caption, bool modal, Window *parent)
instances++;
- setFrameSize(0);
- setPadding(3);
- setTitleBarHeight(20);
+ auto &skin = gui->getTheme()->getSkin(SkinType::Window);
+ setFrameSize(skin.frameSize);
+ setPadding(skin.padding);
+ setTitleBarHeight(skin.titleBarHeight);
// Add this window to the window container
windowContainer->add(this);
@@ -98,45 +99,44 @@ void Window::setWindowContainer(WindowContainer *wc)
void Window::draw(gcn::Graphics *graphics)
{
- auto g = static_cast<Graphics*>(graphics);
- auto theme = gui->getTheme();
-
- WidgetState state(this);
- theme->drawSkin(g, SkinType::Window, state);
+ if (getFrameSize() == 0)
+ drawFrame(graphics);
- // Draw title
- if (mShowTitle)
- {
- g->setColor(Theme::getThemeColor(Theme::TEXT));
- g->setFont(getFont());
- g->drawText(getCaption(), 7, 5, gcn::Graphics::LEFT);
- }
-
- const int closeButtonWidth = theme->getMinWidth(SkinType::ButtonClose);
- const int stickyButtonWidth = theme->getMinWidth(SkinType::ButtonSticky);
+ auto g = static_cast<Graphics*>(graphics);
- // Draw Close Button
if (mCloseButton)
{
- state.x = state.width - closeButtonWidth - getPadding();
- state.y = getPadding();
- theme->drawSkin(g, SkinType::ButtonClose, state);
+ WidgetState state(getCloseButtonRect(), mCloseButtonHovered ? STATE_HOVERED : 0);
+ gui->getTheme()->drawSkin(g, SkinType::ButtonClose, state);
}
- // Draw Sticky Button
if (mStickyButton)
{
- state.flags = mSticky ? STATE_SELECTED : 0;
- state.x = state.width - stickyButtonWidth - getPadding();
- state.y = getPadding();
- if (mCloseButton)
- state.x -= closeButtonWidth;
- theme->drawSkin(g, SkinType::ButtonSticky, state);
+ 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);
+ auto theme = gui->getTheme();
+
+ WidgetState state(this);
+ state.width += getFrameSize() * 2;
+ state.height += getFrameSize() * 2;
+ theme->drawSkin(g, SkinType::Window, state);
+
+ if (mShowTitle)
+ {
+ g->setColor(Theme::getThemeColor(Theme::TEXT));
+ g->setFont(getFont());
+ g->drawText(getCaption(), 7 + getFrameSize(), 5 + getFrameSize(), gcn::Graphics::LEFT);
+ }
+}
+
void Window::setContentSize(int width, int height)
{
width = width + 2 * getPadding();
@@ -273,9 +273,7 @@ void Window::widgetResized(const gcn::Event &event)
void Window::widgetHidden(const gcn::Event &event)
{
if (gui)
- {
gui->setCursorType(Cursor::POINTER);
- }
WidgetListIterator it;
@@ -335,45 +333,16 @@ void Window::mousePressed(gcn::MouseEvent &event)
if (event.getButton() == gcn::MouseEvent::LEFT)
{
- auto theme = gui->getTheme();
-
const int x = event.getX();
const int y = event.getY();
- const int closeButtonWidth = theme->getMinWidth(SkinType::ButtonClose);
- const int closeButtonHeight = theme->getMinHeight(SkinType::ButtonClose);
- const int stickyButtonWidth = theme->getMinWidth(SkinType::ButtonSticky);
- const int stickyButtonHeight = theme->getMinHeight(SkinType::ButtonSticky);
+ if (mCloseButton && getCloseButtonRect().isPointInRect(x, y))
+ close();
- // Handle close button
- if (mCloseButton)
- {
- gcn::Rectangle closeButtonRect(getWidth() - closeButtonWidth - getPadding(),
- getPadding(),
- closeButtonWidth,
- closeButtonHeight);
-
- if (closeButtonRect.isPointInRect(x, y))
- close();
- }
-
- // Handle sticky button
- if (mStickyButton)
- {
- int stickyButtonX = getWidth() - stickyButtonWidth - getPadding();
- if (mCloseButton)
- stickyButtonX -= closeButtonWidth;
-
- gcn::Rectangle stickyButtonRect(stickyButtonX,
- getPadding(),
- stickyButtonWidth,
- stickyButtonHeight);
-
- 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;
@@ -396,10 +365,14 @@ void Window::mouseExited(gcn::MouseEvent &event)
{
if (mGrip && !mouseResize)
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();
@@ -409,30 +382,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::RESIZE_DOWN_RIGHT;
break;
case BOTTOM | LEFT:
case TOP | RIGHT:
- gui->setCursorType(Cursor::RESIZE_DOWN_LEFT);
+ cursor = Cursor::RESIZE_DOWN_LEFT;
break;
case BOTTOM:
case TOP:
- gui->setCursorType(Cursor::RESIZE_DOWN);
+ cursor = Cursor::RESIZE_DOWN;
break;
case RIGHT:
case LEFT:
- gui->setCursorType(Cursor::RESIZE_ACROSS);
+ cursor = Cursor::RESIZE_ACROSS;
break;
default:
- gui->setCursorType(Cursor::POINTER);
+ break;
+ }
}
+
+ gui->setCursorType(cursor);
}
void Window::mouseDragged(gcn::MouseEvent &event)
@@ -693,6 +672,45 @@ int Window::getResizeHandles(gcn::MouseEvent &event)
return resizeHandles;
}
+gcn::Rectangle Window::getCloseButtonRect() const
+{
+ auto theme = gui->getTheme();
+
+ auto &closeButtonSkin = theme->getSkin(SkinType::ButtonClose);
+ const int closeButtonWidth = closeButtonSkin.getMinWidth();
+ const int closeButtonHeight = closeButtonSkin.getMinHeight();
+
+ return {
+ getWidth() - closeButtonWidth - closeButtonSkin.padding,
+ closeButtonSkin.padding,
+ closeButtonWidth,
+ closeButtonHeight
+ };
+}
+
+gcn::Rectangle Window::getStickyButtonRect() const
+{
+ auto theme = gui->getTheme();
+
+ auto &closeButtonSkin = theme->getSkin(SkinType::ButtonClose);
+ const int closeButtonWidth = closeButtonSkin.getMinWidth();
+
+ auto &stickyButtonSkin = theme->getSkin(SkinType::ButtonSticky);
+ const int stickyButtonWidth = stickyButtonSkin.getMinWidth();
+ const int stickyButtonHeight = stickyButtonSkin.getMinHeight();
+
+ int stickyButtonX = getWidth() - stickyButtonWidth - stickyButtonSkin.padding;
+ if (mCloseButton)
+ stickyButtonX -= closeButtonWidth + closeButtonSkin.padding;
+
+ return {
+ stickyButtonX,
+ stickyButtonSkin.padding,
+ stickyButtonWidth,
+ stickyButtonHeight
+ };
+}
+
int Window::getGuiAlpha()
{
float alpha = std::max(config.guiAlpha,
diff --git a/src/gui/widgets/window.h b/src/gui/widgets/window.h
index 916d767b..0e84bcb9 100644
--- a/src/gui/widgets/window.h
+++ b/src/gui/widgets/window.h
@@ -68,11 +68,16 @@ 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);
@@ -375,6 +380,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 */
@@ -382,6 +390,7 @@ 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 */