From 6b6414f60cfd9c75834c1fb48a465d84d7c531f5 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Tue, 23 Jun 2026 21:59:36 +0200 Subject: [PATCH] Take advantage of concatenated namespaces a bit more --- include/TGUI/Components.hpp | 937 ++++++++++++++++++------------------ include/TGUI/Keyboard.hpp | 105 ++-- 2 files changed, 516 insertions(+), 526 deletions(-) diff --git a/include/TGUI/Components.hpp b/include/TGUI/Components.hpp index 66d164a26..544915722 100644 --- a/include/TGUI/Components.hpp +++ b/include/TGUI/Components.hpp @@ -40,657 +40,652 @@ namespace tgui { class BackendRenderTarget; - namespace priv + namespace priv::dev { - namespace dev + /// State of a widget or a component inside it + enum class ComponentState : std::uint8_t { - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + Normal = 0, //!< Default state + Hover = 1, //!< Mouse hover + Active = 2, //!< Pressed/checked/selected + ActiveHover = 3, //!< Pressed/checked/selected with mouse hover + Focused = 4, //!< Has focused + FocusedHover = 5, //!< Has focused with mouse hover + FocusedActive = 6, //!< Has focused while pressed/checked/selected + FocusedActiveHover = 7, //!< Has focused while pressed/checked/selected with mouse hover + Disabled = 8, //!< Is disabled + DisabledActive = 10 //!< Is disabled while pressed/checked/selected + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /// Layout alignment for automatically setting the position and (part of) the size of a component + enum class AlignLayout : std::uint8_t + { + None, //!< Position and size need to be manually set. This is the default. + Top, //!< Places the component on on the top and sets its width to the area between Leftmost and Rightmost aligned components. Height needs to be manually set. + Left, //!< Places the component on the left side and sets its height to the area between Top and Bottom aligned components. Width needs to be manually set. + Right, //!< Places the component on the right side and sets its height to the area between Top and Bottom aligned components. Width needs to be manually set. + Bottom, //!< Places the component on on the bottom and sets its width to the area between Leftmost and Rightmost aligned components. Height needs to be manually set. + Leftmost, //!< Places the component on the left side and sets height to 100%. Width needs to be manually set. Same as Left alignment if no component uses Top or Bottom alignment. + Rightmost, //!< Places the component on the right side and sets height to 100%. Width needs to be manually set. Same as Left alignment if no component uses Top or Bottom alignment. + Fill //!< Sets the position to (0, 0) and size to (100%, 100%). + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + + /// Position alignment of a component within its parent + enum class PositionAlignment : std::uint8_t + { + None, //!< Place the component at the manually set position. This is the default. + TopLeft, //!< Place the component in the upper left corner of its parent + Top, //!< Place the component at the upper side of its parent (horizontally centered) + TopRight, //!< Place the component in the upper right corner of its parent + Right, //!< Place the component at the right side of its parent (vertically centered) + BottomRight, //!< Place the component in the bottom right corner of its parent + Bottom, //!< Place the component at the bottom of its parent (horizontally centered) + BottomLeft, //!< Place the component in the bottom left corner of its parent + Left, //!< Place the component at the left side of its parent (vertically centered) + Center //!< Center the component in its parent + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + + class TGUI_API MessageBroker + { + public: + [[nodiscard]] static std::uint64_t createTopic(); - /// State of a widget or a component inside it - enum class ComponentState : std::uint8_t - { - Normal = 0, //!< Default state - Hover = 1, //!< Mouse hover - Active = 2, //!< Pressed/checked/selected - ActiveHover = 3, //!< Pressed/checked/selected with mouse hover - Focused = 4, //!< Has focused - FocusedHover = 5, //!< Has focused with mouse hover - FocusedActive = 6, //!< Has focused while pressed/checked/selected - FocusedActiveHover = 7, //!< Has focused while pressed/checked/selected with mouse hover - Disabled = 8, //!< Is disabled - DisabledActive = 10 //!< Is disabled while pressed/checked/selected - }; + static void destroyTopic(std::uint64_t topicId); - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + [[nodiscard]] static std::uint64_t subscribe(std::uint64_t topicId, std::function func); - /// Layout alignment for automatically setting the position and (part of) the size of a component - enum class AlignLayout : std::uint8_t - { - None, //!< Position and size need to be manually set. This is the default. - Top, //!< Places the component on on the top and sets its width to the area between Leftmost and Rightmost aligned components. Height needs to be manually set. - Left, //!< Places the component on the left side and sets its height to the area between Top and Bottom aligned components. Width needs to be manually set. - Right, //!< Places the component on the right side and sets its height to the area between Top and Bottom aligned components. Width needs to be manually set. - Bottom, //!< Places the component on on the bottom and sets its width to the area between Leftmost and Rightmost aligned components. Height needs to be manually set. - Leftmost, //!< Places the component on the left side and sets height to 100%. Width needs to be manually set. Same as Left alignment if no component uses Top or Bottom alignment. - Rightmost, //!< Places the component on the right side and sets height to 100%. Width needs to be manually set. Same as Left alignment if no component uses Top or Bottom alignment. - Fill //!< Sets the position to (0, 0) and size to (100%, 100%). - }; + static void unsubscribe(std::uint64_t callbackId); - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + static void sendEvent(std::uint64_t topicId); - /// Position alignment of a component within its parent - enum class PositionAlignment : std::uint8_t - { - None, //!< Place the component at the manually set position. This is the default. - TopLeft, //!< Place the component in the upper left corner of its parent - Top, //!< Place the component at the upper side of its parent (horizontally centered) - TopRight, //!< Place the component in the upper right corner of its parent - Right, //!< Place the component at the right side of its parent (vertically centered) - BottomRight, //!< Place the component in the bottom right corner of its parent - Bottom, //!< Place the component at the bottom of its parent (horizontally centered) - BottomLeft, //!< Place the component in the bottom left corner of its parent - Left, //!< Place the component at the left side of its parent (vertically centered) - Center //!< Center the component in its parent - }; + private: + static std::unordered_map> m_topicIdToCallbackIds; + static std::unordered_map m_callbackIdToTopicId; + static std::unordered_map> m_listeners; // CallbackId -> Func - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + // All topic and callback ids are unique and non-overlapping + static std::uint64_t m_lastId; + }; - class TGUI_API MessageBroker - { - public: - [[nodiscard]] static std::uint64_t createTopic(); + //////////////////////////////////////////////////////////////////////////////////////////////////////////// - static void destroyTopic(std::uint64_t topicId); + class TGUI_API StylePropertyBase + { + public: + virtual ~StylePropertyBase() = default; + }; - [[nodiscard]] static std::uint64_t subscribe(std::uint64_t topicId, std::function func); + //////////////////////////////////////////////////////////////////////////////////////////////////////////// - static void unsubscribe(std::uint64_t callbackId); + template + class TGUI_API StyleProperty : public StylePropertyBase + { + public: + StyleProperty() : + m_defaultValue{}, + m_messageTopicId{MessageBroker::createTopic()} + { + } - static void sendEvent(std::uint64_t topicId); + explicit StyleProperty(ValueType defaultValue) : + m_defaultValue{std::move(defaultValue)}, + m_messageTopicId{MessageBroker::createTopic()} + { + } + + StyleProperty(const StyleProperty& other) : + m_defaultValue{other.m_defaultValue}, + m_messageTopicId{MessageBroker::createTopic()}, + m_globalValues{other.m_globalValues} + { + unsetValue(); - private: - static std::unordered_map> m_topicIdToCallbackIds; - static std::unordered_map m_callbackIdToTopicId; - static std::unordered_map> m_listeners; // CallbackId -> Func + const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000; + const std::uint64_t oldBaseIndex = other.m_propertyData & 0xFFFFFFFFFFFF0000; + const auto oldStoredStates = static_cast(other.m_propertyData & 0xFFFF); - // All topic and callback ids are unique and non-overlapping - static std::uint64_t m_lastId; - }; + std::uint16_t total = 0; + std::uint8_t bitIndex = 0; + while (total < oldStoredStates) + { + if (oldStoredStates & (1 << bitIndex)) + { + m_globalValues[baseIndex + bitIndex] = m_globalValues[oldBaseIndex + bitIndex]; + total += static_cast(1 << bitIndex); + } + ++bitIndex; + } - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + m_propertyData = baseIndex | oldStoredStates; + } - class TGUI_API StylePropertyBase + StyleProperty(StyleProperty&& other) noexcept : + m_defaultValue{std::move(other.m_defaultValue)}, + m_propertyData{std::move(other.m_propertyData)}, + m_messageTopicId{std::move(other.m_messageTopicId)}, + m_globalValues{std::move(other.m_globalValues)} { - public: - virtual ~StylePropertyBase() = default; - }; + other.m_messageTopicId = 0; + } - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + ~StyleProperty() override + { + if (m_messageTopicId) // Can be 0 on moved object + MessageBroker::destroyTopic(m_messageTopicId); + unsetValueImpl(); + } - template - class TGUI_API StyleProperty : public StylePropertyBase + StyleProperty& operator=(const StyleProperty& other) { - public: - StyleProperty() : - m_defaultValue{}, - m_messageTopicId{MessageBroker::createTopic()} + if (&other != this) { + StyleProperty temp(other); + std::swap(m_defaultValue, temp.m_defaultValue); + std::swap(m_propertyData, temp.m_propertyData); + std::swap(m_messageTopicId, temp.m_messageTopicId); + std::swap(m_globalValues, temp.m_globalValues); } - explicit StyleProperty(ValueType defaultValue) : - m_defaultValue{std::move(defaultValue)}, - m_messageTopicId{MessageBroker::createTopic()} - { - } + return *this; + } - StyleProperty(const StyleProperty& other) : - m_defaultValue{other.m_defaultValue}, - m_messageTopicId{MessageBroker::createTopic()}, - m_globalValues{other.m_globalValues} + StyleProperty& operator=(StyleProperty&& other) noexcept + { + if (&other != this) { - unsetValue(); - - const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000; - const std::uint64_t oldBaseIndex = other.m_propertyData & 0xFFFFFFFFFFFF0000; - const auto oldStoredStates = static_cast(other.m_propertyData & 0xFFFF); - - std::uint16_t total = 0; - std::uint8_t bitIndex = 0; - while (total < oldStoredStates) - { - if (oldStoredStates & (1 << bitIndex)) - { - m_globalValues[baseIndex + bitIndex] = m_globalValues[oldBaseIndex + bitIndex]; - total += static_cast(1 << bitIndex); - } - ++bitIndex; - } - - m_propertyData = baseIndex | oldStoredStates; - } + m_defaultValue = std::move(other.m_defaultValue); + m_propertyData = std::move(other.m_propertyData); + m_messageTopicId = std::move(other.m_messageTopicId); + m_globalValues = std::move(other.m_globalValues); - StyleProperty(StyleProperty&& other) noexcept : - m_defaultValue{std::move(other.m_defaultValue)}, - m_propertyData{std::move(other.m_propertyData)}, - m_messageTopicId{std::move(other.m_messageTopicId)}, - m_globalValues{std::move(other.m_globalValues)} - { other.m_messageTopicId = 0; } - ~StyleProperty() override - { - if (m_messageTopicId) // Can be 0 on moved object - MessageBroker::destroyTopic(m_messageTopicId); - unsetValueImpl(); - } - - StyleProperty& operator=(const StyleProperty& other) - { - if (&other != this) - { - StyleProperty temp(other); - std::swap(m_defaultValue, temp.m_defaultValue); - std::swap(m_propertyData, temp.m_propertyData); - std::swap(m_messageTopicId, temp.m_messageTopicId); - std::swap(m_globalValues, temp.m_globalValues); - } + return *this; + } - return *this; - } + StyleProperty& operator=(const ValueType& value) + { + unsetValueImpl(); + setValue(value, ComponentState::Normal); + return *this; + } - StyleProperty& operator=(StyleProperty&& other) noexcept - { - if (&other != this) - { - m_defaultValue = std::move(other.m_defaultValue); - m_propertyData = std::move(other.m_propertyData); - m_messageTopicId = std::move(other.m_messageTopicId); - m_globalValues = std::move(other.m_globalValues); + void setValue(const ValueType& value, ComponentState state = ComponentState::Normal) + { + const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000; + m_propertyData |= static_cast(1) << static_cast(state); + m_globalValues[baseIndex + static_cast(state)] = value; - other.m_messageTopicId = 0; - } + MessageBroker::sendEvent(m_messageTopicId); + } - return *this; - } + void unsetValue(ComponentState state) + { + const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000; + m_propertyData &= ~(static_cast(1) << static_cast(state)); + m_globalValues.erase(baseIndex + static_cast(state)); - StyleProperty& operator=(const ValueType& value) - { - unsetValueImpl(); - setValue(value, ComponentState::Normal); - return *this; - } + MessageBroker::sendEvent(m_messageTopicId); + } - void setValue(const ValueType& value, ComponentState state = ComponentState::Normal) - { - const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000; - m_propertyData |= static_cast(1) << static_cast(state); - m_globalValues[baseIndex + static_cast(state)] = value; + void unsetValue() + { + unsetValueImpl(); + MessageBroker::sendEvent(m_messageTopicId); + } - MessageBroker::sendEvent(m_messageTopicId); - } + [[nodiscard]] const ValueType& getValue(ComponentState state = ComponentState::Normal) const + { + const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000; + const auto storedStates = static_cast(m_propertyData & 0xFFFF); - void unsetValue(ComponentState state) - { - const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000; - m_propertyData &= ~(static_cast(1) << static_cast(state)); - m_globalValues.erase(baseIndex + static_cast(state)); + // If we don't have a value for any state then we can just return the default value + if (storedStates == 0) + return m_defaultValue; - MessageBroker::sendEvent(m_messageTopicId); - } + // If we only have a value for the Normal state then always use this value + if (storedStates == 1) + return m_globalValues.at(baseIndex); - void unsetValue() + if (static_cast(state) & static_cast(ComponentState::Disabled)) { - unsetValueImpl(); - MessageBroker::sendEvent(m_messageTopicId); + if ((static_cast(state) & static_cast(ComponentState::Active)) + && (storedStates & (1 << static_cast(ComponentState::DisabledActive)))) + return m_globalValues.at(baseIndex + static_cast(ComponentState::DisabledActive)); + if (storedStates & (1 << static_cast(ComponentState::Disabled))) + return m_globalValues.at(baseIndex + static_cast(ComponentState::Disabled)); } - [[nodiscard]] const ValueType& getValue(ComponentState state = ComponentState::Normal) const + if (static_cast(state) & static_cast(ComponentState::Active)) { - const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000; - const auto storedStates = static_cast(m_propertyData & 0xFFFF); - - // If we don't have a value for any state then we can just return the default value - if (storedStates == 0) - return m_defaultValue; - - // If we only have a value for the Normal state then always use this value - if (storedStates == 1) - return m_globalValues.at(baseIndex); - - if (static_cast(state) & static_cast(ComponentState::Disabled)) - { - if ((static_cast(state) & static_cast(ComponentState::Active)) - && (storedStates & (1 << static_cast(ComponentState::DisabledActive)))) - return m_globalValues.at(baseIndex + static_cast(ComponentState::DisabledActive)); - if (storedStates & (1 << static_cast(ComponentState::Disabled))) - return m_globalValues.at(baseIndex + static_cast(ComponentState::Disabled)); - } - - if (static_cast(state) & static_cast(ComponentState::Active)) - { - if (static_cast(state) & static_cast(ComponentState::Hover)) - { - if ((static_cast(state) & static_cast(ComponentState::Focused)) - && (storedStates & (1 << static_cast(ComponentState::FocusedActiveHover)))) - return m_globalValues.at(baseIndex + static_cast(ComponentState::FocusedActiveHover)); - if (storedStates & (1 << static_cast(ComponentState::ActiveHover))) - return m_globalValues.at(baseIndex + static_cast(ComponentState::ActiveHover)); - } - - if ((static_cast(state) & static_cast(ComponentState::Focused)) - && (storedStates & (1 << static_cast(ComponentState::FocusedActive)))) - return m_globalValues.at(baseIndex + static_cast(ComponentState::FocusedActive)); - if (storedStates & (1 << static_cast(ComponentState::Active))) - return m_globalValues.at(baseIndex + static_cast(ComponentState::Active)); - } - if (static_cast(state) & static_cast(ComponentState::Hover)) { if ((static_cast(state) & static_cast(ComponentState::Focused)) - && (storedStates & (1 << static_cast(ComponentState::FocusedHover)))) - return m_globalValues.at(baseIndex + static_cast(ComponentState::FocusedHover)); - if (storedStates & (1 << static_cast(ComponentState::Hover))) - return m_globalValues.at(baseIndex + static_cast(ComponentState::Hover)); - } - - if (static_cast(state) & static_cast(ComponentState::Focused)) - { - if (storedStates & (1 << static_cast(ComponentState::Focused))) - return m_globalValues.at(baseIndex + static_cast(ComponentState::Focused)); + && (storedStates & (1 << static_cast(ComponentState::FocusedActiveHover)))) + return m_globalValues.at(baseIndex + static_cast(ComponentState::FocusedActiveHover)); + if (storedStates & (1 << static_cast(ComponentState::ActiveHover))) + return m_globalValues.at(baseIndex + static_cast(ComponentState::ActiveHover)); } - if (storedStates & 1) - { - // We have a value for the Normal state, so return it. It is possible to pass here while storedStates != 1 when there - // is e.g. a value for both Normal and Disabled state and the widget is enabled. - return m_globalValues.at(baseIndex + static_cast(ComponentState::Normal)); - } - - // We don't have any relevant values, so return the default value. It is possible to - // pass here while storedStates > 0 when there is e.g. only a value for the Disabled - // state and the widget is enabled. - return m_defaultValue; + if ((static_cast(state) & static_cast(ComponentState::Focused)) + && (storedStates & (1 << static_cast(ComponentState::FocusedActive)))) + return m_globalValues.at(baseIndex + static_cast(ComponentState::FocusedActive)); + if (storedStates & (1 << static_cast(ComponentState::Active))) + return m_globalValues.at(baseIndex + static_cast(ComponentState::Active)); } - [[nodiscard]] std::uint64_t connectCallback(std::function func) + if (static_cast(state) & static_cast(ComponentState::Hover)) { - return MessageBroker::subscribe(m_messageTopicId, std::move(func)); + if ((static_cast(state) & static_cast(ComponentState::Focused)) + && (storedStates & (1 << static_cast(ComponentState::FocusedHover)))) + return m_globalValues.at(baseIndex + static_cast(ComponentState::FocusedHover)); + if (storedStates & (1 << static_cast(ComponentState::Hover))) + return m_globalValues.at(baseIndex + static_cast(ComponentState::Hover)); } - void disconnectCallback(std::uint64_t id) + if (static_cast(state) & static_cast(ComponentState::Focused)) { - MessageBroker::unsubscribe(id); + if (storedStates & (1 << static_cast(ComponentState::Focused))) + return m_globalValues.at(baseIndex + static_cast(ComponentState::Focused)); } - private: - void unsetValueImpl() + if (storedStates & 1) { - const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000; - const auto storedStates = static_cast(m_propertyData & 0xFFFF); + // We have a value for the Normal state, so return it. It is possible to pass here while storedStates != 1 when there + // is e.g. a value for both Normal and Disabled state and the widget is enabled. + return m_globalValues.at(baseIndex + static_cast(ComponentState::Normal)); + } + + // We don't have any relevant values, so return the default value. It is possible to + // pass here while storedStates > 0 when there is e.g. only a value for the Disabled + // state and the widget is enabled. + return m_defaultValue; + } + + [[nodiscard]] std::uint64_t connectCallback(std::function func) + { + return MessageBroker::subscribe(m_messageTopicId, std::move(func)); + } + + void disconnectCallback(std::uint64_t id) + { + MessageBroker::unsubscribe(id); + } - std::uint16_t total = 0; - std::uint8_t bitIndex = 0; - while (total < storedStates) + private: + void unsetValueImpl() + { + const std::uint64_t baseIndex = m_propertyData & 0xFFFFFFFFFFFF0000; + const auto storedStates = static_cast(m_propertyData & 0xFFFF); + + std::uint16_t total = 0; + std::uint8_t bitIndex = 0; + while (total < storedStates) + { + if (storedStates & (1 << bitIndex)) { - if (storedStates & (1 << bitIndex)) - { - m_globalValues.erase(baseIndex + bitIndex); - total += static_cast(1 << bitIndex); - } - ++bitIndex; + m_globalValues.erase(baseIndex + bitIndex); + total += static_cast(1 << bitIndex); } - - m_propertyData = baseIndex; // Forget about the states that were stored + ++bitIndex; } - private: - ValueType m_defaultValue; + m_propertyData = baseIndex; // Forget about the states that were stored + } - // The highest 48 bits store the index in a static map of values (see below). - // The next 16 bits are used to indicate the set of states that are present for this property. - std::uint64_t m_propertyData = 0; + private: + ValueType m_defaultValue; - // Index of the event that we publish to when the property changes. - std::uint64_t m_messageTopicId = 0; + // The highest 48 bits store the index in a static map of values (see below). + // The next 16 bits are used to indicate the set of states that are present for this property. + std::uint64_t m_propertyData = 0; - // All values are stored in a static map, which can be seen as a very large sparse list. - // Each instance holds a unique 48-bit id that can be seen as the high bits of the index in the list. - // The lowest 4 bits of the index contain the widget state. The remaining 12 bits inbetween are always 0. - ///static std::unordered_map m_globalValues; - ///static std::uint64_t m_nextGlobalValueIndex; + // Index of the event that we publish to when the property changes. + std::uint64_t m_messageTopicId = 0; - /// TODO: The system with global values caused way too many implementation and platform-specific problems. - /// For now we just store the values in the StyleProperty itself. - std::unordered_map m_globalValues; - }; + // All values are stored in a static map, which can be seen as a very large sparse list. + // Each instance holds a unique 48-bit id that can be seen as the high bits of the index in the list. + // The lowest 4 bits of the index contain the widget state. The remaining 12 bits inbetween are always 0. + ///static std::unordered_map m_globalValues; + ///static std::uint64_t m_nextGlobalValueIndex; - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// TODO: The system with global values caused way too many implementation and platform-specific problems. + /// For now we just store the values in the StyleProperty itself. + std::unordered_map m_globalValues; + }; - struct TGUI_API StylePropertyBackground - { - StyleProperty borderColor{Color::Black}; - StyleProperty color{Color::White}; - StyleProperty texture; - StyleProperty borders; - StyleProperty padding; + //////////////////////////////////////////////////////////////////////////////////////////////////////////// - float roundedBorderRadius = 0; - }; + struct TGUI_API StylePropertyBackground + { + StyleProperty borderColor{Color::Black}; + StyleProperty color{Color::White}; + StyleProperty texture; + StyleProperty borders; + StyleProperty padding; - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + float roundedBorderRadius = 0; + }; - struct TGUI_API StylePropertyText - { - StyleProperty color{Color::Black}; - StyleProperty style; - }; + //////////////////////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + struct TGUI_API StylePropertyText + { + StyleProperty color{Color::Black}; + StyleProperty style; + }; - class GroupComponent; + //////////////////////////////////////////////////////////////////////////////////////////////////////////// - class TGUI_API Component - { - public: - Component() = default; - virtual ~Component() = default; + class GroupComponent; - Component(const Component& other); - Component& operator=(const Component& other); + class TGUI_API Component + { + public: + Component() = default; + virtual ~Component() = default; - Component(Component&&) = default; - Component& operator=(Component&&) = default; + Component(const Component& other); + Component& operator=(const Component& other); - void setPosition(Vector2f position); + Component(Component&&) = default; + Component& operator=(Component&&) = default; - [[nodiscard]] Vector2f getPosition() const; + void setPosition(Vector2f position); - [[nodiscard]] Vector2f getSize() const; + [[nodiscard]] Vector2f getPosition() const; - void setPositionAlignment(PositionAlignment alignment); + [[nodiscard]] Vector2f getSize() const; - void setVisible(bool visible); + void setPositionAlignment(PositionAlignment alignment); - [[nodiscard]] bool isVisible() const; + void setVisible(bool visible); - void setParent(GroupComponent* parent); + [[nodiscard]] bool isVisible() const; - virtual void draw(BackendRenderTarget& target, RenderStates states) const = 0; + void setParent(GroupComponent* parent); - virtual void updateLayout(); + virtual void draw(BackendRenderTarget& target, RenderStates states) const = 0; - [[nodiscard]] virtual std::shared_ptr clone() const = 0; + virtual void updateLayout(); - protected: - friend void swap(Component& first, Component& second) noexcept; + [[nodiscard]] virtual std::shared_ptr clone() const = 0; - protected: - ComponentState m_state = ComponentState::Normal; - PositionAlignment m_positionAlignment = PositionAlignment::None; - Vector2f m_position; - Vector2f m_size; - bool m_visible = true; - float m_opacity = 1; - GroupComponent* m_parent = nullptr; - }; + protected: + friend void swap(Component& first, Component& second) noexcept; - class TGUI_API GroupComponent : public Component - { - public: - GroupComponent(const GroupComponent& other); - GroupComponent& operator=(const GroupComponent& other); + protected: + ComponentState m_state = ComponentState::Normal; + PositionAlignment m_positionAlignment = PositionAlignment::None; + Vector2f m_position; + Vector2f m_size; + bool m_visible = true; + float m_opacity = 1; + GroupComponent* m_parent = nullptr; + }; - GroupComponent(GroupComponent&&) = default; - GroupComponent& operator=(GroupComponent&&) = default; + class TGUI_API GroupComponent : public Component + { + public: + GroupComponent(const GroupComponent& other); + GroupComponent& operator=(const GroupComponent& other); - [[nodiscard]] Vector2f getClientSize() const; + GroupComponent(GroupComponent&&) = default; + GroupComponent& operator=(GroupComponent&&) = default; - void addComponent(const std::shared_ptr& component); + [[nodiscard]] Vector2f getClientSize() const; - [[nodiscard]] const std::vector>& getComponents() const; + void addComponent(const std::shared_ptr& component); - void draw(BackendRenderTarget& target, RenderStates states) const override; + [[nodiscard]] const std::vector>& getComponents() const; - void updateLayout() override; + void draw(BackendRenderTarget& target, RenderStates states) const override; - [[nodiscard]] std::shared_ptr clone() const override; + void updateLayout() override; - friend void swap(GroupComponent& first, GroupComponent& second) noexcept; + [[nodiscard]] std::shared_ptr clone() const override; - protected: - GroupComponent() = default; + friend void swap(GroupComponent& first, GroupComponent& second) noexcept; - protected: - std::vector> m_children; - Vector2f m_clientSize; - }; + protected: + GroupComponent() = default; - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + protected: + std::vector> m_children; + Vector2f m_clientSize; + }; - class TGUI_API BackgroundComponent : public GroupComponent - { - public: - explicit BackgroundComponent(StylePropertyBackground* backgroundStyle); + //////////////////////////////////////////////////////////////////////////////////////////////////////////// - ~BackgroundComponent() override; + class TGUI_API BackgroundComponent : public GroupComponent + { + public: + explicit BackgroundComponent(StylePropertyBackground* backgroundStyle); - BackgroundComponent(const BackgroundComponent& other, StylePropertyBackground* backgroundStyle = nullptr); - BackgroundComponent& operator=(const BackgroundComponent& other); + ~BackgroundComponent() override; - void init(); + BackgroundComponent(const BackgroundComponent& other, StylePropertyBackground* backgroundStyle = nullptr); + BackgroundComponent& operator=(const BackgroundComponent& other); - void setSize(Vector2f size); + void init(); - void setBorders(const Outline& border); + void setSize(Vector2f size); - [[nodiscard]] const Outline& getBorders() const; + void setBorders(const Outline& border); - void setPadding(const Outline& padding); + [[nodiscard]] const Outline& getBorders() const; - [[nodiscard]] const Outline& getPadding() const; + void setPadding(const Outline& padding); - void setOpacity(float opacity); + [[nodiscard]] const Outline& getPadding() const; - void setComponentState(ComponentState state); + void setOpacity(float opacity); - [[nodiscard]] bool isTransparentPixel(Vector2f pos, bool transparentTexture) const; + void setComponentState(ComponentState state); - void draw(BackendRenderTarget& target, RenderStates states) const override; + [[nodiscard]] bool isTransparentPixel(Vector2f pos, bool transparentTexture) const; - [[nodiscard]] Vector2f getSizeWithoutBorders() const; + void draw(BackendRenderTarget& target, RenderStates states) const override; - void updateLayout() override; + [[nodiscard]] Vector2f getSizeWithoutBorders() const; - [[nodiscard]] std::shared_ptr clone() const override; + void updateLayout() override; - private: - struct ColorRect - { - Color color; - FloatRect rect; - }; - - StylePropertyBackground* m_backgroundStyle; - - ColorRect m_background{Color::White, {}}; - Color m_borderColor = Color::Black; - Sprite m_sprite; - Outline m_borders; - Outline m_padding; - - std::uint64_t m_borderColorCallbackId = 0; - std::uint64_t m_backgroundColorCallbackId = 0; - std::uint64_t m_textureCallbackId = 0; - std::uint64_t m_bordersCallbackId = 0; - std::uint64_t m_paddingCallbackId = 0; - }; + [[nodiscard]] std::shared_ptr clone() const override; - //////////////////////////////////////////////////////////////////////////////////////////////////////////// - - class TGUI_API TextComponent : public Component + private: + struct ColorRect { - public: - explicit TextComponent(StylePropertyText* textStyle); + Color color; + FloatRect rect; + }; - ~TextComponent() override; + StylePropertyBackground* m_backgroundStyle; - TextComponent(const TextComponent& other, StylePropertyText* textStyle = nullptr); - TextComponent& operator=(const TextComponent& other); + ColorRect m_background{Color::White, {}}; + Color m_borderColor = Color::Black; + Sprite m_sprite; + Outline m_borders; + Outline m_padding; - void init(); + std::uint64_t m_borderColorCallbackId = 0; + std::uint64_t m_backgroundColorCallbackId = 0; + std::uint64_t m_textureCallbackId = 0; + std::uint64_t m_bordersCallbackId = 0; + std::uint64_t m_paddingCallbackId = 0; + }; - void setString(const String& caption); + //////////////////////////////////////////////////////////////////////////////////////////////////////////// - [[nodiscard]] const String& getString() const; + class TGUI_API TextComponent : public Component + { + public: + explicit TextComponent(StylePropertyText* textStyle); - void setCharacterSize(unsigned int size); + ~TextComponent() override; - [[nodiscard]] unsigned int getCharacterSize() const; + TextComponent(const TextComponent& other, StylePropertyText* textStyle = nullptr); + TextComponent& operator=(const TextComponent& other); - void setFont(const Font& font); + void init(); - [[nodiscard]] Font getFont() const; + void setString(const String& caption); - void setOutlineColor(Color color); + [[nodiscard]] const String& getString() const; - [[nodiscard]] Color getOutlineColor() const; + void setCharacterSize(unsigned int size); - void setOutlineThickness(float thickness); + [[nodiscard]] unsigned int getCharacterSize() const; - [[nodiscard]] float getOutlineThickness() const; + void setFont(const Font& font); - [[nodiscard]] float getLineHeight() const; + [[nodiscard]] Font getFont() const; - void setOpacity(float opacity); + void setOutlineColor(Color color); - void updateLayout() override; + [[nodiscard]] Color getOutlineColor() const; - void setComponentState(ComponentState state); + void setOutlineThickness(float thickness); - void draw(BackendRenderTarget& target, RenderStates states) const override; + [[nodiscard]] float getOutlineThickness() const; - [[nodiscard]] std::shared_ptr clone() const override; + [[nodiscard]] float getLineHeight() const; - private: - Text m_text; - StylePropertyText* m_textStyle; + void setOpacity(float opacity); - Color m_color = Color::Black; - TextStyles m_style = TextStyle::Regular; + void updateLayout() override; - std::uint64_t m_colorCallbackId = 0; - std::uint64_t m_styleCallbackId = 0; - }; + void setComponentState(ComponentState state); - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + void draw(BackendRenderTarget& target, RenderStates states) const override; - class TGUI_API ImageComponent : public Component - { - public: - explicit ImageComponent(StyleProperty* textureStyle); + [[nodiscard]] std::shared_ptr clone() const override; - ~ImageComponent() override; + private: + Text m_text; + StylePropertyText* m_textStyle; - ImageComponent(const ImageComponent& other, StyleProperty* textureStyle = nullptr); - ImageComponent& operator=(const ImageComponent& other); + Color m_color = Color::Black; + TextStyles m_style = TextStyle::Regular; - void init(); + std::uint64_t m_colorCallbackId = 0; + std::uint64_t m_styleCallbackId = 0; + }; - void setSize(Vector2f size); + //////////////////////////////////////////////////////////////////////////////////////////////////////////// - void setOpacity(float opacity); + class TGUI_API ImageComponent : public Component + { + public: + explicit ImageComponent(StyleProperty* textureStyle); - void setComponentState(ComponentState state); + ~ImageComponent() override; - [[nodiscard]] bool isTransparentPixel(Vector2f pos, bool transparentTexture) const; + ImageComponent(const ImageComponent& other, StyleProperty* textureStyle = nullptr); + ImageComponent& operator=(const ImageComponent& other); - void draw(BackendRenderTarget& target, RenderStates states) const override; + void init(); - [[nodiscard]] std::shared_ptr clone() const override; + void setSize(Vector2f size); - private: - StyleProperty* m_textureStyle; - Sprite m_sprite; + void setOpacity(float opacity); - std::uint64_t m_textureCallbackId = 0; - }; + void setComponentState(ComponentState state); - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + [[nodiscard]] bool isTransparentPixel(Vector2f pos, bool transparentTexture) const; - [[nodiscard]] inline ComponentState getStateFromFlags(bool hover, bool active, bool focused = false, bool enabled = true) - { - if (!enabled) - { - if (active) - return ComponentState::DisabledActive; + void draw(BackendRenderTarget& target, RenderStates states) const override; - return ComponentState::Disabled; - } + [[nodiscard]] std::shared_ptr clone() const override; - if (focused) - { - if (active) - { - if (hover) - return ComponentState::FocusedActiveHover; + private: + StyleProperty* m_textureStyle; + Sprite m_sprite; - return ComponentState::FocusedActive; - } + std::uint64_t m_textureCallbackId = 0; + }; - if (hover) - return ComponentState::FocusedHover; + //////////////////////////////////////////////////////////////////////////////////////////////////////////// - return ComponentState::Focused; - } + [[nodiscard]] inline ComponentState getStateFromFlags(bool hover, bool active, bool focused = false, bool enabled = true) + { + if (!enabled) + { + if (active) + return ComponentState::DisabledActive; + return ComponentState::Disabled; + } + + if (focused) + { if (active) { if (hover) - return ComponentState::ActiveHover; + return ComponentState::FocusedActiveHover; - return ComponentState::Active; + return ComponentState::FocusedActive; } if (hover) - return ComponentState::Hover; + return ComponentState::FocusedHover; - return ComponentState::Normal; + return ComponentState::Focused; } - //////////////////////////////////////////////////////////////////////////////////////////////////////////// - - inline void setOptionalPropertyValue(StyleProperty& property, const Color& color, ComponentState state) + if (active) { - if (color.isSet()) - property.setValue(color, state); - else - property.unsetValue(state); + if (hover) + return ComponentState::ActiveHover; + + return ComponentState::Active; } - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + if (hover) + return ComponentState::Hover; - inline void setOptionalPropertyValue(StyleProperty& property, const TextStyles& style, ComponentState state) - { - if (style.isSet()) - property.setValue(style, state); - else - property.unsetValue(state); - } + return ComponentState::Normal; + } - //////////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////////// - inline void setOptionalPropertyValue(StyleProperty& property, const Texture& texture, ComponentState state) - { - if (texture.getData()) - property.setValue(texture, state); - else - property.unsetValue(state); - } + inline void setOptionalPropertyValue(StyleProperty& property, const Color& color, ComponentState state) + { + if (color.isSet()) + property.setValue(color, state); + else + property.unsetValue(state); + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////////////////////////////////// - } // namespace dev - } // namespace priv + inline void setOptionalPropertyValue(StyleProperty& property, const TextStyles& style, ComponentState state) + { + if (style.isSet()) + property.setValue(style, state); + else + property.unsetValue(state); + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + + inline void setOptionalPropertyValue(StyleProperty& property, const Texture& texture, ComponentState state) + { + if (texture.getData()) + property.setValue(texture, state); + else + property.unsetValue(state); + } + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + } // namespace priv::dev } // namespace tgui #endif // TGUI_COMPONENTS_HPP diff --git a/include/TGUI/Keyboard.hpp b/include/TGUI/Keyboard.hpp index 0c1eeaf81..fc11d6c79 100644 --- a/include/TGUI/Keyboard.hpp +++ b/include/TGUI/Keyboard.hpp @@ -38,72 +38,68 @@ //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -namespace tgui +namespace tgui::keyboard { - namespace keyboard - { - //////////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef TGUI_REMOVE_DEPRECATED_CODE - TGUI_DEPRECATED("Use BackendGui::startTextInput instead") - inline void openVirtualKeyboard(const Widget* requestingWidget, FloatRect inputRect) - { - TGUI_ASSERT(requestingWidget != nullptr, "requestingWidget must not be nullptr"); - if (!requestingWidget) - return; + TGUI_DEPRECATED("Use BackendGui::startTextInput instead") + inline void openVirtualKeyboard(const Widget* requestingWidget, FloatRect inputRect) + { + TGUI_ASSERT(requestingWidget != nullptr, "requestingWidget must not be nullptr"); + if (!requestingWidget) + return; - const Widget* widget = requestingWidget; - while (widget) + const Widget* widget = requestingWidget; + while (widget) + { + const bool defaultOrigin = (widget->getOrigin().x == 0) && (widget->getOrigin().y == 0); + const bool scaledOrRotated = (widget->getScale().x != 1) || (widget->getScale().y != 1) || (widget->getRotation() != 0); + if (defaultOrigin && !scaledOrRotated) + inputRect.setPosition(inputRect.getPosition() + widget->getPosition()); + else { - const bool defaultOrigin = (widget->getOrigin().x == 0) && (widget->getOrigin().y == 0); - const bool scaledOrRotated = (widget->getScale().x != 1) || (widget->getScale().y != 1) - || (widget->getRotation() != 0); - if (defaultOrigin && !scaledOrRotated) - inputRect.setPosition(inputRect.getPosition() + widget->getPosition()); + const Vector2f origin{widget->getOrigin().x * widget->getSize().x, widget->getOrigin().y * widget->getSize().y}; + if (!scaledOrRotated) + inputRect.setPosition(inputRect.getPosition() + widget->getPosition() - origin); else { - const Vector2f origin{widget->getOrigin().x * widget->getSize().x, widget->getOrigin().y * widget->getSize().y}; - if (!scaledOrRotated) - inputRect.setPosition(inputRect.getPosition() + widget->getPosition() - origin); - else - { - const Vector2f rotOrigin{widget->getRotationOrigin().x * widget->getSize().x, - widget->getRotationOrigin().y * widget->getSize().y}; - const Vector2f scaleOrigin{widget->getScaleOrigin().x * widget->getSize().x, - widget->getScaleOrigin().y * widget->getSize().y}; - - Transform transform; - transform.translate(widget->getPosition() - origin); - transform.rotate(widget->getRotation(), rotOrigin); - transform.scale(widget->getScale(), scaleOrigin); - inputRect = transform.transformRect(inputRect); - } - } - - const Container* parent = widget->getParent(); - if (parent) - { - inputRect.setPosition(inputRect.getPosition() + parent->getChildWidgetsOffset()); - - const auto* panel = dynamic_cast(parent); - if (panel) - inputRect.setPosition(inputRect.getPosition() - panel->getContentOffset()); + const Vector2f rotOrigin{widget->getRotationOrigin().x * widget->getSize().x, + widget->getRotationOrigin().y * widget->getSize().y}; + const Vector2f scaleOrigin{widget->getScaleOrigin().x * widget->getSize().x, + widget->getScaleOrigin().y * widget->getSize().y}; + + Transform transform; + transform.translate(widget->getPosition() - origin); + transform.rotate(widget->getRotation(), rotOrigin); + transform.scale(widget->getScale(), scaleOrigin); + inputRect = transform.transformRect(inputRect); } - - widget = parent; } - const auto* gui = requestingWidget->getParentGui(); - if (gui) + const Container* parent = widget->getParent(); + if (parent) { - const Vector2f topLeftPos = gui->mapCoordsToPixel(inputRect.getPosition()); - const Vector2f bottomRightPos = gui->mapCoordsToPixel(inputRect.getPosition() + inputRect.getSize()); - inputRect = {topLeftPos, bottomRightPos - topLeftPos}; + inputRect.setPosition(inputRect.getPosition() + parent->getChildWidgetsOffset()); + + const auto* panel = dynamic_cast(parent); + if (panel) + inputRect.setPosition(inputRect.getPosition() - panel->getContentOffset()); } - TGUI_IGNORE_DEPRECATED_WARNINGS_START - getBackend()->openVirtualKeyboard(inputRect); - TGUI_IGNORE_DEPRECATED_WARNINGS_END + widget = parent; } + + const auto* gui = requestingWidget->getParentGui(); + if (gui) + { + const Vector2f topLeftPos = gui->mapCoordsToPixel(inputRect.getPosition()); + const Vector2f bottomRightPos = gui->mapCoordsToPixel(inputRect.getPosition() + inputRect.getSize()); + inputRect = {topLeftPos, bottomRightPos - topLeftPos}; + } + + TGUI_IGNORE_DEPRECATED_WARNINGS_START + getBackend()->openVirtualKeyboard(inputRect); + TGUI_IGNORE_DEPRECATED_WARNINGS_END + } #endif //////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -343,7 +339,6 @@ namespace tgui return (event.code == Event::KeyboardKey::Delete) && event.control && !event.alt && !event.system; #endif } - } // namespace keyboard -} // namespace tgui +} // namespace tgui::keyboard #endif // TGUI_KEYBOARD_HPP