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#include <unordered_map>
50 enum class ComponentState : std::uint8_t
59 FocusedActiveHover = 7,
67 enum class AlignLayout
82 enum class PositionAlignment
98 class TGUI_API MessageBroker
102 TGUI_NODISCARD
static std::uint64_t createTopic();
104 static void destroyTopic(std::uint64_t topicId);
106 TGUI_NODISCARD
static std::uint64_t subscribe(std::uint64_t topicId, std::function<
void()> func);
108 static void unsubscribe(std::uint64_t callbackId);
110 static void sendEvent(std::uint64_t topicId);
113 static std::unordered_map<std::uint64_t, std::set<std::uint64_t>> m_topicIdToCallbackIds;
114 static std::unordered_map<std::uint64_t, std::uint64_t> m_callbackIdToTopicId;
115 static std::unordered_map<std::uint64_t, std::function<void()>> m_listeners;
118 static std::uint64_t m_lastId;
123 class TGUI_API StylePropertyBase
126 virtual ~StylePropertyBase() =
default;
131 template <
typename ValueType>
132 class TGUI_API StyleProperty :
public StylePropertyBase
138 m_messageTopicId{MessageBroker::createTopic()}
142 explicit StyleProperty(ValueType defaultValue) :
143 m_defaultValue {std::move(defaultValue)},
144 m_messageTopicId{MessageBroker::createTopic()}
148 StyleProperty(
const StyleProperty& other) :
149 m_defaultValue {other.m_defaultValue},
150 m_messageTopicId{MessageBroker::createTopic()},
151 m_globalValues {other.m_globalValues}
155 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
156 const std::uint64_t oldBaseIndex = other.m_propertyData & 0xFFFFFFFFFFFF0000;
157 const std::uint16_t oldStoredStates =
static_cast<std::uint16_t
>(other.m_propertyData & 0xFFFF);
159 std::uint16_t total = 0;
160 std::uint8_t bitIndex = 0;
161 while (total < oldStoredStates)
163 if (oldStoredStates & (1 << bitIndex))
165 m_globalValues[baseIndex + bitIndex] = m_globalValues[oldBaseIndex + bitIndex];
166 total +=
static_cast<std::uint16_t
>(1 << bitIndex);
171 m_propertyData = baseIndex | oldStoredStates;
174 StyleProperty(StyleProperty&& other) noexcept :
175 m_defaultValue {std::move(other.m_defaultValue)},
176 m_propertyData {std::move(other.m_propertyData)},
177 m_messageTopicId{std::move(other.m_messageTopicId)},
178 m_globalValues {std::move(other.m_globalValues)}
180 other.m_messageTopicId = 0;
183 ~StyleProperty()
override
185 if (m_messageTopicId)
186 MessageBroker::destroyTopic(m_messageTopicId);
190 StyleProperty& operator=(
const StyleProperty& other)
194 StyleProperty temp(other);
195 std::swap(m_defaultValue, temp.m_defaultValue);
196 std::swap(m_propertyData, temp.m_propertyData);
197 std::swap(m_messageTopicId, temp.m_messageTopicId);
198 std::swap(m_globalValues, temp.m_globalValues);
204 StyleProperty& operator=(StyleProperty&& other)
noexcept
208 m_defaultValue = std::move(other.m_defaultValue);
209 m_propertyData = std::move(other.m_propertyData);
210 m_messageTopicId = std::move(other.m_messageTopicId);
211 m_globalValues = std::move(other.m_globalValues);
213 other.m_messageTopicId = 0;
219 StyleProperty& operator=(
const ValueType& value)
222 setValue(value, ComponentState::Normal);
226 void setValue(
const ValueType& value, ComponentState state = ComponentState::Normal)
228 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
229 m_propertyData |=
static_cast<std::uint64_t
>(1) <<
static_cast<std::uint8_t
>(state);
230 m_globalValues[baseIndex +
static_cast<std::uint8_t
>(state)] = value;
232 MessageBroker::sendEvent(m_messageTopicId);
235 void unsetValue(ComponentState state)
237 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
238 m_propertyData &= ~(
static_cast<std::uint64_t
>(1) <<
static_cast<std::uint8_t
>(state));
239 m_globalValues.erase(baseIndex +
static_cast<std::uint8_t
>(state));
241 MessageBroker::sendEvent(m_messageTopicId);
247 MessageBroker::sendEvent(m_messageTopicId);
250 TGUI_NODISCARD
const ValueType& getValue(ComponentState state = ComponentState::Normal)
const
252 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
253 const std::uint16_t storedStates =
static_cast<std::uint16_t
>(m_propertyData & 0xFFFF);
256 if (storedStates == 0)
257 return m_defaultValue;
260 if (storedStates == 1)
261 return m_globalValues.at(baseIndex);
263 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Disabled))
265 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Active)) && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::DisabledActive))))
266 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::DisabledActive));
267 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Disabled)))
268 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Disabled));
271 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Active))
273 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Hover))
275 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused)) && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::FocusedActiveHover))))
276 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::FocusedActiveHover));
277 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::ActiveHover)))
278 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::ActiveHover));
281 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused)) && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::FocusedActive))))
282 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::FocusedActive));
283 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Active)))
284 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Active));
287 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Hover))
289 if ((
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused)) && (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::FocusedHover))))
290 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::FocusedHover));
291 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Hover)))
292 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Hover));
295 if (
static_cast<std::uint8_t
>(state) &
static_cast<std::uint8_t
>(ComponentState::Focused))
297 if (storedStates & (1 <<
static_cast<std::uint8_t
>(ComponentState::Focused)))
298 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Focused));
301 if (storedStates & 1)
305 return m_globalValues.at(baseIndex +
static_cast<std::uint8_t
>(ComponentState::Normal));
311 return m_defaultValue;
315 TGUI_NODISCARD std::uint64_t connectCallback(std::function<
void()> func)
317 return MessageBroker::subscribe(m_messageTopicId, std::move(func));
320 void disconnectCallback(std::uint64_t
id)
322 return MessageBroker::unsubscribe(
id);
327 void unsetValueImpl()
329 const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000;
330 const std::uint16_t storedStates =
static_cast<std::uint16_t
>(m_propertyData & 0xFFFF);
332 std::uint16_t total = 0;
333 std::uint8_t bitIndex = 0;
334 while (total < storedStates)
336 if (storedStates & (1 << bitIndex))
338 m_globalValues.erase(baseIndex + bitIndex);
339 total +=
static_cast<std::uint16_t
>(1 << bitIndex);
344 m_propertyData = baseIndex;
349 ValueType m_defaultValue;
353 std::uint64_t m_propertyData = 0;
356 std::uint64_t m_messageTopicId = 0;
366 std::unordered_map<std::uint64_t, ValueType> m_globalValues;
371 struct TGUI_API StylePropertyBackground
373 StyleProperty<Color> borderColor{Color::Black};
374 StyleProperty<Color> color{Color::White};
375 StyleProperty<Texture> texture;
376 StyleProperty<Outline> borders;
377 StyleProperty<Outline> padding;
379 float roundedBorderRadius = 0;
384 struct TGUI_API StylePropertyText
386 StyleProperty<Color> color{Color::Black};
387 StyleProperty<TextStyles> style;
392 class GroupComponent;
394 class TGUI_API Component
398 Component() =
default;
399 virtual ~Component() =
default;
401 Component(
const Component&);
402 Component& operator=(
const Component&);
404 Component(Component&&) =
default;
405 Component& operator=(Component&&) =
default;
407 void setPosition(Vector2f position);
409 TGUI_NODISCARD Vector2f getPosition()
const;
411 TGUI_NODISCARD Vector2f getSize()
const;
413 void setPositionAlignment(PositionAlignment alignment);
415 void setVisible(
bool visible);
417 TGUI_NODISCARD
bool isVisible()
const;
419 void setParent(GroupComponent* parent);
421 virtual void draw(BackendRenderTarget& target, RenderStates states)
const = 0;
423 virtual void updateLayout();
425 TGUI_NODISCARD
virtual std::shared_ptr<Component> clone()
const = 0;
429 friend void swap(Component& first, Component& second);
433 ComponentState m_state = ComponentState::Normal;
434 PositionAlignment m_positionAlignment = PositionAlignment::None;
437 bool m_visible =
true;
439 GroupComponent* m_parent =
nullptr;
442 class TGUI_API GroupComponent :
public Component
446 GroupComponent(
const GroupComponent&);
447 GroupComponent& operator=(
const GroupComponent&);
449 GroupComponent(GroupComponent&&) =
default;
450 GroupComponent& operator=(GroupComponent&&) =
default;
452 TGUI_NODISCARD Vector2f getClientSize()
const;
454 void addComponent(
const std::shared_ptr<Component>& component);
456 TGUI_NODISCARD
const std::vector<std::shared_ptr<Component>>& getComponents()
const;
458 void draw(BackendRenderTarget& target, RenderStates states)
const override;
460 void updateLayout()
override;
462 TGUI_NODISCARD std::shared_ptr<Component> clone()
const override;
464 friend void swap(GroupComponent& first, GroupComponent& second);
468 GroupComponent() =
default;
471 std::vector<std::shared_ptr<Component>> m_children;
472 Vector2f m_clientSize;
477 class TGUI_API BackgroundComponent :
public GroupComponent
481 BackgroundComponent(StylePropertyBackground* backgroundStyle);
483 ~BackgroundComponent()
override;
485 BackgroundComponent(
const BackgroundComponent& other, StylePropertyBackground* backgroundStyle =
nullptr);
486 BackgroundComponent& operator=(
const BackgroundComponent& other);
490 void setSize(Vector2f size);
492 void setBorders(
const Outline& border);
494 TGUI_NODISCARD
const Outline& getBorders()
const;
496 void setPadding(
const Outline& padding);
498 TGUI_NODISCARD
const Outline& getPadding()
const;
500 void setOpacity(
float opacity);
502 void setComponentState(ComponentState state);
504 TGUI_NODISCARD
bool isTransparentPixel(Vector2f pos,
bool transparentTexture)
const;
506 void draw(BackendRenderTarget& target, RenderStates states)
const override;
508 TGUI_NODISCARD Vector2f getSizeWithoutBorders()
const;
510 void updateLayout()
override;
512 TGUI_NODISCARD std::shared_ptr<Component> clone()
const override;
522 StylePropertyBackground* m_backgroundStyle;
524 ColorRect m_background{Color::White, {}};
525 Color m_borderColor = Color::Black;
530 std::uint64_t m_borderColorCallbackId = 0;
531 std::uint64_t m_backgroundColorCallbackId = 0;
532 std::uint64_t m_textureCallbackId = 0;
533 std::uint64_t m_bordersCallbackId = 0;
534 std::uint64_t m_paddingCallbackId = 0;
539 class TGUI_API TextComponent :
public Component
543 TextComponent(StylePropertyText* textStyle);
545 ~TextComponent()
override;
547 TextComponent(
const TextComponent& other, StylePropertyText* textStyle =
nullptr);
548 TextComponent& operator=(
const TextComponent& other);
552 void setString(
const String& caption);
554 TGUI_NODISCARD
const String& getString()
const;
556 void setCharacterSize(
unsigned int size);
558 TGUI_NODISCARD
unsigned int getCharacterSize()
const;
560 void setFont(
const Font& font);
562 TGUI_NODISCARD Font getFont()
const;
564 void setOutlineColor(Color color);
566 TGUI_NODISCARD Color getOutlineColor()
const;
568 void setOutlineThickness(
float thickness);
570 TGUI_NODISCARD
float getOutlineThickness()
const;
572 TGUI_NODISCARD
float getLineHeight()
const;
574 void setOpacity(
float opacity);
576 void updateLayout()
override;
578 void setComponentState(ComponentState state);
580 void draw(BackendRenderTarget& target, RenderStates states)
const override;
582 TGUI_NODISCARD std::shared_ptr<Component> clone()
const override;
586 StylePropertyText* m_textStyle;
588 Color m_color = Color::Black;
589 TextStyles m_style = TextStyle::Regular;
591 std::uint64_t m_colorCallbackId = 0;
592 std::uint64_t m_styleCallbackId = 0;
597 class TGUI_API ImageComponent :
public Component
601 ImageComponent(StyleProperty<Texture>* textureStyle);
603 ~ImageComponent()
override;
605 ImageComponent(
const ImageComponent& other, StyleProperty<Texture>* textureStyle =
nullptr);
606 ImageComponent& operator=(
const ImageComponent& other);
610 void setSize(Vector2f size);
612 void setOpacity(
float opacity);
614 void setComponentState(ComponentState state);
616 TGUI_NODISCARD
bool isTransparentPixel(Vector2f pos,
bool transparentTexture)
const;
618 void draw(BackendRenderTarget& target, RenderStates states)
const override;
620 TGUI_NODISCARD std::shared_ptr<Component> clone()
const override;
624 StyleProperty<Texture>* m_textureStyle;
627 std::uint64_t m_textureCallbackId = 0;
632 TGUI_NODISCARD
inline ComponentState getStateFromFlags(
bool hover,
bool active,
bool focused =
false,
bool enabled =
true)
637 return ComponentState::DisabledActive;
639 return ComponentState::Disabled;
646 return ComponentState::FocusedActiveHover;
648 return ComponentState::FocusedActive;
651 return ComponentState::FocusedHover;
653 return ComponentState::Focused;
658 return ComponentState::ActiveHover;
660 return ComponentState::Active;
663 return ComponentState::Hover;
665 return ComponentState::Normal;
670 inline void setOptionalPropertyValue(StyleProperty<Color>& property,
const Color& color, ComponentState state)
673 property.setValue(color, state);
675 property.unsetValue(state);
680 inline void setOptionalPropertyValue(StyleProperty<TextStyles>& property,
const TextStyles& style, ComponentState state)
683 property.setValue(style, state);
685 property.unsetValue(state);
690 inline void setOptionalPropertyValue(StyleProperty<Texture>& property,
const Texture& texture, ComponentState state)
692 if (texture.getData())
693 property.setValue(texture, state);
695 property.unsetValue(state);
Base class for render targets.
Definition BackendRenderTarget.hpp:46
Namespace that contains all TGUI functions and classes.
Definition AbsoluteOrRelativeValue.hpp:36