FifeGUI 0.3.0
A C++ GUI library designed for games.
button.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// Corresponding header include
6#include "fifechan/widgets/button.hpp"
7
8// Standard library includes
9#include <string>
10#include <utility>
11
12// Project headers (subdirs before local)
13#include "fifechan/events/mouseevent.hpp"
14#include "fifechan/exception.hpp"
15#include "fifechan/font.hpp"
16#include "fifechan/graphics.hpp"
17#include "fifechan/key.hpp"
18#include "fifechan/mouseinput.hpp"
19
20namespace fcn
21{
22 Button::Button()
23 {
24 setFocusable(true);
26
27 addMouseListener(this);
28 addKeyListener(this);
29 addFocusListener(this);
31 }
32
33 Button::Button(std::string caption) : mCaption(std::move(caption))
34 {
35 setFocusable(true);
37
38 addMouseListener(this);
39 addKeyListener(this);
40 addFocusListener(this);
42 }
43
44 Button::~Button() = default;
45
46 void Button::setCaption(std::string const & caption)
47 {
48 mCaption = caption;
50 }
51
52 std::string const & Button::getCaption() const
53 {
54 return mCaption;
55 }
56
57 void Button::setActive(bool state)
58 {
59 mState = state;
60 }
61
62 bool Button::isActive() const
63 {
64 return mState;
65 }
66
68 {
69 mAlignment = alignment;
70 }
71
76
77 void Button::setDownXOffset(int offset)
78 {
79 mXOffset = offset;
80 }
81
83 {
84 return mXOffset;
85 }
86
87 void Button::setDownYOffset(int offset)
88 {
89 mYOffset = offset;
90 }
91
93 {
94 return mYOffset;
95 }
96
97 void Button::setDownOffset(int x, int y)
98 {
99 mXOffset = x;
100 mYOffset = y;
101 }
102
104 {
106 }
107
108 void Button::draw(Graphics* graphics)
109 {
110 bool const active = isFocused();
111 Color faceColor = getBaseColor();
112 if (active && ((getSelectionMode() & Widget::SelectionMode::Background) == Widget::SelectionMode::Background)) {
113 faceColor = getSelectionColor();
114 }
115
116 int const alpha = faceColor.a;
117
118 if (isPressed()) {
119 faceColor = faceColor - 0x303030;
120 faceColor.a = alpha;
121 }
122 if (!isActive()) {
123 int const color = static_cast<int>((faceColor.r * 0.3) + (faceColor.g * 0.59) + (faceColor.b * 0.11));
124 faceColor.r = color;
125 faceColor.g = color;
126 faceColor.b = color;
127 }
128
129 graphics->setColor(faceColor);
130 Rectangle const offsetRec(getBorderSize(), getBorderSize(), 2 * getBorderSize(), 2 * getBorderSize());
131 graphics->fillRectangle(offsetRec.x, offsetRec.y, getWidth() - offsetRec.width, getHeight() - offsetRec.height);
132
133 if (getBorderSize() > 0) {
134 if (active && (getSelectionMode() & Widget::SelectionMode::Border) == Widget::SelectionMode::Border) {
135 drawSelectionFrame(graphics);
136 } else {
137 drawBorder(graphics);
138 }
139 }
140
141 int textX = 0;
142 int const textY =
143 offsetRec.y + getPaddingTop() +
144 ((getHeight() - offsetRec.height - getPaddingTop() - getPaddingBottom() - getFont()->getHeight()) / 2);
145 switch (getAlignment()) {
146 case Graphics::Alignment::Left:
147 textX = offsetRec.x + getPaddingLeft();
148 break;
149 case Graphics::Alignment::Center:
150 textX = offsetRec.x + getPaddingLeft() +
151 ((getWidth() - offsetRec.width - getPaddingLeft() - getPaddingRight()) / 2);
152 break;
153 case Graphics::Alignment::Right:
154 textX = getWidth() - offsetRec.x - getPaddingRight();
155 break;
156 default:
157 throwException("Unknown alignment.");
158 }
159
160 // set font and color
161 graphics->setFont(getFont());
162 graphics->setColor(getForegroundColor());
163 if (isPressed()) {
164 graphics->drawText(getCaption(), textX + getDownXOffset(), textY + getDownYOffset(), getAlignment());
165 } else {
166 graphics->drawText(getCaption(), textX, textY, getAlignment());
167 }
168 }
169
170 void Button::resizeToContent(bool recursion)
171 {
172 static_cast<void>(recursion);
174 }
175
177 {
179 }
180
182 {
183 int const w = getFont()->getWidth(mCaption) + (2 * getBorderSize()) + getPaddingLeft() + getPaddingRight();
184 int const h = getFont()->getHeight() + (2 * getBorderSize()) + getPaddingTop() + getPaddingBottom();
185 setSize(w, h);
186 }
187
188 bool Button::isPressed() const
189 {
190 if (mMousePressed) {
191 return mHasMouse;
192 }
193 return mKeyPressed;
194 }
195
197 {
198 if (mouseEvent.getButton() == MouseEvent::Button::Left) {
199 if (mHasMouse || isMouseInside(mouseEvent)) {
200 mMousePressed = true;
201 mouseEvent.consume();
202 }
203 }
204 }
205
206 void Button::mouseExited(MouseEvent& /*mouseEvent*/)
207 {
208 mHasMouse = false;
209 }
210
211 void Button::mouseEntered(MouseEvent& /*mouseEvent*/)
212 {
213 mHasMouse = true;
214 }
215
217 {
218 if (mouseEvent.getButton() == MouseEvent::Button::Left && mMousePressed && mHasMouse) {
219 mMousePressed = false;
221 mouseEvent.consume();
222 } else if (mouseEvent.getButton() == MouseEvent::Button::Left) {
223 mMousePressed = false;
224 mouseEvent.consume();
225 }
226 }
227
229 {
230 mouseEvent.consume();
231 }
232
234 {
235 Key const key = keyEvent.getKey();
236
237 if (key.getValue() == fcn::Key::KEY_RETURN || key.getValue() == fcn::Key::SPACE) {
238 mKeyPressed = true;
239 keyEvent.consume();
240 }
241 }
242
244 {
245 Key const key = keyEvent.getKey();
246
247 if ((key.getValue() == fcn::Key::KEY_RETURN || key.getValue() == fcn::Key::SPACE) && mKeyPressed) {
248 mKeyPressed = false;
250 keyEvent.consume();
251 }
252 }
253
254 void Button::focusLost(Event const & /*event*/)
255 {
256 mMousePressed = false;
257 mKeyPressed = false;
258 mHasMouse = false;
259 }
260
261 void Button::ancestorHidden(Event const & /*e*/)
262 {
263 mMousePressed = false;
264 mKeyPressed = false;
265 mHasMouse = false;
266 }
267} // namespace fcn
std::string const & getCaption() const
Gets the caption of the button.
Definition button.cpp:52
void ancestorHidden(Event const &e) override
Invoked when an ancestor of a widget is hidden, i.e its set to be not visible.
Definition button.cpp:261
void setDownOffset(int x, int y)
Sets the number of pixels the image or text will be offset from the top left corner of button when th...
Definition button.cpp:97
bool isActive() const
Returns the button state.
Definition button.cpp:62
void setDownXOffset(int offset)
Sets the number of pixels the image or text will be offset from the top left corner of button when th...
Definition button.cpp:77
Graphics::Alignment getAlignment() const
Gets the alignment of the caption.
Definition button.cpp:72
virtual bool isPressed() const
Checks if the button is pressed.
Definition button.cpp:188
void keyReleased(KeyEvent &keyEvent) override
Called if a key is released when the widget has keyboard focus.
Definition button.cpp:243
bool mHasMouse
True if the mouse is on top of the button, false otherwise.
Definition button.hpp:205
std::string mCaption
Holds the caption of the button.
Definition button.hpp:200
void setDownYOffset(int offset)
Sets the number of pixels the image or text will be offset from the top left corner of button when th...
Definition button.cpp:87
void mouseReleased(MouseEvent &mouseEvent) override
Called when a mouse button has been released on the widget area.
Definition button.cpp:216
virtual void adjustSizeImpl()
Adjusts the size of the button to fit the caption.
Definition button.cpp:181
void mouseEntered(MouseEvent &mouseEvent) override
Called when the mouse has entered into the widget area.
Definition button.cpp:211
bool mKeyPressed
True if a key has been pressed, false otherwise.
Definition button.hpp:210
void mouseDragged(MouseEvent &mouseEvent) override
Called when the mouse has moved and the mouse has previously been pressed on the widget.
Definition button.cpp:228
void adjustSize() override
Resizes the widget's size to fit the content exactly.
Definition button.cpp:176
void draw(Graphics *graphics) override
Draws the widget.
Definition button.cpp:108
void focusLost(Event const &event) override
Called when a widget loses focus.
Definition button.cpp:254
void setAlignment(Graphics::Alignment alignment)
Sets the alignment of the caption.
Definition button.cpp:67
bool mState
True if the button is active.
Definition button.hpp:220
bool mMousePressed
True if a mouse has been pressed, false otherwise.
Definition button.hpp:215
void resizeToContent(bool recursion=true) override
Resizes the widget's size to fit the content exactly, calls recursively all childs.
Definition button.cpp:170
int mYOffset
Holds the y down offset of the caption.
Definition button.hpp:235
void keyPressed(KeyEvent &keyEvent) override
Called if a key is pressed when the widget has keyboard focus.
Definition button.cpp:233
void fontChanged() override
Called when the font has changed.
Definition button.cpp:103
int mXOffset
Holds the x down offset of the caption.
Definition button.hpp:230
Graphics::Alignment mAlignment
Holds the alignment of the caption.
Definition button.hpp:225
int getDownYOffset() const
Gets the number of pixels the image or text will be offset.
Definition button.cpp:92
void mouseExited(MouseEvent &mouseEvent) override
Called when the mouse has exited the widget area.
Definition button.cpp:206
void mousePressed(MouseEvent &mouseEvent) override
Called when a mouse button has been pressed down on the widget area.
Definition button.cpp:196
int getDownXOffset() const
Gets the number of pixels the image or text will be offset.
Definition button.cpp:82
void setCaption(std::string const &caption)
Sets the caption of the button.
Definition button.cpp:46
void setActive(bool state)
Sets the button state.
Definition button.cpp:57
Color.
Definition color.hpp:58
uint8_t a
Alpha color component (0-255).
Definition color.hpp:350
uint8_t b
Blue color component (0-255).
Definition color.hpp:347
uint8_t g
Green color component (0-255).
Definition color.hpp:344
uint8_t r
Red color component (0-255).
Definition color.hpp:341
Base class for all GUI event objects.
Definition event.hpp:25
virtual int getWidth(std::string const &text) const =0
Gets the width of a string.
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:58
Alignment
Horizontal alignments for text drawing.
Definition graphics.hpp:64
void drawText(std::string const &text, int x, int y)
Draws text with a default left alignment.
Definition graphics.hpp:401
virtual void setFont(Font *font)
Sets the font to use when drawing text.
Definition graphics.cpp:91
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 consume()
Marks this event as consumed.
Represents a key event.
Definition keyevent.hpp:26
Key const & getKey() const
Gets the key of the event.
Definition keyevent.cpp:48
Represents a mouse event.
MouseEvent::Button getButton() const
Gets the button of the mouse event.
Represents a rectangular area (X, Y, Width, Height).
Definition rectangle.hpp:22
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.
void addFocusListener(FocusListener *focusListener)
Adds a focus listener to the widget.
Definition widget.cpp:896
Color const & getBaseColor() const
Gets the base color.
Definition widget.cpp:742
void setFocusable(bool focusable)
Sets the widget to be focusable, or not.
Definition widget.cpp:646
bool isMouseInside(MouseEvent const &mouseEvent) const
Checks if a mouse event occurred within this widget.
Definition widget.cpp:275
int getWidth() const
Gets the width of the widget.
Definition widget.cpp:252
virtual bool isFocused() const
Checks if the widget is focused.
Definition widget.cpp:624
unsigned int getPaddingLeft() const
Gets the left padding.
Definition widget.cpp:604
virtual void setSize(int width, int height)
Sets the size of the widget.
Definition widget.cpp:1065
void addMouseListener(MouseListener *mouseListener)
Adds a mouse listener to the widget.
Definition widget.cpp:907
void addWidgetListener(WidgetListener *widgetListener)
Adds a widget listener to the widget.
Definition widget.cpp:918
void addKeyListener(KeyListener *keyListener)
Adds a key listener to the widget.
Definition widget.cpp:885
virtual void drawBorder(Graphics *graphics)
Called when a widget have a border.
Definition widget.cpp:156
unsigned int getPaddingTop() const
Gets the top padding.
Definition widget.cpp:574
unsigned int getBorderSize() const
Gets the size of the widget's border.
Definition widget.cpp:474
virtual void drawSelectionFrame(Graphics *graphics)
Called when a widget is "active" and the selection mode is Frame or FrameWithBackground.
Definition widget.cpp:217
unsigned int getPaddingBottom() const
Gets the bottom padding.
Definition widget.cpp:594
Color const & getForegroundColor() const
Gets the foreground color.
Definition widget.cpp:752
SelectionMode getSelectionMode() const
Gets the selection mode.
Definition widget.cpp:802
Font * getFont() const
Gets the font set for the widget.
Definition widget.cpp:1000
void distributeActionEvent()
Distributes an action event to all action listeners of the widget.
Definition widget.cpp:1291
int getHeight() const
Gets the height of the widget.
Definition widget.cpp:265
unsigned int getPaddingRight() const
Gets the right padding.
Definition widget.cpp:584
Color const & getSelectionColor() const
Gets the selection color.
Definition widget.cpp:772
Used replacement tokens by configure_file():
void throwException(std::string const &message, std::source_location location=std::source_location::current())
Throw an Exception capturing the current source location.