25#ifndef TGUI_COMPONENTS_HPP
26#define TGUI_COMPONENTS_HPP
28#include <TGUI/Text.hpp>
29#include <TGUI/Sprite.hpp>
30#include <TGUI/Texture.hpp>
31#include <TGUI/Outline.hpp>
33#if !TGUI_EXPERIMENTAL_USE_STD_MODULE
34 #include <unordered_map>
43 class BackendRenderTarget;
52 enum class ComponentState : std::uint8_t
61 FocusedActiveHover = 7,
69 enum class AlignLayout
84 enum class PositionAlignment
100 class TGUI_API MessageBroker
104 TGUI_NODISCARD
static std::uint64_t createTopic();
106 static void destroyTopic(std::uint64_t topicId);
108 TGUI_NODISCARD
static std::uint64_t subscribe(std::uint64_t topicId, std::function<
void()> func);
110 static void unsubscribe(std::uint64_t callbackId);
112 static void sendEvent(std::uint64_t topicId);
115 static std::unordered_map<std::uint64_t, std::set<std::uint64_t>> m_topicIdToCallbackIds;
116 static std::unordered_map<std::uint64_t, std::uint64_t> m_callbackIdToTopicId;
117 static std::unordered_map<std::uint64_t, std::function<void()>> m_listeners;
120 static std::uint64_t m_lastId;
125 class TGUI_API StylePropertyBase
128 virtual ~StylePropertyBase() =
default;
133 template <
typename ValueType>
134 class TGUI_API StyleProperty :
public StylePropertyBase
140 m_messageTopicId{MessageBroker::createTopic()}
144 explicit StyleProperty(ValueType defaultValue) :
145 m_defaultValue {std::move(defaultValue)},
146 m_messageTopicId{MessageBroker::createTopic()}
150 StyleProperty(
const StyleProperty& other) :
151 m_defaultValue {other.m_defaultValue},
152 m_messageTopicId{MessageBroker::createTopic()},
153 m_globalValues {other.m_globalValues}
157 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
158 const std::uint64_t oldBaseIndex = other.m_propertyData & 0xFFFFFFFFFFFF0000;
159 const std::uint16_t oldStoredStates =
static_cast<std::uint16_t
>(other.m_propertyData & 0xFFFF);
161 std::uint16_t total = 0;
162 std::uint8_t bitIndex = 0;
163 while (total < oldStoredStates)
165 if (oldStoredStates & (1 << bitIndex))
167 m_globalValues[baseIndex + bitIndex] = m_globalValues[oldBaseIndex + bitIndex];
168 total +=
static_cast<std::uint16_t
>(1 << bitIndex);
173 m_propertyData = baseIndex | oldStoredStates;
176 StyleProperty(StyleProperty&& other) noexcept :
177 m_defaultValue {std::move(other.m_defaultValue)},
178 m_propertyData {std::move(other.m_propertyData)},
179 m_messageTopicId{std::move(other.m_messageTopicId)},
180 m_globalValues {std::move(other.m_globalValues)}
182 other.m_messageTopicId = 0;
185 ~StyleProperty()
override
187 if (m_messageTopicId)
188 MessageBroker::destroyTopic(m_messageTopicId);
192 StyleProperty& operator=(
const StyleProperty& other)
196 StyleProperty temp(other);
197 std::swap(m_defaultValue, temp.m_defaultValue);
198 std::swap(m_propertyData, temp.m_propertyData);
199 std::swap(m_messageTopicId, temp.m_messageTopicId);
200 std::swap(m_globalValues, temp.m_globalValues);
206 StyleProperty& operator=(StyleProperty&& other)
noexcept
210 m_defaultValue = std::move(other.m_defaultValue);
211 m_propertyData = std::move(other.m_propertyData);
212 m_messageTopicId = std::move(other.m_messageTopicId);
213 m_globalValues = std::move(other.m_globalValues);
215 other.m_messageTopicId = 0;
221 StyleProperty& operator=(
const ValueType& value)
224 setValue(value, ComponentState::Normal);
228 void setValue(
const ValueType& value, ComponentState state = ComponentState::Normal)
230 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
231 m_propertyData |=
static_cast<std::uint64_t
>(1) <<
static_cast<std::uint8_t
>(state);
232 m_globalValues[baseIndex +
static_cast<std::uint8_t
>(state)] = value;
234 MessageBroker::sendEvent(m_messageTopicId);
237 void unsetValue(ComponentState state)
239 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
240 m_propertyData &= ~(
static_cast<std::uint64_t
>(1) <<
static_cast<std::uint8_t
>(state));
241 m_globalValues.erase(baseIndex +
static_cast<std::uint8_t
>(state));
243 MessageBroker::sendEvent(m_messageTopicId);
249 MessageBroker::sendEvent(m_messageTopicId);
252 TGUI_NODISCARD
const ValueType& getValue(ComponentState state = ComponentState::Normal)
const
254 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
255 const std::uint16_t storedStates =
static_cast<std::uint16_t
>(m_propertyData & 0xFFFF);
258 if (storedStates == 0)
259 return m_defaultValue;
262 if (storedStates == 1)
263 return m_globalValues.at(baseIndex);
265 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Disabled))
267 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Active)) && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::DisabledActive))))
268 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::DisabledActive));
269 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Disabled)))
270 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Disabled));
273 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Active))
275 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Hover))
277 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused)) && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::FocusedActiveHover))))
278 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::FocusedActiveHover));
279 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::ActiveHover)))
280 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::ActiveHover));
283 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused)) && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::FocusedActive))))
284 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::FocusedActive));
285 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Active)))
286 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Active));
289 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Hover))
291 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused)) && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::FocusedHover))))
292 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::FocusedHover));
293 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Hover)))
294 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Hover));
297 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused))
299 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Focused)))
300 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Focused));
303 if (storedStates & 1)
307 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Normal));
313 return m_defaultValue;
317 TGUI_NODISCARD std::uint64_t connectCallback(std::function<
void()> func)
319 return MessageBroker::subscribe(m_messageTopicId, std::move(func));
322 void disconnectCallback(std::uint64_t
id)
324 return MessageBroker::unsubscribe(
id);
329 void unsetValueImpl()
331 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
332 const std::uint16_t storedStates =
static_cast<std::uint16_t
>(m_propertyData & 0xFFFF);
334 std::uint16_t total = 0;
335 std::uint8_t bitIndex = 0;
336 while (total < storedStates)
338 if (storedStates & (1 << bitIndex))
340 m_globalValues.erase(baseIndex + bitIndex);
341 total +=
static_cast<std::uint16_t
>(1 << bitIndex);
346 m_propertyData = baseIndex;
351 ValueType m_defaultValue;
355 std::uint64_t m_propertyData = 0;
358 std::uint64_t m_messageTopicId = 0;
368 std::unordered_map<std::uint64_t, ValueType> m_globalValues;
373 struct TGUI_API StylePropertyBackground
375 StyleProperty<Color> borderColor{Color::Black};
376 StyleProperty<Color> color{Color::White};
377 StyleProperty<Texture> texture;
378 StyleProperty<Outline> borders;
379 StyleProperty<Outline> padding;
381 float roundedBorderRadius = 0;
386 struct TGUI_API StylePropertyText
388 StyleProperty<Color> color{Color::Black};
389 StyleProperty<TextStyles> style;
394 class GroupComponent;
396 class TGUI_API Component
400 Component() =
default;
401 virtual ~Component() =
default;
403 Component(
const Component&);
404 Component& operator=(
const Component&);
406 Component(Component&&) =
default;
407 Component& operator=(Component&&) =
default;
409 void setPosition(Vector2f position);
411 TGUI_NODISCARD Vector2f getPosition()
const;
413 TGUI_NODISCARD Vector2f getSize()
const;
415 void setPositionAlignment(PositionAlignment alignment);
417 void setVisible(
bool visible);
419 TGUI_NODISCARD
bool isVisible()
const;
421 void setParent(GroupComponent* parent);
423 virtual void draw(BackendRenderTarget& target, RenderStates states)
const = 0;
425 virtual void updateLayout();
427 TGUI_NODISCARD
virtual std::shared_ptr<Component> clone()
const = 0;
431 friend void swap(Component& first, Component& second);
435 ComponentState m_state = ComponentState::Normal;
436 PositionAlignment m_positionAlignment = PositionAlignment::None;
439 bool m_visible =
true;
441 GroupComponent* m_parent =
nullptr;
444 class TGUI_API GroupComponent :
public Component
448 GroupComponent(
const GroupComponent&);
449 GroupComponent& operator=(
const GroupComponent&);
451 GroupComponent(GroupComponent&&) =
default;
452 GroupComponent& operator=(GroupComponent&&) =
default;
454 TGUI_NODISCARD Vector2f getClientSize()
const;
456 void addComponent(
const std::shared_ptr<Component>& component);
458 TGUI_NODISCARD
const std::vector<std::shared_ptr<Component>>& getComponents()
const;
460 void draw(BackendRenderTarget& target, RenderStates states)
const override;
462 void updateLayout()
override;
464 TGUI_NODISCARD std::shared_ptr<Component> clone()
const override;
466 friend void swap(GroupComponent& first, GroupComponent& second);
470 GroupComponent() =
default;
473 std::vector<std::shared_ptr<Component>> m_children;
474 Vector2f m_clientSize;
479 class TGUI_API BackgroundComponent :
public GroupComponent
483 BackgroundComponent(StylePropertyBackground* backgroundStyle);
485 ~BackgroundComponent()
override;
487 BackgroundComponent(
const BackgroundComponent& other, StylePropertyBackground* backgroundStyle =
nullptr);
488 BackgroundComponent& operator=(
const BackgroundComponent& other);
492 void setSize(Vector2f size);
494 void setBorders(
const Outline& border);
496 TGUI_NODISCARD
const Outline& getBorders()
const;
498 void setPadding(
const Outline& padding);
500 TGUI_NODISCARD
const Outline& getPadding()
const;
502 void setOpacity(
float opacity);
504 void setComponentState(ComponentState state);
506 TGUI_NODISCARD
bool isTransparentPixel(Vector2f pos,
bool transparentTexture)
const;
508 void draw(BackendRenderTarget& target, RenderStates states)
const override;
510 TGUI_NODISCARD Vector2f getSizeWithoutBorders()
const;
512 void updateLayout()
override;
514 TGUI_NODISCARD std::shared_ptr<Component> clone()
const override;
524 StylePropertyBackground* m_backgroundStyle;
526 ColorRect m_background{Color::White, {}};
527 Color m_borderColor = Color::Black;
532 std::uint64_t m_borderColorCallbackId = 0;
533 std::uint64_t m_backgroundColorCallbackId = 0;
534 std::uint64_t m_textureCallbackId = 0;
535 std::uint64_t m_bordersCallbackId = 0;
536 std::uint64_t m_paddingCallbackId = 0;
541 class TGUI_API TextComponent :
public Component
545 TextComponent(StylePropertyText* textStyle);
547 ~TextComponent()
override;
549 TextComponent(
const TextComponent& other, StylePropertyText* textStyle =
nullptr);
550 TextComponent& operator=(
const TextComponent& other);
554 void setString(
const String& caption);
556 TGUI_NODISCARD
const String& getString()
const;
558 void setCharacterSize(
unsigned int size);
560 TGUI_NODISCARD
unsigned int getCharacterSize()
const;
562 void setFont(
const Font& font);
564 TGUI_NODISCARD Font getFont()
const;
566 void setOutlineColor(Color color);
568 TGUI_NODISCARD Color getOutlineColor()
const;
570 void setOutlineThickness(
float thickness);
572 TGUI_NODISCARD
float getOutlineThickness()
const;
574 TGUI_NODISCARD
float getLineHeight()
const;
576 void setOpacity(
float opacity);
578 void updateLayout()
override;
580 void setComponentState(ComponentState state);
582 void draw(BackendRenderTarget& target, RenderStates states)
const override;
584 TGUI_NODISCARD std::shared_ptr<Component> clone()
const override;
588 StylePropertyText* m_textStyle;
590 Color m_color = Color::Black;
591 TextStyles m_style = TextStyle::Regular;
593 std::uint64_t m_colorCallbackId = 0;
594 std::uint64_t m_styleCallbackId = 0;
599 class TGUI_API ImageComponent :
public Component
603 ImageComponent(StyleProperty<Texture>* textureStyle);
605 ~ImageComponent()
override;
607 ImageComponent(
const ImageComponent& other, StyleProperty<Texture>* textureStyle =
nullptr);
608 ImageComponent& operator=(
const ImageComponent& other);
612 void setSize(Vector2f size);
614 void setOpacity(
float opacity);
616 void setComponentState(ComponentState state);
618 TGUI_NODISCARD
bool isTransparentPixel(Vector2f pos,
bool transparentTexture)
const;
620 void draw(BackendRenderTarget& target, RenderStates states)
const override;
622 TGUI_NODISCARD std::shared_ptr<Component> clone()
const override;
626 StyleProperty<Texture>* m_textureStyle;
629 std::uint64_t m_textureCallbackId = 0;
634 TGUI_NODISCARD
inline ComponentState getStateFromFlags(
bool hover,
bool active,
bool focused =
false,
bool enabled =
true)
639 return ComponentState::DisabledActive;
641 return ComponentState::Disabled;
648 return ComponentState::FocusedActiveHover;
650 return ComponentState::FocusedActive;
653 return ComponentState::FocusedHover;
655 return ComponentState::Focused;
660 return ComponentState::ActiveHover;
662 return ComponentState::Active;
665 return ComponentState::Hover;
667 return ComponentState::Normal;
672 inline void setOptionalPropertyValue(StyleProperty<Color>& property,
const Color& color, ComponentState state)
675 property.setValue(color, state);
677 property.unsetValue(state);
682 inline void setOptionalPropertyValue(StyleProperty<TextStyles>& property,
const TextStyles& style, ComponentState state)
685 property.setValue(style, state);
687 property.unsetValue(state);
692 inline void setOptionalPropertyValue(StyleProperty<Texture>& property,
const Texture& texture, ComponentState state)
694 if (texture.getData())
695 property.setValue(texture, state);
697 property.unsetValue(state);
Namespace that contains all TGUI functions and classes.
Definition AbsoluteOrRelativeValue.hpp:38