aboutsummaryrefslogtreecommitdiff
path: root/include/cru/ui/helper
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2020-11-08 17:45:41 +0800
committercrupest <crupest@outlook.com>2020-11-08 17:45:41 +0800
commit2188845a7acffa653015a1000139ec0a9a3984bc (patch)
tree7e8ed6eca5868a0943af6fcad6467115f369987c /include/cru/ui/helper
parent93265251d56c91b05f160423077ce95339786f87 (diff)
downloadcru-2188845a7acffa653015a1000139ec0a9a3984bc.tar.gz
cru-2188845a7acffa653015a1000139ec0a9a3984bc.tar.bz2
cru-2188845a7acffa653015a1000139ec0a9a3984bc.zip
...
Diffstat (limited to 'include/cru/ui/helper')
-rw-r--r--include/cru/ui/helper/ClickDetector.hpp87
-rw-r--r--include/cru/ui/helper/ShortcutHub.hpp129
2 files changed, 216 insertions, 0 deletions
diff --git a/include/cru/ui/helper/ClickDetector.hpp b/include/cru/ui/helper/ClickDetector.hpp
new file mode 100644
index 00000000..0df77c60
--- /dev/null
+++ b/include/cru/ui/helper/ClickDetector.hpp
@@ -0,0 +1,87 @@
+#pragma once
+#include "../controls/Control.hpp"
+
+namespace cru::ui::helper {
+class ClickEventArgs : Object {
+ public:
+ ClickEventArgs(controls::Control* sender, const Point& down_point,
+ const Point& up_point, MouseButton button)
+ : sender_(sender),
+ down_point_(down_point),
+ up_point_(up_point),
+ button_(button) {}
+
+ CRU_DEFAULT_COPY(ClickEventArgs)
+ CRU_DEFAULT_MOVE(ClickEventArgs)
+
+ ~ClickEventArgs() override = default;
+
+ controls::Control* GetSender() const { return sender_; }
+ Point GetDownPoint() const { return down_point_; }
+ Point GetUpPoint() const { return up_point_; }
+ MouseButton GetButton() const { return button_; }
+
+ private:
+ controls::Control* sender_;
+ Point down_point_;
+ Point up_point_;
+ MouseButton button_;
+};
+
+enum class ClickState {
+ None, // Mouse is outside the control.
+ Hover, // Mouse hovers on the control but not pressed
+ Press, // Mouse is pressed and if released click is done.
+ PressInactive // Mouse is pressed but if released click is canceled.
+};
+
+class ClickDetector : public Object {
+ CRU_DEFINE_CLASS_LOG_TAG(u"cru::ui::ClickDetector")
+
+ public:
+ explicit ClickDetector(controls::Control* control);
+
+ CRU_DELETE_COPY(ClickDetector)
+ CRU_DELETE_MOVE(ClickDetector)
+
+ ~ClickDetector() override = default;
+
+ controls::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_; }
+
+ IEvent<ClickState>* StateChangeEvent() { return &state_change_event_; }
+
+ private:
+ void SetState(ClickState state);
+
+ private:
+ controls::Control* control_;
+
+ 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_;
+
+ Point down_point_;
+ MouseButton button_;
+};
+} // namespace cru::ui::helper
diff --git a/include/cru/ui/helper/ShortcutHub.hpp b/include/cru/ui/helper/ShortcutHub.hpp
new file mode 100644
index 00000000..a4ff2da2
--- /dev/null
+++ b/include/cru/ui/helper/ShortcutHub.hpp
@@ -0,0 +1,129 @@
+#pragma once
+#include "../Base.hpp"
+
+#include "../events/UiEvent.hpp"
+#include "cru/common/Event.hpp"
+#include "cru/platform/gui/Keyboard.hpp"
+
+#include <cstddef>
+#include <functional>
+#include <memory>
+#include <optional>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <unordered_map>
+#include <vector>
+
+namespace cru::ui::helper {
+
+class ShortcutKeyBind {
+ public:
+ ShortcutKeyBind(platform::gui::KeyCode key,
+ platform::gui::KeyModifier modifier)
+ : key_(key), modifier_(modifier) {}
+
+ CRU_DEFAULT_COPY(ShortcutKeyBind)
+ CRU_DEFAULT_MOVE(ShortcutKeyBind)
+
+ ~ShortcutKeyBind() = default;
+
+ platform::gui::KeyCode GetKey() const { return key_; }
+ platform::gui::KeyModifier GetModifier() const { return modifier_; }
+
+ bool Is(platform::gui::KeyCode key,
+ platform::gui::KeyModifier modifier) const {
+ return key == key_ && modifier == modifier_;
+ }
+
+ bool operator==(const ShortcutKeyBind& other) const {
+ return this->key_ == other.key_ && this->modifier_ == other.modifier_;
+ }
+
+ bool operator!=(const ShortcutKeyBind& other) const {
+ return !this->operator==(other);
+ }
+
+ std::u16string ToString() {
+ std::u16string result = u"(";
+ result += platform::gui::ToString(modifier_);
+ result += u")";
+ result += platform::gui::ToString(key_);
+ return result;
+ }
+
+ private:
+ platform::gui::KeyCode key_;
+ platform::gui::KeyModifier modifier_;
+};
+} // namespace cru::ui::helper
+
+namespace std {
+template <>
+struct hash<cru::ui::helper::ShortcutKeyBind> {
+ std::size_t operator()(const cru::ui::helper::ShortcutKeyBind& value) const {
+ std::size_t result = 0;
+ cru::hash_combine(result, static_cast<int>(value.GetKey()));
+ cru::hash_combine(result, static_cast<int>(value.GetModifier()));
+ return result;
+ }
+};
+} // namespace std
+
+namespace cru::ui::helper {
+struct Shortcut {
+ // Just for debug.
+ std::u16string name;
+ ShortcutKeyBind key_bind;
+ // Return true if it consumes the shortcut. Or return false if it does not
+ // handle the shortcut.
+ std::function<bool()> handler;
+};
+
+struct ShortcutInfo {
+ int id;
+ std::u16string name;
+ ShortcutKeyBind key_bind;
+ std::function<bool()> handler;
+};
+
+class ShortcutHub : public Object {
+ public:
+ ShortcutHub() = default;
+
+ CRU_DELETE_COPY(ShortcutHub)
+ CRU_DELETE_MOVE(ShortcutHub)
+
+ ~ShortcutHub() override = default;
+
+ int RegisterShortcut(std::u16string name, ShortcutKeyBind bind,
+ std::function<bool()> handler) {
+ return RegisterShortcut({std::move(name), bind, std::move(handler)});
+ }
+
+ // Return an id used for unregistering.
+ int RegisterShortcut(Shortcut shortcut);
+
+ void UnregisterShortcut(int id);
+
+ std::vector<ShortcutInfo> GetAllShortcuts() const;
+ std::optional<ShortcutInfo> GetShortcut(int id) const;
+ const std::vector<ShortcutInfo>& GetShortcutByKeyBind(
+ const ShortcutKeyBind& key_bind) const;
+
+ void Install(controls::Control* control);
+ void Uninstall();
+
+ private:
+ void OnKeyDown(event::KeyEventArgs& event);
+
+ private:
+ std::unordered_map<ShortcutKeyBind, std::vector<ShortcutInfo>> map_;
+
+ const std::vector<ShortcutInfo> empty_list_;
+
+ int current_id_ = 1;
+
+ EventRevokerListGuard event_guard_;
+};
+} // namespace cru::ui::helper