KTech 1.1.0
C++ 2D terminal game engine library
Loading...
Searching...
No Matches
button.hpp
1/*
2 KTech, Kaup's C++ 2D terminal game engine library.
3 Copyright (C) 2023-2025 Ethan Kaufman (AKA Kaup)
4
5 This file is part of KTech.
6
7 KTech is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 any later version.
11
12 KTech is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with KTech. If not, see <https://www.gnu.org/licenses/>.
19*/
20
21#pragma once
22
23#include "../ktech.hpp"
24
28class Button : public KTech::Widget
29{
30public:
31 std::function<void()> m_OnPress;
32
49 std::function<void()> OnPress,
50 const std::string& key = KTech::Keys::return_,
51 KTech::Point position = KTech::Point(0, 0),
52 const std::string& text = "Button",
53 bool withFrame = false,
54 KTech::RGBA unselected = KTech::RGBAColors::gray,
55 KTech::RGBA selected = KTech::RGBAColors::white,
56 KTech::RGBA down = KTech::RGBAColors::Widgets::buttonDownBlue)
57 : Widget(engine, ui, position),
58 m_OnPress(std::move(OnPress)),
59 m_unselectedRGBA(unselected),
60 m_selectedRGBA(selected),
61 m_downRGBA(down),
62 m_downInvocation(engine, [this]() -> bool { return RemovePressColor(); })
63 {
64 // Texture
65 SetText(text, withFrame);
66 // Input handlers
67 m_callbackGroup.RegisterCallback(key, [this]() -> bool { return InsideOnPress(); });
68 }
69
76 void SetText(const std::string& text, bool withFrame)
77 {
78 KTech::RGBA tempColor;
79 if (m_downInvocation.m_active) // The button is down as it is invoked to remove down color
80 {
81 tempColor = m_downRGBA;
82 }
83 else if (m_selected)
84 {
85 tempColor = m_selectedRGBA;
86 }
87 else
88 {
89 tempColor = m_unselectedRGBA;
90 }
91
92 if (withFrame)
93 {
94 m_textures.resize(TEXTURES_SIZE_FRAMED);
95 m_textures[ti_topLeftCorner].Simple(KTech::UPoint(1, 1), KTech::CellA('#', tempColor), KTech::Point(0, 0));
96 m_textures[ti_topRightCorner].Simple(KTech::UPoint(1, 1), KTech::CellA('#', tempColor), KTech::Point(1 + text.length(), 0));
97 m_textures[ti_bottomLeftCorner].Simple(KTech::UPoint(1, 1), KTech::CellA('#', tempColor), KTech::Point(0, 2));
98 m_textures[ti_bottomRightCorner].Simple(KTech::UPoint(1, 1), KTech::CellA('#', tempColor), KTech::Point(1 + text.length(), 2));
99 m_textures[ti_topFrame].Simple(KTech::UPoint(text.length(), 1), KTech::CellA('-', tempColor), KTech::Point(1, 0));
100 m_textures[ti_leftFrame].Simple(KTech::UPoint(1, 1), KTech::CellA('|', tempColor), KTech::Point(0, 1));
101 m_textures[ti_bottomFrame].Simple(KTech::UPoint(text.length(), 1), KTech::CellA('-', tempColor), KTech::Point(1, 2));
102 m_textures[ti_rightFrame].Simple(KTech::UPoint(1, 1), KTech::CellA('|', tempColor), KTech::Point(1 + text.length(), 1));
103 }
104 else
105 {
106 m_textures.resize(TEXTURES_SIZE_FRAMELESS);
107 }
108 // text
109 m_textures[ti_text].Write({text}, tempColor, KTech::RGBAColors::transparent, KTech::Point(1, 1));
110 }
111
112private:
113 enum TextureIndex : size_t
114 {
115 ti_text,
116 TEXTURES_SIZE_FRAMELESS,
117 ti_topLeftCorner = TEXTURES_SIZE_FRAMELESS,
118 ti_topRightCorner,
119 ti_bottomLeftCorner,
120 ti_bottomRightCorner,
121 ti_topFrame,
122 ti_leftFrame,
123 ti_bottomFrame,
124 ti_rightFrame,
125 TEXTURES_SIZE_FRAMED
126 };
127
128 KTech::RGBA m_unselectedRGBA, m_selectedRGBA, m_downRGBA;
129 static constexpr size_t pressLength = 100;
130 KTech::Time::Invocation m_downInvocation;
131
132 void OnSelect() override
133 {
134 RenderSelected();
135 }
136
137 void OnDeselect() override
138 {
139 RenderUnselected();
140 }
141
142 void RenderSelected()
143 {
144 for (KTech::Texture& texture : m_textures)
145 {
146 texture.Transform([&](KTech::CellA& cell){ cell.f = m_selectedRGBA; });
147 }
148 }
149
150 void RenderUnselected()
151 {
152 for (KTech::Texture& texture : m_textures)
153 {
154 texture.Transform([&](KTech::CellA& cell){ cell.f = m_unselectedRGBA; });
155 }
156 }
157
158 auto RemovePressColor() -> bool
159 {
160 if (m_selected)
161 {
162 for (KTech::Texture& texture : m_textures)
163 {
164 texture.Transform([&](KTech::CellA& cell){ cell.f = m_selectedRGBA; });
165 }
166 }
167 else
168 {
169 for (KTech::Texture& texture : m_textures)
170 {
171 texture.Transform([&](KTech::CellA& cell){ cell.f = m_unselectedRGBA; });
172 }
173 }
174 return true;
175 }
176
177 auto InsideOnPress() -> bool
178 {
179 for (KTech::Texture& texture : m_textures)
180 {
181 texture.Transform([&](KTech::CellA& cell){ cell.f = m_downRGBA; });
182 }
183 m_downInvocation.Invoke(pressLength, KTech::Time::Measurement::milliseconds);
184 if (m_OnPress)
185 {
186 m_OnPress();
187 }
188 return true;
189 }
190};
Widget that calls a callback function when pressed.
Definition button.hpp:29
void SetText(const std::string &text, bool withFrame)
Change the displayed text.
Definition button.hpp:76
std::function< void()> m_OnPress
Function to call when pressed.
Definition button.hpp:31
Button(KTech::Engine &engine, KTech::ID< KTech::UI > ui, std::function< void()> OnPress, const std::string &key=KTech::Keys::return_, KTech::Point position=KTech::Point(0, 0), const std::string &text="Button", bool withFrame=false, KTech::RGBA unselected=KTech::RGBAColors::gray, KTech::RGBA selected=KTech::RGBAColors::white, KTech::RGBA down=KTech::RGBAColors::Widgets::buttonDownBlue)
Construct a Button.
Definition button.hpp:47
Complete engine containing all engine components.
Definition engine.hpp:41
World structure that comprises Textures, behaves as a user interface element, and exists within UI.
Definition widget.hpp:45
Engine & engine
Parent Engine.
Definition widget.hpp:57
Widget(Engine &engine, Point position=Point(0, 0), std::string name="")
Construct a Widget.
Definition widget.cpp:34
Like Cell, but with RGBA foreground and background colors, instead of RGB.
Definition cella.hpp:32
RGBA f
Foreground (character) color.
Definition cella.hpp:33
Serializable world structure identifier.
Definition id.hpp:38
2D vector, mostly used to store positions and directions.
Definition point.hpp:30
Like RGB, but also has an alpha channel representing transparency.
Definition rgba.hpp:30
A CellA-based sprite.
Definition texture.hpp:48
Calls a function after a given time.
Definition invocation.hpp:68
void Invoke(long time, Measurement measurement)
Invoke your callback function.
Definition invocation.cpp:82
Unsigned 2D vector, mostly used to store sizes and 2D indexes.
Definition upoint.hpp:29