diff options
46 files changed, 336 insertions, 179 deletions
diff --git a/demos/CMakeLists.txt b/demos/CMakeLists.txt index f3b4afde..17a8fbed 100644 --- a/demos/CMakeLists.txt +++ b/demos/CMakeLists.txt @@ -1,8 +1,6 @@ add_library(cru_demo_base INTERFACE) -if(WIN32) - target_link_libraries(cru_demo_base INTERFACE cru_win_gui) -endif() +target_link_libraries(cru_demo_base INTERFACE cru_platform_boostrap) if(WIN32) # Currently only enable tests on Windows. add_subdirectory(main) diff --git a/demos/input_method/main.cpp b/demos/input_method/main.cpp index 5a6dc942..b509cd97 100644 --- a/demos/input_method/main.cpp +++ b/demos/input_method/main.cpp @@ -1,3 +1,4 @@ +#include "cru/platform/bootstrap/Bootstrap.hpp" #include "cru/platform/graphics/Factory.hpp" #include "cru/platform/graphics/Font.hpp" #include "cru/platform/graphics/Painter.hpp" @@ -10,7 +11,7 @@ int main() { using namespace cru::platform::graphics; using namespace cru::platform::gui; - auto application = CreateUiApplication(); + IUiApplication* application = boostrap::CreateUiApplication(); auto graph_factory = application->GetGraphFactory(); diff --git a/demos/main/main.cpp b/demos/main/main.cpp index 541a2320..af2625a9 100644 --- a/demos/main/main.cpp +++ b/demos/main/main.cpp @@ -1,4 +1,5 @@ #include "cru/platform/HeapDebug.hpp" +#include "cru/platform/bootstrap/Bootstrap.hpp" #include "cru/platform/gui/UiApplication.hpp" #include "cru/platform/gui/Window.hpp" #include "cru/ui/Base.hpp" @@ -9,7 +10,7 @@ #include "cru/ui/controls/Window.hpp" #include "cru/ui/host/WindowHost.hpp" -using cru::platform::gui::CreateUiApplication; +using cru::platform::gui::IUiApplication; using cru::ui::controls::Button; using cru::ui::controls::FlexLayout; using cru::ui::controls::TextBlock; @@ -21,7 +22,7 @@ int main() { cru::platform::SetupHeapDebug(); #endif - auto application = CreateUiApplication(); + IUiApplication* application = cru::platform::boostrap::CreateUiApplication(); const auto window = Window::Create(); diff --git a/demos/scroll_view/main.cpp b/demos/scroll_view/main.cpp index f6b29934..2d65f68f 100644 --- a/demos/scroll_view/main.cpp +++ b/demos/scroll_view/main.cpp @@ -1,14 +1,16 @@ +#include "cru/platform/bootstrap/Bootstrap.hpp" #include "cru/platform/gui/UiApplication.hpp" #include "cru/ui/controls/ScrollView.hpp" #include "cru/ui/controls/TextBlock.hpp" #include "cru/ui/controls/Window.hpp" +using cru::platform::gui::IUiApplication; using cru::ui::controls::ScrollView; using cru::ui::controls::TextBlock; using cru::ui::controls::Window; int main() { - auto application = cru::platform::gui::CreateUiApplication(); + IUiApplication* application = cru::platform::boostrap::CreateUiApplication(); auto window = Window::Create(); diff --git a/include/cru/common/Base.hpp b/include/cru/common/Base.hpp index 93b0008c..5ed1e763 100644 --- a/include/cru/common/Base.hpp +++ b/include/cru/common/Base.hpp @@ -36,6 +36,12 @@ classname(classname&&) = delete; \ classname& operator=(classname&&) = delete; +#define CRU_DEFAULT_DESTRUCTOR(classname) ~classname() override = default; + +#define CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(classname) \ + classname() = default; \ + ~classname() override = default; + namespace cru { class CRU_BASE_API Object { public: @@ -66,21 +72,4 @@ inline void hash_combine(std::size_t& s, const T& v) { #define CRU_DEFINE_CLASS_LOG_TAG(tag) \ private: \ constexpr static std::u16string_view log_tag = tag; - -class CRU_BASE_API Exception { - public: - Exception() = default; - Exception(std::u16string message) : message_(std::move(message)) {} - - CRU_DEFAULT_COPY(Exception) - CRU_DEFAULT_MOVE(Exception) - - virtual ~Exception() = default; - - public: - std::u16string GetMessage() const { return message_; } - - private: - std::u16string message_; -}; } // namespace cru diff --git a/include/cru/common/Exception.hpp b/include/cru/common/Exception.hpp new file mode 100644 index 00000000..861bf5e9 --- /dev/null +++ b/include/cru/common/Exception.hpp @@ -0,0 +1,21 @@ +#pragma once +#include "String.hpp" + +namespace cru { +class CRU_BASE_API Exception { + public: + Exception() = default; + Exception(String message) : message_(std::move(message)) {} + + CRU_DEFAULT_COPY(Exception) + CRU_DEFAULT_MOVE(Exception) + + virtual ~Exception() = default; + + public: + String GetMessage() const { return message_; } + + private: + String message_; +}; +} // namespace cru diff --git a/include/cru/common/String.hpp b/include/cru/common/String.hpp index ea9480f0..e779e3a6 100644 --- a/include/cru/common/String.hpp +++ b/include/cru/common/String.hpp @@ -9,21 +9,24 @@ namespace cru { class CRU_BASE_API String { public: - static String fromUtf8(const char* str, Index size); + static String FromUtf8(std::string_view str) { + return FromUtf8(str.data(), str.size()); + } + static String FromUtf8(const char* str, Index size); - static String fromUtf16(const std::uint16_t* str) { return String(str); } - static String fromUtf16(const std::uint16_t* str, Index size) { + static String FromUtf16(const std::uint16_t* str) { return String(str); } + static String FromUtf16(const std::uint16_t* str, Index size) { return String(str, size); } - static String fromUtf16(const char16_t* str) { return String(str); } - static String fromUtf16(const char16_t* str, Index size) { + static String FromUtf16(const char16_t* str) { return String(str); } + static String FromUtf16(const char16_t* str, Index size) { return String(str, size); } #ifdef CRU_PLATFORM_WINDOWS - static String fromUtf16(wchar_t* str) { return String(str); } - static String fromUtf16(wchar_t* str, Index size) { + static String FromUtf16(wchar_t* str) { return String(str); } + static String FromUtf16(wchar_t* str, Index size) { return String(str, size); } #endif @@ -49,10 +52,12 @@ class CRU_BASE_API String { String(const char16_t* str); String(const char16_t* str, Index size); + String(const std::u16string& str) : String(str.data(), str.size()) {} #ifdef CRU_PLATFORM_WINDOWS String(const wchar_t* str); String(const wchar_t* str, Index size); + String(const std::wstring& str) : String(str.data(), str.size()) {} #endif String(const String& other); @@ -121,6 +126,19 @@ class CRU_BASE_API String { this->insert(cend(), str, size); } + public: + const char16_t* Char16CStr() const { + return reinterpret_cast<const char16_t*>(c_str()); + } + +#ifdef CRU_PLATFORM_WINDOWS + const wchar_t* WinCStr() const { + return reinterpret_cast<const wchar_t*>(c_str()); + } +#endif + + std::string ToUtf8() const; + private: static std::uint16_t kEmptyBuffer[1]; diff --git a/include/cru/common/StringUtil.hpp b/include/cru/common/StringUtil.hpp index 481566a6..985f0032 100644 --- a/include/cru/common/StringUtil.hpp +++ b/include/cru/common/StringUtil.hpp @@ -1,5 +1,6 @@ #pragma once #include "Base.hpp" +#include "Exception.hpp" #include <functional> #include <string> diff --git a/include/cru/platform/Base.hpp b/include/cru/platform/Base.hpp new file mode 100644 index 00000000..8589e6cb --- /dev/null +++ b/include/cru/platform/Base.hpp @@ -0,0 +1,11 @@ +#pragma once + +#ifdef CRU_PLATFORM_WINDOWS +#ifdef CRU_PLATFORM_EXPORT_API +#define CRU_PLATFORM_API __declspec(dllexport) +#else +#define CRU_PLATFORM_API __declspec(dllimport) +#endif +#else +#define CRU_PLATFORM_API +#endif diff --git a/include/cru/platform/Check.hpp b/include/cru/platform/Check.hpp index d3180582..9ecd2d1d 100644 --- a/include/cru/platform/Check.hpp +++ b/include/cru/platform/Check.hpp @@ -10,32 +10,31 @@ namespace cru::platform { template <typename TTarget> -TTarget* CheckPlatform(INativeResource* resource, - const std::u16string_view& target_platform) { +TTarget* CheckPlatform(IPlatformResource* resource, + const String& target_platform) { Expects(resource); const auto result = dynamic_cast<TTarget*>(resource); if (result == nullptr) { - throw UnsupportPlatformException(fmt::format( + throw UnsupportPlatformException(String::FromUtf8(fmt::format( "Try to convert resource to target platform failed. Platform id of " "resource to convert: {} . Target platform id: {} .", - ToUtf8(resource->GetPlatformId()), ToUtf8(target_platform))); + resource->GetPlatformId().ToUtf8(), target_platform.ToUtf8()))); } return result; } template <typename TTarget, typename TSource> -std::shared_ptr<TTarget> CheckPlatform( - const std::shared_ptr<TSource>& resource, - const std::u16string_view& target_platform) { - static_assert(std::is_base_of_v<INativeResource, TSource>, +std::shared_ptr<TTarget> CheckPlatform(const std::shared_ptr<TSource>& resource, + const String& target_platform) { + static_assert(std::is_base_of_v<IPlatformResource, TSource>, "TSource must be a subclass of INativeResource."); Expects(resource); const auto result = std::dynamic_pointer_cast<TTarget>(resource); if (result == nullptr) { - throw UnsupportPlatformException(fmt::format( + throw UnsupportPlatformException(String::FromUtf8(fmt::format( "Try to convert resource to target platform failed. Platform id of " "resource to convert: {} . Target platform id: {} .", - ToUtf8(resource->GetPlatformId()), ToUtf8(target_platform))); + resource->GetPlatformId().ToUtf8(), target_platform.ToUtf8()))); } return result; } diff --git a/include/cru/platform/Color.hpp b/include/cru/platform/Color.hpp index 530695b2..a6793269 100644 --- a/include/cru/platform/Color.hpp +++ b/include/cru/platform/Color.hpp @@ -1,5 +1,7 @@ #pragma once -#include "boost/functional/hash.hpp" +#include "cru/platform/Base.hpp" + +#include <boost/functional/hash.hpp> #include <cstdint> #include <optional> @@ -7,7 +9,7 @@ #include <unordered_map> namespace cru::platform { -struct Color { +struct CRU_PLATFORM_API Color { constexpr Color() : Color(0, 0, 0, 255) {} constexpr Color(std::uint8_t red, std::uint8_t green, std::uint8_t blue, std::uint8_t alpha = 255) diff --git a/include/cru/platform/Exception.hpp b/include/cru/platform/Exception.hpp index 8b958a1d..379753d4 100644 --- a/include/cru/platform/Exception.hpp +++ b/include/cru/platform/Exception.hpp @@ -1,28 +1,43 @@ #pragma once +#include "Base.hpp" #include "cru/common/Base.hpp" - -#include <stdexcept> +#include "cru/common/Exception.hpp" namespace cru::platform { -class PlatformException : public std::runtime_error { +class CRU_PLATFORM_API PlatformException : public Exception { public: - using runtime_error::runtime_error; // inherit constructors + using Exception::Exception; // inherit constructors + + CRU_DEFAULT_COPY(PlatformException) + CRU_DEFAULT_MOVE(PlatformException) + + CRU_DEFAULT_DESTRUCTOR(PlatformException) }; // This exception is thrown when a resource is used on another platform. // Of course, you can't mix resources of two different platform. // For example, Win32 Brush (may add in the future) with Direct Painter. -class UnsupportPlatformException : public std::runtime_error { +class CRU_PLATFORM_API UnsupportPlatformException : public Exception { public: - using runtime_error::runtime_error; // inherit constructors + using Exception::Exception; // inherit constructors + + CRU_DEFAULT_COPY(UnsupportPlatformException) + CRU_DEFAULT_MOVE(UnsupportPlatformException) + + CRU_DEFAULT_DESTRUCTOR(UnsupportPlatformException) }; // This exception is thrown when a resource has been disposed and not usable // again. // For example, calling Build twice on a GeometryBuilder::Build will lead to // this exception. -class ReuseException : public std::runtime_error { +class CRU_PLATFORM_API ReuseException : public Exception { public: - using runtime_error::runtime_error; // inherit constructors + using Exception::Exception; // inherit constructors + + CRU_DEFAULT_COPY(ReuseException) + CRU_DEFAULT_MOVE(ReuseException) + + CRU_DEFAULT_DESTRUCTOR(ReuseException) }; } // namespace cru::platform diff --git a/include/cru/platform/Resource.hpp b/include/cru/platform/Resource.hpp index 7a85d9c1..b55da43a 100644 --- a/include/cru/platform/Resource.hpp +++ b/include/cru/platform/Resource.hpp @@ -1,10 +1,15 @@ #pragma once +#include "Base.hpp" + #include "cru/common/Base.hpp" +#include "cru/common/String.hpp" #include <string_view> namespace cru::platform { -struct INativeResource : virtual Interface { - virtual std::u16string_view GetPlatformId() const = 0; +struct CRU_PLATFORM_API IPlatformResource : virtual Interface { + CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(IPlatformResource) + + virtual String GetPlatformId() const = 0; }; } // namespace cru::platform diff --git a/include/cru/platform/bootstrap/Bootstrap.hpp b/include/cru/platform/bootstrap/Bootstrap.hpp new file mode 100644 index 00000000..730df28c --- /dev/null +++ b/include/cru/platform/bootstrap/Bootstrap.hpp @@ -0,0 +1,17 @@ +#pragma once +#include "cru/platform/gui/UiApplication.hpp" + +#ifdef CRU_PLATFORM_WINDOWS +#ifdef CRU_PLATFORM_BOOTSTRAP_EXPORT_API +#define CRU_PLATFORM_BOOTSTRAP_API __declspec(dllexport) +#else +#define CRU_PLATFORM_BOOTSTRAP_API __declspec(dllimport) +#endif +#else +#define CRU_PLATFORM_BOOTSTRAP_API +#endif + +namespace cru::platform::boostrap { +CRU_PLATFORM_BOOTSTRAP_API cru::platform::gui::IUiApplication* +CreateUiApplication(); +} diff --git a/include/cru/platform/graphics/Base.hpp b/include/cru/platform/graphics/Base.hpp index e751ebdb..25881772 100644 --- a/include/cru/platform/graphics/Base.hpp +++ b/include/cru/platform/graphics/Base.hpp @@ -21,4 +21,4 @@ struct TextHitTestResult { bool trailing; bool insideText; }; -} // namespace cru::platform::graph +} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Brush.hpp b/include/cru/platform/graphics/Brush.hpp index 10c666b5..18d9705e 100644 --- a/include/cru/platform/graphics/Brush.hpp +++ b/include/cru/platform/graphics/Brush.hpp @@ -8,4 +8,4 @@ struct ISolidColorBrush : virtual IBrush { virtual Color GetColor() = 0; virtual void SetColor(const Color& color) = 0; }; -} // namespace cru::platform::graph +} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Factory.hpp b/include/cru/platform/graphics/Factory.hpp index f9018e13..4ee10204 100644 --- a/include/cru/platform/graphics/Factory.hpp +++ b/include/cru/platform/graphics/Factory.hpp @@ -11,7 +11,7 @@ namespace cru::platform::graphics { // Entry point of the graph module. -struct IGraphFactory : virtual INativeResource { +struct IGraphFactory : virtual IPlatformResource { virtual std::unique_ptr<ISolidColorBrush> CreateSolidColorBrush() = 0; virtual std::unique_ptr<IGeometryBuilder> CreateGeometryBuilder() = 0; diff --git a/include/cru/platform/graphics/Font.hpp b/include/cru/platform/graphics/Font.hpp index 70392a69..c8a155fc 100644 --- a/include/cru/platform/graphics/Font.hpp +++ b/include/cru/platform/graphics/Font.hpp @@ -5,4 +5,4 @@ namespace cru::platform::graphics { struct IFont : virtual IGraphResource { virtual float GetFontSize() = 0; }; -} // namespace cru::platform::graph +} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Geometry.hpp b/include/cru/platform/graphics/Geometry.hpp index b0ce6ad9..cc8f8761 100644 --- a/include/cru/platform/graphics/Geometry.hpp +++ b/include/cru/platform/graphics/Geometry.hpp @@ -17,4 +17,4 @@ struct IGeometryBuilder : virtual IGraphResource { virtual std::unique_ptr<IGeometry> Build() = 0; }; -} // namespace cru::platform::graph +} // namespace cru::platform::graphics diff --git a/include/cru/platform/graphics/Painter.hpp b/include/cru/platform/graphics/Painter.hpp index f75ea52b..24592f95 100644 --- a/include/cru/platform/graphics/Painter.hpp +++ b/include/cru/platform/graphics/Painter.hpp @@ -3,7 +3,7 @@ namespace cru::platform::graphics { -struct IPainter : virtual INativeResource { +struct IPainter : virtual IPlatformResource { virtual Matrix GetTransform() = 0; virtual void SetTransform(const Matrix& matrix) = 0; diff --git a/include/cru/platform/graphics/Resource.hpp b/include/cru/platform/graphics/Resource.hpp index a1625ce4..212e5b18 100644 --- a/include/cru/platform/graphics/Resource.hpp +++ b/include/cru/platform/graphics/Resource.hpp @@ -4,7 +4,7 @@ namespace cru::platform::graphics { struct IGraphFactory; -struct IGraphResource : virtual INativeResource { +struct IGraphResource : virtual IPlatformResource { virtual IGraphFactory* GetGraphFactory() = 0; }; -} // namespace cru::platform::graph +} // namespace cru::platform::graphics diff --git a/include/cru/platform/gui/Base.hpp b/include/cru/platform/gui/Base.hpp index fd9d265c..4c2a8034 100644 --- a/include/cru/platform/gui/Base.hpp +++ b/include/cru/platform/gui/Base.hpp @@ -1,11 +1,20 @@ #pragma once -#include "Keyboard.hpp" #include "cru/common/Base.hpp" #include "cru/common/Bitmask.hpp" #include "cru/platform/graphics/Base.hpp" #include "../Resource.hpp" +#ifdef CRU_PLATFORM_WINDOWS +#ifdef CRU_PLATFORM_GUI_EXPORT_API +#define CRU_PLATFORM_GUI_API __declspec(dllexport) +#else +#define CRU_PLATFORM_GUI_API __declspec(dllimport) +#endif +#else +#define CRU_PLATFORM_GUI_API +#endif + namespace cru::platform::gui { struct ICursor; struct ICursorManager; @@ -24,26 +33,4 @@ constexpr MouseButton left{0b1}; constexpr MouseButton middle{0b10}; constexpr MouseButton right{0b100}; } // namespace mouse_buttons - -struct NativeMouseButtonEventArgs { - MouseButton button; - Point point; - KeyModifier modifier; -}; - -struct NativeMouseWheelEventArgs { - // Positive means down. Negative means up. - float delta; - Point point; - KeyModifier modifier; -}; - -struct NativeKeyEventArgs { - KeyCode key; - KeyModifier modifier; -}; - -enum class FocusChangeType { Gain, Lost }; - -enum class MouseEnterLeaveType { Enter, Leave }; } // namespace cru::platform::gui diff --git a/include/cru/platform/gui/Cursor.hpp b/include/cru/platform/gui/Cursor.hpp index 316496a0..abc8b064 100644 --- a/include/cru/platform/gui/Cursor.hpp +++ b/include/cru/platform/gui/Cursor.hpp @@ -6,9 +6,9 @@ namespace cru::platform::gui { enum class SystemCursorType { Arrow, Hand, IBeam }; -struct ICursor : virtual INativeResource {}; +struct ICursor : virtual IPlatformResource {}; -struct ICursorManager : virtual INativeResource { +struct ICursorManager : virtual IPlatformResource { virtual std::shared_ptr<ICursor> GetSystemCursor(SystemCursorType type) = 0; // TODO: Add method to create cursor. diff --git a/include/cru/platform/gui/InputMethod.hpp b/include/cru/platform/gui/InputMethod.hpp index 9d090eab..9b07959c 100644 --- a/include/cru/platform/gui/InputMethod.hpp +++ b/include/cru/platform/gui/InputMethod.hpp @@ -22,7 +22,7 @@ struct CompositionText { TextRange selection; }; -struct IInputMethodContext : virtual INativeResource { +struct IInputMethodContext : virtual IPlatformResource { // Return true if you should draw composition text manually. Return false if // system will take care of that for you. virtual bool ShouldManuallyDrawCompositionText() = 0; diff --git a/include/cru/platform/gui/Keyboard.hpp b/include/cru/platform/gui/Keyboard.hpp index 6c29239b..b93b44fa 100644 --- a/include/cru/platform/gui/Keyboard.hpp +++ b/include/cru/platform/gui/Keyboard.hpp @@ -1,5 +1,6 @@ #pragma once #include "cru/common/Bitmask.hpp" +#include "cru/platform/gui/Base.hpp" #include <string> #include <string_view> @@ -122,7 +123,7 @@ struct KeyModifiers { static constexpr KeyModifier alt{0b100}; }; -std::u16string_view ToString(KeyCode key_code); -std::u16string ToString(KeyModifier key_modifier, - std::u16string_view separator = u"+"); +CRU_PLATFORM_GUI_API std::u16string_view ToString(KeyCode key_code); +CRU_PLATFORM_GUI_API std::u16string ToString( + KeyModifier key_modifier, std::u16string_view separator = u"+"); } // namespace cru::platform::gui diff --git a/include/cru/platform/gui/TimerHelper.hpp b/include/cru/platform/gui/TimerHelper.hpp new file mode 100644 index 00000000..a61d2f04 --- /dev/null +++ b/include/cru/platform/gui/TimerHelper.hpp @@ -0,0 +1,69 @@ +#pragma once +#include "UiApplication.hpp" + +namespace cru::platform::gui { + +class TimerAutoCanceler { + public: + TimerAutoCanceler() : id_(0) {} + explicit TimerAutoCanceler(long long id) : id_(id) {} + + CRU_DELETE_COPY(TimerAutoCanceler) + + TimerAutoCanceler(TimerAutoCanceler&& other) : id_(other.id_) { + other.id_ = 0; + } + + TimerAutoCanceler& operator=(TimerAutoCanceler&& other) { + if (&other == this) { + return *this; + } + Reset(other.id_); + other.id_ = 0; + return *this; + } + + TimerAutoCanceler& operator=(long long other) { + return this->operator=(TimerAutoCanceler(other)); + } + + ~TimerAutoCanceler() { Reset(); } + + long long Release() { + auto temp = id_; + id_ = 0; + return temp; + } + + void Reset(long long id = 0) { + if (id_ > 0) IUiApplication::GetInstance()->CancelTimer(id_); + id_ = id; + } + + explicit operator bool() const { return id_; } + + private: + long long id_; +}; + +class TimerListAutoCanceler { + public: + TimerListAutoCanceler() = default; + CRU_DELETE_COPY(TimerListAutoCanceler) + CRU_DEFAULT_MOVE(TimerListAutoCanceler) + ~TimerListAutoCanceler() = default; + + TimerListAutoCanceler& operator+=(long long id) { + list_.push_back(TimerAutoCanceler(id)); + return *this; + } + + void Clear() { list_.clear(); } + + bool IsEmpty() const { return list_.empty(); } + + private: + std::vector<TimerAutoCanceler> list_; +}; + +} // namespace cru::platform::gui diff --git a/include/cru/platform/gui/UiApplication.hpp b/include/cru/platform/gui/UiApplication.hpp index 5a5b0b13..407e4fa1 100644 --- a/include/cru/platform/gui/UiApplication.hpp +++ b/include/cru/platform/gui/UiApplication.hpp @@ -20,7 +20,7 @@ struct CreateWindowFlags { }; // The entry point of a ui application. -struct IUiApplication : public virtual INativeResource { +struct CRU_PLATFORM_GUI_API IUiApplication : public virtual IPlatformResource { public: static IUiApplication* GetInstance() { return instance; } @@ -66,70 +66,4 @@ struct IUiApplication : public virtual INativeResource { virtual ICursorManager* GetCursorManager() = 0; }; - -class TimerAutoCanceler { - public: - TimerAutoCanceler() : id_(0) {} - explicit TimerAutoCanceler(long long id) : id_(id) {} - - CRU_DELETE_COPY(TimerAutoCanceler) - - TimerAutoCanceler(TimerAutoCanceler&& other) : id_(other.id_) { - other.id_ = 0; - } - - TimerAutoCanceler& operator=(TimerAutoCanceler&& other) { - if (&other == this) { - return *this; - } - Reset(other.id_); - other.id_ = 0; - return *this; - } - - TimerAutoCanceler& operator=(long long other) { - return this->operator=(TimerAutoCanceler(other)); - } - - ~TimerAutoCanceler() { Reset(); } - - long long Release() { - auto temp = id_; - id_ = 0; - return temp; - } - - void Reset(long long id = 0) { - if (id_ > 0) IUiApplication::GetInstance()->CancelTimer(id_); - id_ = id; - } - - explicit operator bool() const { return id_; } - - private: - long long id_; -}; - -class TimerListAutoCanceler { - public: - TimerListAutoCanceler() = default; - CRU_DELETE_COPY(TimerListAutoCanceler) - CRU_DEFAULT_MOVE(TimerListAutoCanceler) - ~TimerListAutoCanceler() = default; - - TimerListAutoCanceler& operator+=(long long id) { - list_.push_back(TimerAutoCanceler(id)); - return *this; - } - - void Clear() { list_.clear(); } - - bool IsEmpty() const { return list_.empty(); } - - private: - std::vector<TimerAutoCanceler> list_; -}; - -// Bootstrap from this. -std::unique_ptr<IUiApplication> CreateUiApplication(); } // namespace cru::platform::gui diff --git a/include/cru/platform/gui/Window.hpp b/include/cru/platform/gui/Window.hpp index b2129322..3502868a 100644 --- a/include/cru/platform/gui/Window.hpp +++ b/include/cru/platform/gui/Window.hpp @@ -1,14 +1,38 @@ #pragma once #include "Base.hpp" +#include "Keyboard.hpp" + #include "cru/common/Event.hpp" #include <string_view> namespace cru::platform::gui { +enum class FocusChangeType { Gain, Lost }; + +enum class MouseEnterLeaveType { Enter, Leave }; + +struct NativeMouseButtonEventArgs { + MouseButton button; + Point point; + KeyModifier modifier; +}; + +struct NativeMouseWheelEventArgs { + // Positive means down. Negative means up. + float delta; + Point point; + KeyModifier modifier; +}; + +struct NativeKeyEventArgs { + KeyCode key; + KeyModifier modifier; +}; + // Represents a native window, which exposes some low-level events and // operations. -struct INativeWindow : virtual INativeResource { +struct INativeWindow : virtual IPlatformResource { virtual void Close() = 0; virtual INativeWindow* GetParent() = 0; diff --git a/include/cru/ui/controls/TextHostControlService.hpp b/include/cru/ui/controls/TextHostControlService.hpp index 340228fe..f39d9456 100644 --- a/include/cru/ui/controls/TextHostControlService.hpp +++ b/include/cru/ui/controls/TextHostControlService.hpp @@ -2,10 +2,12 @@ #include "Base.hpp" #include "cru/platform/gui/InputMethod.hpp" +#include "cru/platform/gui/TimerHelper.hpp" #include "cru/platform/gui/UiApplication.hpp" #include "cru/ui/controls/Control.hpp" #include "cru/ui/helper/ShortcutHub.hpp" + #include <functional> #include <string> diff --git a/include/cru/ui/host/LayoutPaintCycler.hpp b/include/cru/ui/host/LayoutPaintCycler.hpp index ed543afa..861fff41 100644 --- a/include/cru/ui/host/LayoutPaintCycler.hpp +++ b/include/cru/ui/host/LayoutPaintCycler.hpp @@ -1,6 +1,7 @@ #pragma once #include "../Base.hpp" +#include "cru/platform/gui/TimerHelper.hpp" #include "cru/platform/gui/UiApplication.hpp" #include <chrono> diff --git a/include/cru/ui/render/ScrollBar.hpp b/include/cru/ui/render/ScrollBar.hpp index 005cf3bb..ce6f1b98 100644 --- a/include/cru/ui/render/ScrollBar.hpp +++ b/include/cru/ui/render/ScrollBar.hpp @@ -7,11 +7,13 @@ #include "cru/platform/graphics/Geometry.hpp" #include "cru/platform/graphics/Painter.hpp" #include "cru/platform/gui/Cursor.hpp" +#include "cru/platform/gui/TimerHelper.hpp" #include "cru/platform/gui/UiApplication.hpp" #include "cru/ui/Base.hpp" #include "cru/ui/controls/Control.hpp" #include "cru/ui/helper/ClickDetector.hpp" + #include <gsl/pointers> #include <memory> #include <optional> diff --git a/include/cru/win/graphics/direct/Resource.hpp b/include/cru/win/graphics/direct/Resource.hpp index f60f373e..e6ffb203 100644 --- a/include/cru/win/graphics/direct/Resource.hpp +++ b/include/cru/win/graphics/direct/Resource.hpp @@ -8,9 +8,9 @@ namespace cru::platform::graphics::win::direct { class DirectGraphFactory; -class DirectResource : public Object, public virtual INativeResource { +class DirectResource : public Object, public virtual IPlatformResource { public: - static constexpr std::u16string_view k_platform_id = u"Windows Direct"; + static String kPlatformId; protected: DirectResource() = default; @@ -22,7 +22,7 @@ class DirectResource : public Object, public virtual INativeResource { ~DirectResource() override = default; public: - std::u16string_view GetPlatformId() const final { return k_platform_id; } + String GetPlatformId() const final { return kPlatformId; } }; class DirectGraphResource : public DirectResource, diff --git a/include/cru/win/gui/Resource.hpp b/include/cru/win/gui/Resource.hpp index 1f6f0a4a..4215de69 100644 --- a/include/cru/win/gui/Resource.hpp +++ b/include/cru/win/gui/Resource.hpp @@ -4,9 +4,9 @@ #include "cru/platform/Resource.hpp" namespace cru::platform::gui::win { -class WinNativeResource : public Object, public virtual INativeResource { +class WinNativeResource : public Object, public virtual IPlatformResource { public: - static constexpr std::u16string_view k_platform_id = u"Windows"; + static String kPlatformId; protected: WinNativeResource() = default; @@ -18,6 +18,6 @@ class WinNativeResource : public Object, public virtual INativeResource { ~WinNativeResource() override = default; public: - std::u16string_view GetPlatformId() const final { return k_platform_id; } + String GetPlatformId() const final { return kPlatformId; } }; } // namespace cru::platform::gui::win diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index d5d544ee..94961746 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -8,6 +8,7 @@ target_sources(cru_base PUBLIC ${CRU_BASE_INCLUDE_DIR}/Base.hpp ${CRU_BASE_INCLUDE_DIR}/Bitmask.hpp ${CRU_BASE_INCLUDE_DIR}/Event.hpp + ${CRU_BASE_INCLUDE_DIR}/Exception.hpp ${CRU_BASE_INCLUDE_DIR}/Format.hpp ${CRU_BASE_INCLUDE_DIR}/Logger.hpp ${CRU_BASE_INCLUDE_DIR}/PreConfig.hpp diff --git a/src/common/String.cpp b/src/common/String.cpp index ce124575..91422d48 100644 --- a/src/common/String.cpp +++ b/src/common/String.cpp @@ -1,8 +1,14 @@ #include "cru/common/String.hpp" +#include "cru/common/StringUtil.hpp" #include <cstring> +#include <string_view> namespace cru { +String String::FromUtf8(const char* str, Index size) { + return String{cru::ToUtf16(std::string_view(str, size))}; +} + std::uint16_t String::kEmptyBuffer[1] = {0}; template <typename C> @@ -138,4 +144,8 @@ String::iterator String::erase(const_iterator start, const_iterator end) { return s; } +std::string String::ToUtf8() const { + return cru::ToUtf8(std::u16string_view(Char16CStr(), size())); +} + } // namespace cru diff --git a/src/platform/CMakeLists.txt b/src/platform/CMakeLists.txt index 23f4a0f6..f5f48795 100644 --- a/src/platform/CMakeLists.txt +++ b/src/platform/CMakeLists.txt @@ -1,8 +1,10 @@ set(CRU_PLATFORM_BASE_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/platform) -add_library(cru_platform_base STATIC +add_library(cru_platform_base SHARED + ForDllExport.cpp Color.cpp ) target_sources(cru_platform_base PUBLIC + ${CRU_PLATFORM_BASE_INCLUDE_DIR}/Base.hpp ${CRU_PLATFORM_BASE_INCLUDE_DIR}/Check.hpp ${CRU_PLATFORM_BASE_INCLUDE_DIR}/Color.hpp ${CRU_PLATFORM_BASE_INCLUDE_DIR}/Exception.hpp @@ -12,6 +14,8 @@ target_sources(cru_platform_base PUBLIC ${CRU_PLATFORM_BASE_INCLUDE_DIR}/Resource.hpp ) target_link_libraries(cru_platform_base PUBLIC cru_base) +target_compile_definitions(cru_platform_base PRIVATE CRU_PLATFORM_EXPORT_API) add_subdirectory(graphics) add_subdirectory(gui) +add_subdirectory(bootstrap) diff --git a/src/platform/ForDllExport.cpp b/src/platform/ForDllExport.cpp new file mode 100644 index 00000000..743a9efa --- /dev/null +++ b/src/platform/ForDllExport.cpp @@ -0,0 +1,2 @@ +#include "cru/platform/Exception.hpp" +#include "cru/platform/Resource.hpp" diff --git a/src/platform/bootstrap/Bootstrap.cpp b/src/platform/bootstrap/Bootstrap.cpp new file mode 100644 index 00000000..99b5badb --- /dev/null +++ b/src/platform/bootstrap/Bootstrap.cpp @@ -0,0 +1,15 @@ +#include "cru/platform/bootstrap/Bootstrap.hpp" + +#ifdef CRU_PLATFORM_WINDOWS +#include "cru/win/gui/UiApplication.hpp" +#else +#endif + +namespace cru::platform::boostrap { +cru::platform::gui::IUiApplication* CreateUiApplication() { +#ifdef CRU_PLATFORM_WINDOWS + return new cru::platform::gui::win::WinUiApplication(); +#else +#endif +} +} // namespace cru::platform::boostrap diff --git a/src/platform/bootstrap/CMakeLists.txt b/src/platform/bootstrap/CMakeLists.txt new file mode 100644 index 00000000..7759415f --- /dev/null +++ b/src/platform/bootstrap/CMakeLists.txt @@ -0,0 +1,13 @@ +set(CRU_PLATFORM_BOOTSTRAP_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/platform/bootstrap) +add_library(cru_platform_boostrap SHARED + Bootstrap.cpp +) +target_sources(cru_platform_boostrap PUBLIC + ${CRU_PLATFORM_BOOTSTRAP_INCLUDE_DIR}/Bootstrap.hpp +) + +if(WIN32) + target_link_libraries(cru_platform_boostrap PUBLIC cru_win_gui) +endif() + +target_compile_definitions(cru_platform_boostrap PRIVATE CRU_PLATFORM_BOOTSTRAP_EXPORT_API) diff --git a/src/platform/gui/CMakeLists.txt b/src/platform/gui/CMakeLists.txt index aca7620c..7f16a0e0 100644 --- a/src/platform/gui/CMakeLists.txt +++ b/src/platform/gui/CMakeLists.txt @@ -1,5 +1,5 @@ set(CRU_PLATFORM_GUI_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/platform/gui) -add_library(cru_platform_gui STATIC +add_library(cru_platform_gui SHARED Keyboard.cpp UiApplication.cpp ) @@ -12,3 +12,4 @@ target_sources(cru_platform_gui PUBLIC ${CRU_PLATFORM_GUI_INCLUDE_DIR}/UiApplication.hpp ) target_link_libraries(cru_platform_gui PUBLIC cru_platform_graphics) +target_compile_definitions(cru_platform_gui PRIVATE CRU_PLATFORM_GUI_EXPORT_API) diff --git a/src/win/Exception.cpp b/src/win/Exception.cpp index 8d2eee23..df2103fd 100644 --- a/src/win/Exception.cpp +++ b/src/win/Exception.cpp @@ -5,13 +5,13 @@ namespace cru::platform::win { -inline std::string HResultMakeMessage( - HRESULT h_result, std::optional<std::string_view> message) { +inline String HResultMakeMessage(HRESULT h_result, + std::optional<String> message) { if (message.has_value()) - return fmt::format(FMT_STRING("HRESULT: {:#08x}. Message: {}"), h_result, - *message); + return fmt::format(FMT_STRING(L"HRESULT: {:#08x}. Message: {}"), h_result, + message->WinCStr()); else - return fmt::format(FMT_STRING("HRESULT: {:#08x}."), h_result); + return fmt::format(FMT_STRING(L"HRESULT: {:#08x}."), h_result); } HResultError::HResultError(HRESULT h_result) @@ -20,19 +20,21 @@ HResultError::HResultError(HRESULT h_result) HResultError::HResultError(HRESULT h_result, std::string_view additional_message) - : PlatformException(HResultMakeMessage(h_result, additional_message)), + : PlatformException(HResultMakeMessage( + h_result, String::FromUtf8(additional_message.data(), + additional_message.size()))), h_result_(h_result) {} -inline std::string Win32MakeMessage(DWORD error_code, - std::string_view message) { - return fmt::format("Last error code: {:#04x}.\nMessage: {}\n", error_code, - message); +inline String Win32MakeMessage(DWORD error_code, String message) { + return fmt::format(L"Last error code: {:#04x}.\nMessage: {}\n", error_code, + message.WinCStr()); } Win32Error::Win32Error(std::string_view message) : Win32Error(::GetLastError(), message) {} Win32Error::Win32Error(DWORD error_code, std::string_view message) - : PlatformException(Win32MakeMessage(error_code, message)), + : PlatformException(Win32MakeMessage( + error_code, String::FromUtf8(message.data(), message.size()))), error_code_(error_code) {} } // namespace cru::platform::win diff --git a/src/win/graphics/direct/Geometry.cpp b/src/win/graphics/direct/Geometry.cpp index 8aa961b2..d07a819f 100644 --- a/src/win/graphics/direct/Geometry.cpp +++ b/src/win/graphics/direct/Geometry.cpp @@ -13,7 +13,7 @@ D2DGeometryBuilder::D2DGeometryBuilder(DirectGraphFactory* factory) void D2DGeometryBuilder::CheckValidation() { if (!IsValid()) - throw ReuseException("The geometry builder is already disposed."); + throw ReuseException(L"The geometry builder is already disposed."); } void D2DGeometryBuilder::BeginFigure(const Point& point) { diff --git a/src/win/graphics/direct/Painter.cpp b/src/win/graphics/direct/Painter.cpp index d6999cfa..26ef92ec 100644 --- a/src/win/graphics/direct/Painter.cpp +++ b/src/win/graphics/direct/Painter.cpp @@ -106,7 +106,7 @@ void D2DPainter::EndDraw() { void D2DPainter::CheckValidation() { if (!is_drawing_) { throw cru::platform::ReuseException( - "Can't do that on painter after end drawing."); + L"Can't do that on painter after end drawing."); } } } // namespace cru::platform::graphics::win::direct diff --git a/src/win/graphics/direct/Resource.cpp b/src/win/graphics/direct/Resource.cpp index 2b4a0772..6ae74e64 100644 --- a/src/win/graphics/direct/Resource.cpp +++ b/src/win/graphics/direct/Resource.cpp @@ -3,6 +3,8 @@ #include "cru/win/graphics/direct/Factory.hpp" namespace cru::platform::graphics::win::direct { +String DirectResource::kPlatformId = u"Windows Direct"; + DirectGraphResource::DirectGraphResource(DirectGraphFactory* factory) : factory_(factory) { Expects(factory); diff --git a/src/win/gui/CMakeLists.txt b/src/win/gui/CMakeLists.txt index 48bed00d..53dfe69b 100644 --- a/src/win/gui/CMakeLists.txt +++ b/src/win/gui/CMakeLists.txt @@ -8,6 +8,7 @@ add_library(cru_win_gui STATIC GodWindow.cpp InputMethod.cpp Keyboard.cpp + Resource.cpp TimerManager.cpp UiApplication.cpp Window.cpp diff --git a/src/win/gui/Resource.cpp b/src/win/gui/Resource.cpp new file mode 100644 index 00000000..dc4de173 --- /dev/null +++ b/src/win/gui/Resource.cpp @@ -0,0 +1,6 @@ +#include "cru/win/gui/Resource.hpp" +#include "cru/win/gui/Window.hpp" + +namespace cru::platform::gui::win { +String WinNativeResource::kPlatformId = u"Windows"; +} |