aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/cru/common/base.hpp67
-rw-r--r--include/cru/common/bitmask.hpp42
-rw-r--r--include/cru/platform/native/basic_types.hpp16
-rw-r--r--include/cru/ui/base.hpp6
-rw-r--r--include/cru/ui/click_detector.hpp35
-rw-r--r--include/cru/ui/controls/button.hpp48
-rw-r--r--include/cru/ui/render/render_object.hpp2
-rw-r--r--include/cru/ui/render/window_render_object.hpp3
-rw-r--r--include/cru/ui/ui_event.hpp2
9 files changed, 86 insertions, 135 deletions
diff --git a/include/cru/common/base.hpp b/include/cru/common/base.hpp
index d4f164bf..4264142d 100644
--- a/include/cru/common/base.hpp
+++ b/include/cru/common/base.hpp
@@ -2,7 +2,6 @@
#include "pre_config.hpp"
#include <stdexcept>
-#include <type_traits>
#define CRU_UNUSED(entity) static_cast<void>(entity);
@@ -41,70 +40,4 @@ struct Interface {
[[noreturn]] inline void UnreachableCode() {
throw std::runtime_error("Unreachable code.");
}
-
} // namespace cru
-
-template <typename Enum>
-struct enable_bitmask_operators : std::false_type {};
-
-#define CRU_ENABLE_BITMASK_OPERATORS(enumname) \
- template <> \
- struct enable_bitmask_operators<enumname> : std::true_type {};
-
-template <typename Enum>
-auto operator|(Enum lhs, Enum rhs)
- -> std::enable_if_t<enable_bitmask_operators<Enum>::value, Enum> {
- using underlying = typename std::underlying_type<Enum>::type;
- return static_cast<Enum>(static_cast<underlying>(lhs) |
- static_cast<underlying>(rhs));
-}
-
-template <typename Enum>
-auto operator&(Enum lhs, Enum rhs)
- -> std::enable_if_t<enable_bitmask_operators<Enum>::value, Enum> {
- using underlying = typename std::underlying_type<Enum>::type;
- return static_cast<Enum>(static_cast<underlying>(lhs) &
- static_cast<underlying>(rhs));
-}
-
-template <typename Enum>
-auto operator^(Enum lhs, Enum rhs)
- -> std::enable_if_t<enable_bitmask_operators<Enum>::value, Enum> {
- using underlying = typename std::underlying_type<Enum>::type;
- return static_cast<Enum>(static_cast<underlying>(lhs) ^
- static_cast<underlying>(rhs));
-}
-
-template <typename Enum>
-auto operator~(Enum rhs)
- -> std::enable_if_t<enable_bitmask_operators<Enum>::value, Enum> {
- using underlying = typename std::underlying_type<Enum>::type;
- return static_cast<Enum>(~static_cast<underlying>(rhs));
-}
-
-template <typename Enum>
-auto operator|=(Enum& lhs, Enum rhs)
- -> std::enable_if_t<enable_bitmask_operators<Enum>::value, Enum&> {
- using underlying = typename std::underlying_type<Enum>::type;
- lhs = static_cast<Enum>(static_cast<underlying>(lhs) |
- static_cast<underlying>(rhs));
- return lhs;
-}
-
-template <typename Enum>
-auto operator&=(Enum& lhs, Enum rhs)
- -> std::enable_if_t<enable_bitmask_operators<Enum>::value, Enum&> {
- using underlying = typename std::underlying_type<Enum>::type;
- lhs = static_cast<Enum>(static_cast<underlying>(lhs) &
- static_cast<underlying>(rhs));
- return lhs;
-}
-
-template <typename Enum>
-auto operator^=(Enum& lhs, Enum rhs)
- -> std::enable_if_t<enable_bitmask_operators<Enum>::value, Enum&> {
- using underlying = typename std::underlying_type<Enum>::type;
- lhs = static_cast<Enum>(static_cast<underlying>(lhs) ^
- static_cast<underlying>(rhs));
- return lhs;
-}
diff --git a/include/cru/common/bitmask.hpp b/include/cru/common/bitmask.hpp
new file mode 100644
index 00000000..6dfb651c
--- /dev/null
+++ b/include/cru/common/bitmask.hpp
@@ -0,0 +1,42 @@
+#pragma once
+#include "base.hpp"
+
+namespace cru {
+template <typename Tag, typename TUnderlying = unsigned>
+struct Bitmask final {
+ using Underlying = TUnderlying;
+
+ constexpr Bitmask() : value(0) {}
+ constexpr explicit Bitmask(TUnderlying value) : value(value) {}
+
+ CRU_DEFAULT_COPY(Bitmask)
+ CRU_DEFAULT_MOVE(Bitmask)
+
+ ~Bitmask() = default;
+
+ Bitmask operator|(Bitmask rhs) const { return Bitmask(value | rhs.value); }
+ Bitmask operator&(Bitmask rhs) const { return Bitmask(value & rhs.value); }
+ Bitmask operator^(Bitmask rhs) const { return Bitmask(value ^ rhs.value); }
+ Bitmask operator~() const { return Bitmask(~value); }
+ Bitmask& operator|=(Bitmask rhs) {
+ value |= rhs;
+ return *this;
+ }
+ Bitmask& operator&=(Bitmask rhs) {
+ value &= rhs;
+ return *this;
+ }
+ Bitmask& operator^=(Bitmask rhs) {
+ value ^= rhs;
+ return *this;
+ }
+
+ bool operator==(Bitmask rhs) const { return this->value == rhs.value; }
+ bool operator!=(Bitmask rhs) const { return this->value != rhs.value; }
+
+ explicit operator TUnderlying() const { return value; }
+ explicit operator bool() const { return value != 0; }
+
+ TUnderlying value;
+};
+} // namespace cru
diff --git a/include/cru/platform/native/basic_types.hpp b/include/cru/platform/native/basic_types.hpp
index 247df06d..84cc61d1 100644
--- a/include/cru/platform/native/basic_types.hpp
+++ b/include/cru/platform/native/basic_types.hpp
@@ -1,5 +1,6 @@
#pragma once
#include "cru/common/base.hpp"
+#include "cru/common/bitmask.hpp"
namespace cru::platform::native {
struct Dpi {
@@ -7,7 +8,16 @@ struct Dpi {
float y;
};
-enum class MouseButton : unsigned { Left = 0b1, Right = 0b10, Middle = 0b100 };
-} // namespace cru::platform::native
+namespace details {
+struct TagMouseButton {};
+} // namespace details
+
+using MouseButton = Bitmask<details::TagMouseButton>;
-CRU_ENABLE_BITMASK_OPERATORS(::cru::platform::native::MouseButton)
+namespace mouse_buttons {
+constexpr MouseButton left{0b1};
+constexpr MouseButton middle{0b10};
+constexpr MouseButton right{0b100};
+} // namespace mouse_buttons
+
+} // namespace cru::platform::native
diff --git a/include/cru/ui/base.hpp b/include/cru/ui/base.hpp
index 581e6f8f..90a3f746 100644
--- a/include/cru/ui/base.hpp
+++ b/include/cru/ui/base.hpp
@@ -16,6 +16,12 @@ using cru::platform::TextRange;
using cru::platform::Thickness;
using cru::platform::native::MouseButton;
+namespace mouse_buttons {
+using cru::platform::native::mouse_buttons::left;
+using cru::platform::native::mouse_buttons::middle;
+using cru::platform::native::mouse_buttons::right;
+} // namespace mouse_buttons
+
namespace colors {
using cru::platform::colors::black;
using cru::platform::colors::skyblue;
diff --git a/include/cru/ui/click_detector.hpp b/include/cru/ui/click_detector.hpp
index d5e4ac78..9b59c717 100644
--- a/include/cru/ui/click_detector.hpp
+++ b/include/cru/ui/click_detector.hpp
@@ -49,7 +49,17 @@ class ClickDetector : public Object {
Control* GetControl() const { return control_; }
+ ClickState GetState() const { return state_; }
+
+ // Default is enable.
+ bool IsEnabled() const { return enable_; }
+ // If disable when user is pressing, the pressing is deactivated.
+ void SetEnabled(bool enable);
+
+ // Default is left and right.
MouseButton GetTriggerButton() const { return trigger_button_; }
+ // If unset the trigger button when user is pressing, the pressing is
+ // deactivated.
void SetTriggerButton(MouseButton trigger_button);
IEvent<ClickEventArgs>* ClickEvent() { return &event_; }
@@ -57,33 +67,22 @@ class ClickDetector : public Object {
IEvent<ClickState>* StateChangeEvent() { return &state_change_event_; }
private:
- std::optional<Point>& FromButton(MouseButton button) {
- switch (button) {
- case MouseButton::Left:
- return click_map_.left;
- case MouseButton::Middle:
- return click_map_.middle;
- case MouseButton::Right:
- return click_map_.right;
- default:
- UnreachableCode();
- }
- }
+ void SetState(ClickState state);
private:
Control* control_;
- MouseButton trigger_button_ = MouseButton::Left | MouseButton::Right;
+ ClickState state_;
+
+ bool enable_ = true;
+ MouseButton trigger_button_ = mouse_buttons::left | mouse_buttons::right;
Event<ClickEventArgs> event_;
Event<ClickState> state_change_event_;
std::vector<EventRevokerGuard> event_rovoker_guards_;
- struct {
- std::optional<Point> left = std::nullopt;
- std::optional<Point> middle = std::nullopt;
- std::optional<Point> right = std::nullopt;
- } click_map_;
+ Point down_point_;
+ MouseButton button_;
};
} // namespace cru::ui
diff --git a/include/cru/ui/controls/button.hpp b/include/cru/ui/controls/button.hpp
index 60b1243f..b24a9934 100644
--- a/include/cru/ui/controls/button.hpp
+++ b/include/cru/ui/controls/button.hpp
@@ -19,27 +19,16 @@ struct ButtonStateStyle {
};
struct ButtonStyle {
- // corresponds to ButtonState::Normal
+ // corresponds to ClickState::None
ButtonStateStyle normal;
- // corresponds to ButtonState::Hover
+ // corresponds to ClickState::Hover
ButtonStateStyle hover;
- // corresponds to ButtonState::Press
+ // corresponds to ClickState::Press
ButtonStateStyle press;
- // corresponds to ButtonState::PressCancel
+ // corresponds to ClickState::PressInactive
ButtonStateStyle press_cancel;
};
-enum class ButtonState {
- // mouse is not in it
- Normal,
- // mouse is in it and not pressed
- Hover,
- // mouse is pressed in it
- Press,
- // mouse is pressed outside button
- PressCancel,
-};
-
class Button : public ContentControl {
public:
static constexpr std::string_view control_type = "Button";
@@ -56,9 +45,7 @@ class Button : public ContentControl {
Button& operator=(Button&& other) = delete;
~Button() override = default;
- std::string_view GetControlType() const final {
- return control_type;
- }
+ std::string_view GetControlType() const final { return control_type; }
render::RenderObject* GetRenderObject() const override;
@@ -66,37 +53,12 @@ class Button : public ContentControl {
const ButtonStyle& GetStyle() const { return style_; }
void SetStyle(ButtonStyle style);
- ButtonState GetState() const { return state_; }
-
- // Get the trigger mouse button(s). Return value might be a union of Left,
- // Middle and Right.
- MouseButton GetTriggerButton() const { return trigger_button_; }
- // Set the trigger mouse button(s). You can set multiple buttons by passing a
- // union of Left, Middle and Right. If you disable a button when user is
- // pressing the same one, click will be stopped.
- // Default is only Left.
- void SetTriggerButton(MouseButton newTrigger);
-
protected:
void OnChildChanged(Control* old_child, Control* new_child) override;
- virtual void OnStateChange(ButtonState oldState, ButtonState newState);
-
- private:
- void SetState(ButtonState newState) {
- if (state_ == newState) return;
- const auto oldState = state_;
- state_ = newState;
- OnStateChange(oldState, newState);
- }
-
private:
std::unique_ptr<render::BorderRenderObject> render_object_{};
- ButtonState state_ = ButtonState::Normal;
-
- MouseButton trigger_button_ = MouseButton::Left;
-
ButtonStyle style_;
ClickDetector click_detector_;
diff --git a/include/cru/ui/render/render_object.hpp b/include/cru/ui/render/render_object.hpp
index 55b7f2da..3e351d34 100644
--- a/include/cru/ui/render/render_object.hpp
+++ b/include/cru/ui/render/render_object.hpp
@@ -117,6 +117,8 @@ class RenderObject : public Object {
private:
void SetParent(RenderObject* new_parent);
+ void SetRenderHostRecursive(IRenderHost* host);
+
private:
Control* control_ = nullptr;
IRenderHost* render_host_ = nullptr;
diff --git a/include/cru/ui/render/window_render_object.hpp b/include/cru/ui/render/window_render_object.hpp
index 8f35ad80..ae95b8ee 100644
--- a/include/cru/ui/render/window_render_object.hpp
+++ b/include/cru/ui/render/window_render_object.hpp
@@ -26,9 +26,6 @@ class WindowRenderObject : public RenderObject {
RenderObject* HitTest(const Point& point) override;
protected:
- void OnAddChild(RenderObject* new_child, int position) override;
- void OnRemoveChild(RenderObject* new_child, int position) override;
-
Size OnMeasureContent(const Size& available_size) override;
void OnLayoutContent(const Rect& content_rect) override;
diff --git a/include/cru/ui/ui_event.hpp b/include/cru/ui/ui_event.hpp
index c9ed1b80..147d3da6 100644
--- a/include/cru/ui/ui_event.hpp
+++ b/include/cru/ui/ui_event.hpp
@@ -100,7 +100,7 @@ class MouseButtonEventArgs : public MouseEventArgs {
MouseButtonEventArgs& operator=(MouseButtonEventArgs&& other) = default;
~MouseButtonEventArgs() override = default;
- MouseButton GetMouseButton() const { return button_; }
+ MouseButton GetButton() const { return button_; }
private:
MouseButton button_;