25#ifndef TGUI_COMPONENTS_HPP
26#define TGUI_COMPONENTS_HPP
28#include <TGUI/Outline.hpp>
29#include <TGUI/Sprite.hpp>
30#include <TGUI/Text.hpp>
31#include <TGUI/Texture.hpp>
35#include <unordered_map>
46 enum class ComponentState : std::uint8_t
55 FocusedActiveHover = 7,
63 enum class AlignLayout : std::uint8_t
78 enum class PositionAlignment : std::uint8_t
94 class TGUI_API MessageBroker
97 [[nodiscard]]
static std::uint64_t createTopic();
99 static void destroyTopic(std::uint64_t topicId);
101 [[nodiscard]]
static std::uint64_t subscribe(std::uint64_t topicId, std::function<
void()> func);
103 static void unsubscribe(std::uint64_t callbackId);
105 static void sendEvent(std::uint64_t topicId);
108 static std::unordered_map<std::uint64_t, std::set<std::uint64_t>> m_topicIdToCallbackIds;
109 static std::unordered_map<std::uint64_t, std::uint64_t> m_callbackIdToTopicId;
110 static std::unordered_map<std::uint64_t, std::function<void()>> m_listeners;
113 static std::uint64_t m_lastId;
118 class TGUI_API StylePropertyBase
121 virtual ~StylePropertyBase() =
default;
126 template <
typename ValueType>
127 class TGUI_API StyleProperty :
public StylePropertyBase
132 m_messageTopicId{MessageBroker::createTopic()}
136 explicit StyleProperty(ValueType defaultValue) :
137 m_defaultValue{std::move(defaultValue)},
138 m_messageTopicId{MessageBroker::createTopic()}
142 StyleProperty(
const StyleProperty& other) :
143 m_defaultValue{other.m_defaultValue},
144 m_messageTopicId{MessageBroker::createTopic()},
145 m_globalValues{other.m_globalValues}
149 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
150 const std::uint64_t oldBaseIndex = other.m_propertyData & 0xFFFFFFFFFFFF0000;
151 const auto oldStoredStates =
static_cast<std::uint16_t
>(other.m_propertyData & 0xFFFF);
153 std::uint16_t total = 0;
154 std::uint8_t bitIndex = 0;
155 while (total < oldStoredStates)
157 if (oldStoredStates & (1 << bitIndex))
159 m_globalValues[baseIndex + bitIndex] = m_globalValues[oldBaseIndex + bitIndex];
160 total +=
static_cast<std::uint16_t
>(1 << bitIndex);
165 m_propertyData = baseIndex | oldStoredStates;
168 StyleProperty(StyleProperty&& other) noexcept :
169 m_defaultValue{std::move(other.m_defaultValue)},
170 m_propertyData{std::move(other.m_propertyData)},
171 m_messageTopicId{std::move(other.m_messageTopicId)},
172 m_globalValues{std::move(other.m_globalValues)}
174 other.m_messageTopicId = 0;
177 ~StyleProperty()
override
179 if (m_messageTopicId)
180 MessageBroker::destroyTopic(m_messageTopicId);
184 StyleProperty& operator=(
const StyleProperty& other)
188 StyleProperty temp(other);
189 std::swap(m_defaultValue, temp.m_defaultValue);
190 std::swap(m_propertyData, temp.m_propertyData);
191 std::swap(m_messageTopicId, temp.m_messageTopicId);
192 std::swap(m_globalValues, temp.m_globalValues);
198 StyleProperty& operator=(StyleProperty&& other)
noexcept
202 m_defaultValue = std::move(other.m_defaultValue);
203 m_propertyData = std::move(other.m_propertyData);
204 m_messageTopicId = std::move(other.m_messageTopicId);
205 m_globalValues = std::move(other.m_globalValues);
207 other.m_messageTopicId = 0;
213 StyleProperty& operator=(
const ValueType& value)
216 setValue(value, ComponentState::Normal);
220 void setValue(
const ValueType& value, ComponentState state = ComponentState::Normal)
222 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
223 m_propertyData |=
static_cast<std::uint64_t
>(1) <<
static_cast<std::uint8_t
>(state);
224 m_globalValues[baseIndex +
static_cast<std::uint8_t
>(state)] = value;
226 MessageBroker::sendEvent(m_messageTopicId);
229 void unsetValue(ComponentState state)
231 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
232 m_propertyData &= ~(
static_cast<std::uint64_t
>(1) <<
static_cast<std::uint8_t
>(state));
233 m_globalValues.erase(baseIndex +
static_cast<std::uint8_t
>(state));
235 MessageBroker::sendEvent(m_messageTopicId);
241 MessageBroker::sendEvent(m_messageTopicId);
244 [[nodiscard]]
const ValueType& getValue(ComponentState state = ComponentState::Normal)
const
246 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
247 const auto storedStates =
static_cast<std::uint16_t
>(m_propertyData & 0xFFFF);
250 if (storedStates == 0)
251 return m_defaultValue;
254 if (storedStates == 1)
255 return m_globalValues.at(baseIndex);
257 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Disabled))
259 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Active))
260 && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::DisabledActive))))
261 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::DisabledActive));
262 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Disabled)))
263 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Disabled));
266 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Active))
268 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Hover))
270 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused))
271 && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::FocusedActiveHover))))
272 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::FocusedActiveHover));
273 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::ActiveHover)))
274 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::ActiveHover));
277 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused))
278 && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::FocusedActive))))
279 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::FocusedActive));
280 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Active)))
281 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Active));
284 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Hover))
286 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused))
287 && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::FocusedHover))))
288 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::FocusedHover));
289 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Hover)))
290 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Hover));
293 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused))
295 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Focused)))
296 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Focused));
299 if (storedStates & 1)
303 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Normal));
309 return m_defaultValue;
312 [[nodiscard]] std::uint64_t connectCallback(std::function<
void()> func)
314 return MessageBroker::subscribe(m_messageTopicId, std::move(func));
317 void disconnectCallback(std::uint64_t
id)
319 MessageBroker::unsubscribe(
id);
323 void unsetValueImpl()
325 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
326 const auto storedStates =
static_cast<std::uint16_t
>(m_propertyData & 0xFFFF);
328 std::uint16_t total = 0;
329 std::uint8_t bitIndex = 0;
330 while (total < storedStates)
332 if (storedStates & (1 << bitIndex))
334 m_globalValues.erase(baseIndex + bitIndex);
335 total +=
static_cast<std::uint16_t
>(1 << bitIndex);
340 m_propertyData = baseIndex;
344 ValueType m_defaultValue;
348 std::uint64_t m_propertyData = 0;
351 std::uint64_t m_messageTopicId = 0;
361 std::unordered_map<std::uint64_t, ValueType> m_globalValues;
366 struct TGUI_API StylePropertyBackground
368 StyleProperty<Color> borderColor{Color::Black};
369 StyleProperty<Color> color{Color::White};
370 StyleProperty<Texture> texture;
371 StyleProperty<Outline> borders;
372 StyleProperty<Outline> padding;
374 float roundedBorderRadius = 0;
379 struct TGUI_API StylePropertyText
381 StyleProperty<Color> color{Color::Black};
382 StyleProperty<TextStyles> style;
387 class GroupComponent;
389 class TGUI_API Component
392 Component() =
default;
393 virtual ~Component() =
default;
395 Component(
const Component& other);
396 Component& operator=(
const Component& other);
398 Component(Component&&) =
default;
399 Component& operator=(Component&&) =
default;
401 void setPosition(Vector2f position);
403 [[nodiscard]] Vector2f getPosition()
const;
405 [[nodiscard]] Vector2f getSize()
const;
407 void setPositionAlignment(PositionAlignment alignment);
409 void setVisible(
bool visible);
411 [[nodiscard]]
bool isVisible()
const;
413 void setParent(GroupComponent* parent);
415 virtual void draw(BackendRenderTarget& target, RenderStates states)
const = 0;
417 virtual void updateLayout();
419 [[nodiscard]]
virtual std::shared_ptr<Component> clone()
const = 0;
422 friend void swap(Component& first, Component& second)
noexcept;
425 ComponentState m_state = ComponentState::Normal;
426 PositionAlignment m_positionAlignment = PositionAlignment::None;
429 bool m_visible =
true;
431 GroupComponent* m_parent =
nullptr;
434 class TGUI_API GroupComponent :
public Component
437 GroupComponent(
const GroupComponent& other);
438 GroupComponent& operator=(
const GroupComponent& other);
440 GroupComponent(GroupComponent&&) =
default;
441 GroupComponent& operator=(GroupComponent&&) =
default;
443 [[nodiscard]] Vector2f getClientSize()
const;
445 void addComponent(
const std::shared_ptr<Component>& component);
447 [[nodiscard]]
const std::vector<std::shared_ptr<Component>>& getComponents()
const;
449 void draw(BackendRenderTarget& target, RenderStates states)
const override;
451 void updateLayout()
override;
453 [[nodiscard]] std::shared_ptr<Component> clone()
const override;
455 friend void swap(GroupComponent& first, GroupComponent& second)
noexcept;
458 GroupComponent() =
default;
461 std::vector<std::shared_ptr<Component>> m_children;
462 Vector2f m_clientSize;
467 class TGUI_API BackgroundComponent :
public GroupComponent
470 explicit BackgroundComponent(StylePropertyBackground* backgroundStyle);
472 ~BackgroundComponent()
override;
474 BackgroundComponent(
const BackgroundComponent& other, StylePropertyBackground* backgroundStyle =
nullptr);
475 BackgroundComponent& operator=(
const BackgroundComponent& other);
479 void setSize(Vector2f size);
481 void setBorders(
const Outline& border);
483 [[nodiscard]]
const Outline& getBorders()
const;
485 void setPadding(
const Outline& padding);
487 [[nodiscard]]
const Outline& getPadding()
const;
489 void setOpacity(
float opacity);
491 void setComponentState(ComponentState state);
493 [[nodiscard]]
bool isTransparentPixel(Vector2f pos,
bool transparentTexture)
const;
495 void draw(BackendRenderTarget& target, RenderStates states)
const override;
497 [[nodiscard]] Vector2f getSizeWithoutBorders()
const;
499 void updateLayout()
override;
501 [[nodiscard]] std::shared_ptr<Component> clone()
const override;
510 StylePropertyBackground* m_backgroundStyle;
512 ColorRect m_background{Color::White, {}};
513 Color m_borderColor = Color::Black;
518 std::uint64_t m_borderColorCallbackId = 0;
519 std::uint64_t m_backgroundColorCallbackId = 0;
520 std::uint64_t m_textureCallbackId = 0;
521 std::uint64_t m_bordersCallbackId = 0;
522 std::uint64_t m_paddingCallbackId = 0;
527 class TGUI_API TextComponent :
public Component
530 explicit TextComponent(StylePropertyText* textStyle);
532 ~TextComponent()
override;
534 TextComponent(
const TextComponent& other, StylePropertyText* textStyle =
nullptr);
535 TextComponent& operator=(
const TextComponent& other);
539 void setString(
const String& caption);
541 [[nodiscard]]
const String& getString()
const;
543 void setCharacterSize(
unsigned int size);
545 [[nodiscard]]
unsigned int getCharacterSize()
const;
547 void setFont(
const Font& font);
549 [[nodiscard]] Font getFont()
const;
551 void setOutlineColor(Color color);
553 [[nodiscard]] Color getOutlineColor()
const;
555 void setOutlineThickness(
float thickness);
557 [[nodiscard]]
float getOutlineThickness()
const;
559 [[nodiscard]]
float getLineHeight()
const;
561 void setOpacity(
float opacity);
563 void updateLayout()
override;
565 void setComponentState(ComponentState state);
567 void draw(BackendRenderTarget& target, RenderStates states)
const override;
569 [[nodiscard]] std::shared_ptr<Component> clone()
const override;
573 StylePropertyText* m_textStyle;
575 Color m_color = Color::Black;
576 TextStyles m_style = TextStyle::Regular;
578 std::uint64_t m_colorCallbackId = 0;
579 std::uint64_t m_styleCallbackId = 0;
584 class TGUI_API ImageComponent :
public Component
587 explicit ImageComponent(StyleProperty<Texture>* textureStyle);
589 ~ImageComponent()
override;
591 ImageComponent(
const ImageComponent& other, StyleProperty<Texture>* textureStyle =
nullptr);
592 ImageComponent& operator=(
const ImageComponent& other);
596 void setSize(Vector2f size);
598 void setOpacity(
float opacity);
600 void setComponentState(ComponentState state);
602 [[nodiscard]]
bool isTransparentPixel(Vector2f pos,
bool transparentTexture)
const;
604 void draw(BackendRenderTarget& target, RenderStates states)
const override;
606 [[nodiscard]] std::shared_ptr<Component> clone()
const override;
609 StyleProperty<Texture>* m_textureStyle;
612 std::uint64_t m_textureCallbackId = 0;
617 [[nodiscard]]
inline ComponentState getStateFromFlags(
bool hover,
bool active,
bool focused =
false,
bool enabled =
true)
622 return ComponentState::DisabledActive;
624 return ComponentState::Disabled;
632 return ComponentState::FocusedActiveHover;
634 return ComponentState::FocusedActive;
638 return ComponentState::FocusedHover;
640 return ComponentState::Focused;
646 return ComponentState::ActiveHover;
648 return ComponentState::Active;
652 return ComponentState::Hover;
654 return ComponentState::Normal;
659 inline void setOptionalPropertyValue(StyleProperty<Color>& property,
const Color& color, ComponentState state)
662 property.setValue(color, state);
664 property.unsetValue(state);
669 inline void setOptionalPropertyValue(StyleProperty<TextStyles>& property,
const TextStyles& style, ComponentState state)
672 property.setValue(style, state);
674 property.unsetValue(state);
679 inline void setOptionalPropertyValue(StyleProperty<Texture>& property,
const Texture& texture, ComponentState state)
681 if (texture.getData())
682 property.setValue(texture, state);
684 property.unsetValue(state);
Base class for render targets.
Definition BackendRenderTarget.hpp:46
Namespace that contains all TGUI functions and classes.
Definition AbsoluteOrRelativeValue.hpp:37