26#ifndef TGUI_COMPONENTS_HPP
27#define TGUI_COMPONENTS_HPP
29#include <TGUI/Text.hpp>
30#include <TGUI/Sprite.hpp>
31#include <TGUI/Texture.hpp>
32#include <TGUI/Outline.hpp>
34#if !TGUI_EXPERIMENTAL_USE_STD_MODULE
35 #include <unordered_map>
44 class BackendRenderTarget;
53 enum class ComponentState : std::uint8_t
62 FocusedActiveHover = 7,
70 enum class AlignLayout
85 enum class PositionAlignment
101 class TGUI_API MessageBroker
105 TGUI_NODISCARD
static std::uint64_t createTopic();
107 static void destroyTopic(std::uint64_t topicId);
109 TGUI_NODISCARD
static std::uint64_t subscribe(std::uint64_t topicId, std::function<
void()> func);
111 static void unsubscribe(std::uint64_t callbackId);
113 static void sendEvent(std::uint64_t topicId);
116 static std::unordered_map<std::uint64_t, std::set<std::uint64_t>> m_topicIdToCallbackIds;
117 static std::unordered_map<std::uint64_t, std::uint64_t> m_callbackIdToTopicId;
118 static std::unordered_map<std::uint64_t, std::function<void()>> m_listeners;
121 static std::uint64_t m_lastId;
126 class TGUI_API StylePropertyBase
129 virtual ~StylePropertyBase() =
default;
134 template <
typename ValueType>
135 class TGUI_API StyleProperty :
public StylePropertyBase
141 m_messageTopicId{MessageBroker::createTopic()}
145 explicit StyleProperty(ValueType defaultValue) :
146 m_defaultValue {std::move(defaultValue)},
147 m_messageTopicId{MessageBroker::createTopic()}
151 StyleProperty(
const StyleProperty& other) :
152 m_defaultValue {other.m_defaultValue},
153 m_messageTopicId{MessageBroker::createTopic()},
154 m_globalValues {other.m_globalValues}
158 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
159 const std::uint64_t oldBaseIndex = other.m_propertyData & 0xFFFFFFFFFFFF0000;
160 const std::uint16_t oldStoredStates =
static_cast<std::uint16_t
>(other.m_propertyData & 0xFFFF);
162 std::uint16_t total = 0;
163 std::uint8_t bitIndex = 0;
164 while (total < oldStoredStates)
166 if (oldStoredStates & (1 << bitIndex))
168 m_globalValues[baseIndex + bitIndex] = m_globalValues[oldBaseIndex + bitIndex];
169 total +=
static_cast<std::uint16_t
>(1 << bitIndex);
174 m_propertyData = baseIndex | oldStoredStates;
177 StyleProperty(StyleProperty&& other) noexcept :
178 m_defaultValue {std::move(other.m_defaultValue)},
179 m_propertyData {std::move(other.m_propertyData)},
180 m_messageTopicId{std::move(other.m_messageTopicId)},
181 m_globalValues {std::move(other.m_globalValues)}
183 other.m_messageTopicId = 0;
186 ~StyleProperty()
override
188 if (m_messageTopicId)
189 MessageBroker::destroyTopic(m_messageTopicId);
193 StyleProperty& operator=(
const StyleProperty& other)
197 StyleProperty temp(other);
198 std::swap(m_defaultValue, temp.m_defaultValue);
199 std::swap(m_propertyData, temp.m_propertyData);
200 std::swap(m_messageTopicId, temp.m_messageTopicId);
201 std::swap(m_globalValues, temp.m_globalValues);
207 StyleProperty& operator=(StyleProperty&& other)
noexcept
211 m_defaultValue = std::move(other.m_defaultValue);
212 m_propertyData = std::move(other.m_propertyData);
213 m_messageTopicId = std::move(other.m_messageTopicId);
214 m_globalValues = std::move(other.m_globalValues);
216 other.m_messageTopicId = 0;
222 StyleProperty& operator=(
const ValueType& value)
225 setValue(value, ComponentState::Normal);
229 void setValue(
const ValueType& value, ComponentState state = ComponentState::Normal)
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[baseIndex +
static_cast<std::uint8_t
>(state)] = value;
235 MessageBroker::sendEvent(m_messageTopicId);
238 void unsetValue(ComponentState state)
240 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
241 m_propertyData &= ~(
static_cast<std::uint64_t
>(1) <<
static_cast<std::uint8_t
>(state));
242 m_globalValues.erase(baseIndex +
static_cast<std::uint8_t
>(state));
244 MessageBroker::sendEvent(m_messageTopicId);
250 MessageBroker::sendEvent(m_messageTopicId);
253 TGUI_NODISCARD
const ValueType& getValue(ComponentState state = ComponentState::Normal)
const
255 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
256 const std::uint16_t storedStates =
static_cast<std::uint16_t
>(m_propertyData & 0xFFFF);
259 if (storedStates == 0)
260 return m_defaultValue;
263 if (storedStates == 1)
264 return m_globalValues.at(baseIndex);
266 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Disabled))
268 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Active)) && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::DisabledActive))))
269 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::DisabledActive));
270 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Disabled)))
271 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Disabled));
274 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Active))
276 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Hover))
278 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused)) && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::FocusedActiveHover))))
279 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::FocusedActiveHover));
280 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::ActiveHover)))
281 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::ActiveHover));
284 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused)) && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::FocusedActive))))
285 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::FocusedActive));
286 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Active)))
287 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Active));
290 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Hover))
292 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused)) && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::FocusedHover))))
293 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::FocusedHover));
294 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Hover)))
295 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Hover));
298 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused))
300 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Focused)))
301 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Focused));
304 if (storedStates & 1)
308 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Normal));
314 return m_defaultValue;
318 TGUI_NODISCARD std::uint64_t connectCallback(std::function<
void()> func)
320 return MessageBroker::subscribe(m_messageTopicId, std::move(func));
323 void disconnectCallback(std::uint64_t
id)
325 return MessageBroker::unsubscribe(
id);
330 void unsetValueImpl()
332 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
333 const std::uint16_t storedStates =
static_cast<std::uint16_t
>(m_propertyData & 0xFFFF);
335 std::uint16_t total = 0;
336 std::uint8_t bitIndex = 0;
337 while (total < storedStates)
339 if (storedStates & (1 << bitIndex))
341 m_globalValues.erase(baseIndex + bitIndex);
342 total +=
static_cast<std::uint16_t
>(1 << bitIndex);
347 m_propertyData = baseIndex;
352 ValueType m_defaultValue;
356 std::uint64_t m_propertyData = 0;
359 std::uint64_t m_messageTopicId = 0;
369 std::unordered_map<std::uint64_t, ValueType> m_globalValues;
374 struct TGUI_API StylePropertyBackground
376 StyleProperty<Color> borderColor{Color::Black};
377 StyleProperty<Color> color{Color::White};
378 StyleProperty<Texture> texture;
379 StyleProperty<Outline> borders;
380 StyleProperty<Outline> padding;
382 float roundedBorderRadius = 0;
387 struct TGUI_API StylePropertyText
389 StyleProperty<Color> color{Color::Black};
390 StyleProperty<TextStyles> style;
395 class GroupComponent;
397 class TGUI_API Component
401 Component() =
default;
402 virtual ~Component() =
default;
404 Component(
const Component&);
405 Component& operator=(
const Component&);
407 Component(Component&&) =
default;
408 Component& operator=(Component&&) =
default;
410 void setPosition(Vector2f position);
412 TGUI_NODISCARD Vector2f getPosition()
const;
414 TGUI_NODISCARD Vector2f getSize()
const;
416 void setPositionAlignment(PositionAlignment alignment);
418 void setVisible(
bool visible);
420 TGUI_NODISCARD
bool isVisible()
const;
422 void setParent(GroupComponent* parent);
424 virtual void draw(BackendRenderTarget& target, RenderStates states)
const = 0;
426 virtual void updateLayout();
428 TGUI_NODISCARD
virtual std::shared_ptr<Component> clone()
const = 0;
432 friend void swap(Component& first, Component& second);
436 ComponentState m_state = ComponentState::Normal;
437 PositionAlignment m_positionAlignment = PositionAlignment::None;
440 bool m_visible =
true;
442 GroupComponent* m_parent =
nullptr;
445 class TGUI_API GroupComponent :
public Component
449 GroupComponent(
const GroupComponent&);
450 GroupComponent& operator=(
const GroupComponent&);
452 GroupComponent(GroupComponent&&) =
default;
453 GroupComponent& operator=(GroupComponent&&) =
default;
455 TGUI_NODISCARD Vector2f getClientSize()
const;
457 void addComponent(
const std::shared_ptr<Component>& component);
459 TGUI_NODISCARD
const std::vector<std::shared_ptr<Component>>& getComponents()
const;
461 void draw(BackendRenderTarget& target, RenderStates states)
const override;
463 void updateLayout()
override;
465 TGUI_NODISCARD std::shared_ptr<Component> clone()
const override;
467 friend void swap(GroupComponent& first, GroupComponent& second);
471 GroupComponent() =
default;
474 std::vector<std::shared_ptr<Component>> m_children;
475 Vector2f m_clientSize;
480 class TGUI_API BackgroundComponent :
public GroupComponent
484 BackgroundComponent(StylePropertyBackground* backgroundStyle);
486 ~BackgroundComponent()
override;
488 BackgroundComponent(
const BackgroundComponent& other, StylePropertyBackground* backgroundStyle =
nullptr);
489 BackgroundComponent& operator=(
const BackgroundComponent& other);
493 void setSize(Vector2f size);
495 void setBorders(
const Outline& border);
497 TGUI_NODISCARD
const Outline& getBorders()
const;
499 void setPadding(
const Outline& padding);
501 TGUI_NODISCARD
const Outline& getPadding()
const;
503 void setOpacity(
float opacity);
505 void setComponentState(ComponentState state);
507 TGUI_NODISCARD
bool isTransparentPixel(Vector2f pos,
bool transparentTexture)
const;
509 void draw(BackendRenderTarget& target, RenderStates states)
const override;
511 TGUI_NODISCARD Vector2f getSizeWithoutBorders()
const;
513 void updateLayout()
override;
515 TGUI_NODISCARD std::shared_ptr<Component> clone()
const override;
525 StylePropertyBackground* m_backgroundStyle;
527 ColorRect m_background{Color::White, {}};
528 Color m_borderColor = Color::Black;
533 std::uint64_t m_borderColorCallbackId = 0;
534 std::uint64_t m_backgroundColorCallbackId = 0;
535 std::uint64_t m_textureCallbackId = 0;
536 std::uint64_t m_bordersCallbackId = 0;
537 std::uint64_t m_paddingCallbackId = 0;
542 class TGUI_API TextComponent :
public Component
546 TextComponent(StylePropertyText* textStyle);
548 ~TextComponent()
override;
550 TextComponent(
const TextComponent& other, StylePropertyText* textStyle =
nullptr);
551 TextComponent& operator=(
const TextComponent& other);
555 void setString(
const String& caption);
557 TGUI_NODISCARD
const String& getString()
const;
559 void setCharacterSize(
unsigned int size);
561 TGUI_NODISCARD
unsigned int getCharacterSize()
const;
563 void setFont(
const Font& font);
565 TGUI_NODISCARD Font getFont()
const;
567 void setOutlineColor(Color color);
569 TGUI_NODISCARD Color getOutlineColor()
const;
571 void setOutlineThickness(
float thickness);
573 TGUI_NODISCARD
float getOutlineThickness()
const;
575 TGUI_NODISCARD
float getLineHeight()
const;
577 void setOpacity(
float opacity);
579 void updateLayout()
override;
581 void setComponentState(ComponentState state);
583 void draw(BackendRenderTarget& target, RenderStates states)
const override;
585 TGUI_NODISCARD std::shared_ptr<Component> clone()
const override;
589 StylePropertyText* m_textStyle;
591 Color m_color = Color::Black;
592 TextStyles m_style = TextStyle::Regular;
594 std::uint64_t m_colorCallbackId = 0;
595 std::uint64_t m_styleCallbackId = 0;
600 class TGUI_API ImageComponent :
public Component
604 ImageComponent(StyleProperty<Texture>* textureStyle);
606 ~ImageComponent()
override;
608 ImageComponent(
const ImageComponent& other, StyleProperty<Texture>* textureStyle =
nullptr);
609 ImageComponent& operator=(
const ImageComponent& other);
613 void setSize(Vector2f size);
615 void setOpacity(
float opacity);
617 void setComponentState(ComponentState state);
619 TGUI_NODISCARD
bool isTransparentPixel(Vector2f pos,
bool transparentTexture)
const;
621 void draw(BackendRenderTarget& target, RenderStates states)
const override;
623 TGUI_NODISCARD std::shared_ptr<Component> clone()
const override;
627 StyleProperty<Texture>* m_textureStyle;
630 std::uint64_t m_textureCallbackId = 0;
635 TGUI_NODISCARD
inline ComponentState getStateFromFlags(
bool hover,
bool active,
bool focused =
false,
bool enabled =
true)
640 return ComponentState::DisabledActive;
642 return ComponentState::Disabled;
649 return ComponentState::FocusedActiveHover;
651 return ComponentState::FocusedActive;
654 return ComponentState::FocusedHover;
656 return ComponentState::Focused;
661 return ComponentState::ActiveHover;
663 return ComponentState::Active;
666 return ComponentState::Hover;
668 return ComponentState::Normal;
673 inline void setOptionalPropertyValue(StyleProperty<Color>& property,
const Color& color, ComponentState state)
676 property.setValue(color, state);
678 property.unsetValue(state);
683 inline void setOptionalPropertyValue(StyleProperty<TextStyles>& property,
const TextStyles& style, ComponentState state)
686 property.setValue(style, state);
688 property.unsetValue(state);
693 inline void setOptionalPropertyValue(StyleProperty<Texture>& property,
const Texture& texture, ComponentState state)
695 if (texture.getData())
696 property.setValue(texture, state);
698 property.unsetValue(state);
Namespace that contains all TGUI functions and classes.
Definition AbsoluteOrRelativeValue.hpp:39