FifeGUI 0.2.0
A C++ GUI library designed for games.
imagebutton.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later OR BSD-3-Clause
2// SPDX-FileCopyrightText: 2004 - 2008 Olof Naessén and Per Larsson
3// SPDX-FileCopyrightText: 2013 - 2026 Fifengine contributors
4
5#include "fifechan/widgets/imagebutton.hpp"
6
7#include <algorithm>
8#include <string>
9#include <vector>
10
11#include "fifechan/exception.hpp"
12#include "fifechan/font.hpp"
13#include "fifechan/graphics.hpp"
14#include "fifechan/image.hpp"
15
16namespace fcn
17{
18 ImageButton::ImageButton() : mImages(6, static_cast<Image const *>(nullptr)), mOwnedImages(6)
19 {
20 adjustSizeImpl();
21 }
22
23 ImageButton::ImageButton(std::string const & filename) :
24 mImages(6, static_cast<Image const *>(nullptr)), mOwnedImages(6)
25 {
26 setUpImage(filename);
27 }
28
29 ImageButton::ImageButton(Image const * image) : mImages(6, static_cast<Image const *>(nullptr)), mOwnedImages(6)
30 {
31 setUpImage(image);
32 }
33
34 ImageButton::~ImageButton() = default;
35
36 void ImageButton::setImage(std::string const & filename, ImageType type)
37 {
38 mOwnedImages[static_cast<size_t>(type)].reset(Image::load(filename));
39 mImages[static_cast<size_t>(type)] = mOwnedImages[static_cast<size_t>(type)].get();
41 }
42
43 void ImageButton::setImage(Image const * image, ImageType type)
44 {
45 mOwnedImages[static_cast<size_t>(type)].reset();
46 mImages[static_cast<size_t>(type)] = image;
48 }
49
50 void ImageButton::setUpImage(std::string const & filename)
51 {
52 setImage(filename, ImageType::Up);
53 }
54
55 void ImageButton::setUpImage(Image const * image)
56 {
57 setImage(image, ImageType::Up);
58 }
59
61 {
62 return mImages[static_cast<size_t>(ImageType::Up)];
63 }
64
65 void ImageButton::setDownImage(std::string const & filename)
66 {
67 setImage(filename, ImageType::Down);
68 }
69
70 void ImageButton::setDownImage(Image const * image)
71 {
72 setImage(image, ImageType::Down);
73 }
74
76 {
77 return mImages[static_cast<size_t>(ImageType::Down)];
78 }
79
80 void ImageButton::setHoverImage(std::string const & filename)
81 {
82 setImage(filename, ImageType::Hover);
83 }
84
86 {
87 setImage(image, ImageType::Hover);
88 }
89
91 {
92 return mImages[static_cast<size_t>(ImageType::Hover)];
93 }
94
95 void ImageButton::setInactiveUpImage(std::string const & filename)
96 {
97 setImage(filename, ImageType::Up_Inactive);
98 }
99
101 {
102 setImage(image, ImageType::Up_Inactive);
103 }
104
106 {
107 return mImages[static_cast<size_t>(ImageType::Up_Inactive)];
108 }
109
110 void ImageButton::setInactiveDownImage(std::string const & filename)
111 {
112 setImage(filename, ImageType::Down_Inactive);
113 }
114
116 {
117 setImage(image, ImageType::Down_Inactive);
118 }
119
121 {
122 return mImages[static_cast<size_t>(ImageType::Down_Inactive)];
123 }
124
125 void ImageButton::setInactiveHoverImage(std::string const & filename)
126 {
127 setImage(filename, ImageType::Hover_Inactive);
128 }
129
131 {
132 setImage(image, ImageType::Hover_Inactive);
133 }
134
136 {
137 return mImages[static_cast<size_t>(ImageType::Hover_Inactive)];
138 }
139
140 void ImageButton::resizeToContent([[maybe_unused]] bool recursion)
141 {
143 }
144
146 {
148 }
149
151 {
152 int w = 0;
153 int h = 0;
154 for (unsigned int i = 0; i < 6; ++i) {
155 Image const * img = mImages[i];
156 if (img != nullptr) {
157 w = std::max(w, img->getWidth());
158 h = std::max(h, img->getHeight());
159 }
160 }
161 if (!getCaption().empty()) {
162 w = std::max(getFont()->getWidth(getCaption()), w);
163 h = std::max(getFont()->getHeight(), h);
164 }
167 setSize(w, h);
168 }
169
171 {
172 // draw border or frame
173 if (getBorderSize() > 0) {
174 if (isFocused() && (getSelectionMode() & Widget::SelectionMode::Border) == Widget::SelectionMode::Border) {
175 drawSelectionFrame(graphics);
176 } else {
177 drawBorder(graphics);
178 }
179 }
180
182 // fetch the image, down, hover or up
183 Image const * img = !isActive() && (getInactiveUpImage() != nullptr) ? getInactiveUpImage() : getUpImage();
184 if (isPressed()) {
185 offsetRec.x += getDownXOffset();
186 offsetRec.y += getDownYOffset();
187 if (!isActive()) {
188 if (getInactiveDownImage() != nullptr) {
189 img = getInactiveDownImage();
190 }
191 } else {
192 img = (getDownImage() != nullptr) ? getDownImage() : getUpImage();
193 }
194 } else if (mHasMouse) {
195 if (!isActive()) {
196 if (getInactiveHoverImage() != nullptr) {
197 img = getInactiveHoverImage();
198 }
199 } else {
200 img = (getHoverImage() != nullptr) ? getHoverImage() : getUpImage();
201 }
202 }
203 // render foreground image or color rectangle
204 if (img != nullptr) {
205 graphics->drawImage(
206 img, 0, 0, offsetRec.x, offsetRec.y, getWidth() - offsetRec.width, getHeight() - offsetRec.height);
207 } else {
208 Color faceColor = getBaseColor();
209 if (isFocused() &&
210 ((getSelectionMode() & Widget::SelectionMode::Background) == Widget::SelectionMode::Background)) {
211 faceColor = getSelectionColor();
212 }
213 int const alpha = faceColor.a;
214
215 if (isPressed()) {
216 faceColor = faceColor - 0x303030;
217 faceColor.a = alpha;
218 }
219 if (!isActive()) {
220 int const color = static_cast<int>((faceColor.r * 0.3) + (faceColor.g * 0.59) + (faceColor.b * 0.11));
221 faceColor.r = color;
222 faceColor.g = color;
223 faceColor.b = color;
224 }
225
226 graphics->setColor(faceColor);
227 graphics->fillRectangle(
228 offsetRec.x, offsetRec.y, getWidth() - offsetRec.width, getHeight() - offsetRec.height);
229 }
230
231 // render caption if it exits
232 if (!getCaption().empty()) {
233 int textX = 0;
234 int const textY =
235 offsetRec.y + getPaddingTop() +
236 ((getHeight() - offsetRec.height - getPaddingTop() - getPaddingBottom() - getFont()->getHeight()) / 2);
237 switch (getAlignment()) {
238 case Graphics::Alignment::Left:
239 textX = offsetRec.x + getPaddingLeft();
240 break;
241 case Graphics::Alignment::Center:
242 textX = offsetRec.x + getPaddingLeft() +
243 (getWidth() - offsetRec.width - getPaddingLeft() - getPaddingRight()) / 2;
244 break;
245 case Graphics::Alignment::Right:
246 textX = getWidth() - offsetRec.x - getPaddingRight();
247 break;
248 default:
249 throwException("Unknown alignment.");
250 }
251 // set font and color
252 graphics->setFont(getFont());
253 graphics->setColor(getForegroundColor());
254 graphics->drawText(getCaption(), textX, textY, getAlignment());
255 }
256 }
257} // namespace fcn
std::string const & getCaption() const
Gets the caption of the button.
Definition button.cpp:49
bool isActive() const
Returns the button state.
Definition button.cpp:59
Graphics::Alignment getAlignment() const
Gets the alignment of the caption.
Definition button.cpp:69
virtual bool isPressed() const
Checks if the button is pressed.
Definition button.cpp:185
bool mHasMouse
True if the mouse is on top of the button, false otherwise.
Definition button.hpp:201
int getDownYOffset() const
Gets the number of pixels the image or text will be offset.
Definition button.cpp:89
int getDownXOffset() const
Gets the number of pixels the image or text will be offset.
Definition button.cpp:79
Color.
Definition color.hpp:56
uint8_t a
Alpha color component (0-255).
Definition color.hpp:322
uint8_t b
Blue color component (0-255).
Definition color.hpp:319
uint8_t g
Green color component (0-255).
Definition color.hpp:316
uint8_t r
Red color component (0-255).
Definition color.hpp:313
virtual int getHeight() const =0
Gets the height of the glyphs in the font.
Abstract interface providing primitive drawing functions (lines, rectangles, etc.).
Definition graphics.hpp:57
virtual void drawImage(Image const *image, int srcX, int srcY, int dstX, int dstY, int width, int height)=0
Draws a part of an image.
void drawText(std::string const &text, int x, int y)
Draws text with a default left alignment.
Definition graphics.hpp:362
virtual void setFont(Font *font)
Sets the font to use when drawing text.
Definition graphics.cpp:79
virtual void setColor(Color const &color)=0
Sets the color to use when drawing.
virtual void fillRectangle(Rectangle const &rectangle)=0
Draws a filled rectangle.
void setImage(std::string const &filename, ImageType type)
Internal helper to set an image for a specific ImageType by filename.
Image const * getInactiveDownImage() const
Gets inactive down image.
void adjustSize() override
Adjust internal size after layout or image changes.
Image const * getUpImage() const
Gets current up image.
void setInactiveUpImage(std::string const &filename)
Sets the up image to display if the button is inactive.
void setDownImage(std::string const &filename)
Sets the down image to display.
Image const * getDownImage() const
Gets current down image.
std::vector< Image const * > mImages
The images to display.
void setInactiveHoverImage(std::string const &filename)
Sets the hover image to display if the button is inactive.
Image const * getInactiveUpImage() const
Gets inactive up image.
void adjustSizeImpl() override
Adjusts the size of the button to fit the caption.
void setHoverImage(std::string const &filename)
Sets the hover image to display.
std::vector< std::unique_ptr< Image const > > mOwnedImages
Owned images loaded by filename.
ImageType
Types of images used by ImageButton.
void setUpImage(std::string const &filename)
Sets the up image to display.
void setInactiveDownImage(std::string const &filename)
Sets the down image to display if the button is inactive.
Image const * getHoverImage() const
Gets current hover image.
void draw(fcn::Graphics *graphics) override
Draw the button using the provided graphics backend.
Image const * getInactiveHoverImage() const
Gets inactive hover image.
Abstract holder for image data.
Definition image.hpp:32
virtual int getHeight() const =0
Gets the height of the image.
static Image * load(std::string const &filename, bool convertToDisplayFormat=true)
Loads an image by using the class' image loader.
Definition image.cpp:31
virtual int getWidth() const =0
Gets the width of the image.
Represents a rectangular area (X, Y, Width, Height).
Definition rectangle.hpp:20
int width
Holds the width of the rectangle.
int y
Holds the x coordinate of the rectangle.
int x
Holds the x coordinate of the rectangle.
int height
Holds the height of the rectangle.
Color const & getBaseColor() const
Gets the base color.
Definition widget.cpp:596
int getWidth() const
Gets the width of the widget.
Definition widget.cpp:170
virtual bool isFocused() const
Checks if the widget is focused.
Definition widget.cpp:497
unsigned int getPaddingLeft() const
Gets the left padding.
Definition widget.cpp:477
void setSize(int width, int height)
Sets the size of the widget.
Definition widget.cpp:855
void resizeToContent()
Resizes the widget's size to fit the content exactly, calls recursively all childs.
Definition widget.hpp:1417
virtual void drawBorder(Graphics *graphics)
Called when a widget have a border.
Definition widget.cpp:111
unsigned int getPaddingTop() const
Gets the top padding.
Definition widget.cpp:447
unsigned int getBorderSize() const
Gets the size of the widget's border.
Definition widget.cpp:381
virtual void drawSelectionFrame(Graphics *graphics)
Called when a widget is "active" and the selection mode is Frame or FrameWithBackground.
Definition widget.cpp:135
unsigned int getPaddingBottom() const
Gets the bottom padding.
Definition widget.cpp:467
Color const & getForegroundColor() const
Gets the foreground color.
Definition widget.cpp:606
SelectionMode getSelectionMode() const
Gets the selection mode.
Definition widget.cpp:656
Font * getFont() const
Gets the font set for the widget.
Definition widget.cpp:796
int getHeight() const
Gets the height of the widget.
Definition widget.cpp:183
unsigned int getPaddingRight() const
Gets the right padding.
Definition widget.cpp:457
Color const & getSelectionColor() const
Gets the selection color.
Definition widget.cpp:626