diff options
-rw-r--r-- | demos/main/main.cpp | 34 | ||||
-rw-r--r-- | include/cru/common/Format.hpp | 23 | ||||
-rw-r--r-- | include/cru/common/Logger.hpp | 2 | ||||
-rw-r--r-- | include/cru/platform/GraphBase.hpp | 9 | ||||
-rw-r--r-- | include/cru/ui/Base.hpp | 3 | ||||
-rw-r--r-- | include/cru/ui/UiManager.hpp | 4 | ||||
-rw-r--r-- | include/cru/ui/render/FlexLayoutRenderObject.hpp | 4 | ||||
-rw-r--r-- | include/cru/ui/render/MeasureRequirement.hpp | 28 | ||||
-rw-r--r-- | include/cru/ui/render/RenderObject.hpp | 7 | ||||
-rw-r--r-- | include/cru/ui/render/WindowRenderObject.hpp | 5 | ||||
-rw-r--r-- | src/common/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/common/Logger.cpp | 1 | ||||
-rw-r--r-- | src/ui/UiManager.cpp | 5 | ||||
-rw-r--r-- | src/ui/render/FlexLayoutRenderObject.cpp | 6 | ||||
-rw-r--r-- | src/ui/render/RenderObject.cpp | 36 | ||||
-rw-r--r-- | src/ui/render/WindowRenderObject.cpp | 4 | ||||
-rw-r--r-- | src/win/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/win/StdOutLogger.hpp | 24 | ||||
-rw-r--r-- | src/win/native/UiApplication.cpp | 3 |
19 files changed, 170 insertions, 30 deletions
diff --git a/demos/main/main.cpp b/demos/main/main.cpp index 82038731..3026baeb 100644 --- a/demos/main/main.cpp +++ b/demos/main/main.cpp @@ -1,6 +1,7 @@ #include "cru/platform/HeapDebug.hpp" #include "cru/platform/native/UiApplication.hpp" #include "cru/platform/native/Window.hpp" +#include "cru/ui/Base.hpp" #include "cru/ui/UiHost.hpp" #include "cru/ui/Window.hpp" #include "cru/ui/controls/Button.hpp" @@ -10,12 +11,9 @@ #include "cru/ui/controls/TextBox.hpp" using cru::platform::native::CreateUiApplication; -using cru::ui::Rect; -using cru::ui::Thickness; using cru::ui::Window; using cru::ui::controls::Button; using cru::ui::controls::FlexLayout; -using cru::ui::controls::StackLayout; using cru::ui::controls::TextBlock; using cru::ui::controls::TextBox; @@ -31,30 +29,20 @@ int main() { const auto flex_layout = FlexLayout::Create(); window->SetChild(flex_layout); + flex_layout->SetFlexDirection(cru::ui::FlexDirection::Vertical); - const auto button = Button::Create(); - const auto text_block1 = TextBlock::Create(); - text_block1->SetText(u"Hello World!"); - button->SetChild(text_block1); - flex_layout->AddChild(button, 0); - - const auto text_block2 = TextBlock::Create(); - text_block2->SetText(u"Hello World!"); - - const auto text_block3 = TextBlock::Create(); - text_block3->SetText(u"Overlapped text"); + const auto text_block = TextBlock::Create(); + text_block->SetText(u"Hello World from CruUI!"); + flex_layout->AddChild(text_block, 0); - const auto stack_layout = StackLayout::Create(); - stack_layout->AddChild(text_block2, 0); - stack_layout->AddChild(text_block3, 1); - flex_layout->AddChild(stack_layout, 1); - - const auto text_block4 = TextBlock::Create(); - text_block4->SetText(u"Hello World!!!"); - flex_layout->AddChild(text_block4, 2); + const auto button_text_block = TextBlock::Create(); + button_text_block->SetText(u"OK"); + const auto button = Button::Create(); + button->SetChild(button_text_block); + flex_layout->AddChild(button, 1); const auto text_box = TextBox::Create(); - flex_layout->AddChild(text_box, 3); + flex_layout->AddChild(text_box, 2); window->GetUiHost()->GetNativeWindowResolver()->Resolve()->SetVisible(true); diff --git a/include/cru/common/Format.hpp b/include/cru/common/Format.hpp new file mode 100644 index 00000000..59f34036 --- /dev/null +++ b/include/cru/common/Format.hpp @@ -0,0 +1,23 @@ +#pragma once +#include "Base.hpp" + +#include "StringUtil.hpp" + +#include <array> +#include <charconv> +#include <string> +#include <string_view> +#include <system_error> +#include <type_traits> + +namespace cru { +template <typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>> +std::u16string ToUtf16String(T number) { + std::array<char, 40> buffer; + auto result = + std::to_chars(buffer.data(), buffer.data() + buffer.size(), number); + Ensures(result.ec == std::errc()); + std::string_view utf8_result(buffer.data(), result.ptr - buffer.data()); + return ToUtf16(utf8_result); +} +} // namespace cru diff --git a/include/cru/common/Logger.hpp b/include/cru/common/Logger.hpp index 4ea17c09..daf2e7d2 100644 --- a/include/cru/common/Logger.hpp +++ b/include/cru/common/Logger.hpp @@ -40,6 +40,7 @@ class Logger : public Object { std::list<std::unique_ptr<ILogSource>> sources_; }; +// TODO: Remove argument evaluation in Debug. template <typename... TArgs> void Debug([[maybe_unused]] TArgs&&... args) { #ifdef CRU_DEBUG @@ -66,6 +67,7 @@ void Error(TArgs&&... args) { fmt::format(std::forward<TArgs>(args)...)); } +// TODO: Remove argument evaluation in Debug. template <typename... TArgs> void TagDebug([[maybe_unused]] std::u16string_view tag, [[maybe_unused]] TArgs&&... args) { diff --git a/include/cru/platform/GraphBase.hpp b/include/cru/platform/GraphBase.hpp index 186ee9d0..571b36f7 100644 --- a/include/cru/platform/GraphBase.hpp +++ b/include/cru/platform/GraphBase.hpp @@ -1,9 +1,13 @@ #pragma once #include "cru/common/Base.hpp" +#include "cru/common/Format.hpp" + +#include <fmt/core.h> #include <cstdint> #include <limits> #include <optional> +#include <string> #include <utility> namespace cru::platform { @@ -46,6 +50,11 @@ struct Size final { std::numeric_limits<float>::max()}; } + std::u16string ToDebugString() const { + return fmt::format(u"({}, {})", ToUtf16String(width), + ToUtf16String(height)); + } + float width = 0; float height = 0; }; diff --git a/include/cru/ui/Base.hpp b/include/cru/ui/Base.hpp index 6be359ab..0c0a4783 100644 --- a/include/cru/ui/Base.hpp +++ b/include/cru/ui/Base.hpp @@ -8,6 +8,9 @@ #include <optional> #include <vector> +// Change 0 to 1 to enable debug layout log. +#define CRUUI_DEBUG_LAYOUT 0 + namespace cru::ui { //-------------------- region: import -------------------- using cru::platform::Color; diff --git a/include/cru/ui/UiManager.hpp b/include/cru/ui/UiManager.hpp index e6facdbd..46f06ac2 100644 --- a/include/cru/ui/UiManager.hpp +++ b/include/cru/ui/UiManager.hpp @@ -3,8 +3,12 @@ #include "controls/Base.hpp" +#include <memory> +#include <string> + namespace cru::ui { struct ThemeResources { + std::u16string default_font_family; std::shared_ptr<platform::graph::IFont> default_font; std::shared_ptr<platform::graph::IBrush> text_brush; std::shared_ptr<platform::graph::IBrush> text_selection_brush; diff --git a/include/cru/ui/render/FlexLayoutRenderObject.hpp b/include/cru/ui/render/FlexLayoutRenderObject.hpp index ee29d1e4..a8154487 100644 --- a/include/cru/ui/render/FlexLayoutRenderObject.hpp +++ b/include/cru/ui/render/FlexLayoutRenderObject.hpp @@ -1,6 +1,8 @@ #pragma once #include "LayoutRenderObject.hpp" +#include <string_view> + namespace cru::ui::render { // Measure Logic (v0.1): // Cross axis measure logic is the same as stack layout. @@ -85,6 +87,8 @@ class FlexLayoutRenderObject : public LayoutRenderObject<FlexChildLayoutData> { FlexLayoutRenderObject& operator=(FlexLayoutRenderObject&& other) = delete; ~FlexLayoutRenderObject() override = default; + std::u16string_view GetName() const override; + FlexDirection GetFlexDirection() const { return direction_; } void SetFlexDirection(FlexDirection direction) { direction_ = direction; diff --git a/include/cru/ui/render/MeasureRequirement.hpp b/include/cru/ui/render/MeasureRequirement.hpp index 2be159f8..6a0c6952 100644 --- a/include/cru/ui/render/MeasureRequirement.hpp +++ b/include/cru/ui/render/MeasureRequirement.hpp @@ -1,8 +1,12 @@ #pragma once #include "Base.hpp" +#include "cru/common/Format.hpp" + +#include <fmt/core.h> #include <algorithm> #include <limits> +#include <string> namespace cru::ui::render { constexpr Size Min(const Size& left, const Size& right) { @@ -112,6 +116,11 @@ class MeasureLength final { } } + std::u16string ToDebugString() const { + return IsSpecified() ? ToUtf16String(GetLengthOrUndefined()) + : u"UNSPECIFIED"; + } + private: // -1 for not specify float length_; @@ -160,6 +169,11 @@ struct MeasureSize { }; } + std::u16string ToDebugString() const { + return fmt::format(u"({}, {})", width.ToDebugString(), + height.ToDebugString()); + } + constexpr static MeasureSize NotSpecified() { return MeasureSize{MeasureLength::NotSpecified(), MeasureLength::NotSpecified()}; @@ -187,10 +201,11 @@ struct MeasureRequirement { : max(max), min(min) {} constexpr bool Satisfy(const Size& size) const { - return max.width.GetLengthOrMax() >= size.width && - max.height.GetLengthOrMax() >= size.height && - min.width.GetLengthOr0() <= size.width && - min.height.GetLengthOr0() <= size.height; + auto normalized = Normalize(); + return normalized.max.width.GetLengthOrMax() >= size.width && + normalized.max.height.GetLengthOrMax() >= size.height && + normalized.min.width.GetLengthOr0() <= size.width && + normalized.min.height.GetLengthOr0() <= size.height; } constexpr MeasureRequirement Normalize() const { @@ -225,6 +240,11 @@ struct MeasureRequirement { return result; } + std::u16string ToDebugString() const { + return fmt::format(u"{{min: {}, max: {}}}", min.ToDebugString(), + max.ToDebugString()); + } + constexpr static MeasureRequirement Merge(const MeasureRequirement& left, const MeasureRequirement& right) { return MeasureRequirement{MeasureSize::Min(left.max, right.max), diff --git a/include/cru/ui/render/RenderObject.hpp b/include/cru/ui/render/RenderObject.hpp index f820f029..57251e3a 100644 --- a/include/cru/ui/render/RenderObject.hpp +++ b/include/cru/ui/render/RenderObject.hpp @@ -4,6 +4,9 @@ #include "MeasureRequirement.hpp" #include "cru/common/Event.hpp" +#include <string> +#include <string_view> + namespace cru::ui::render { // Render object will not destroy its children when destroyed. Control must @@ -133,6 +136,10 @@ class RenderObject : public Object { void InvalidateLayout(); void InvalidatePaint(); + public: + virtual std::u16string_view GetName() const; + std::u16string GetDebugPathInTree() const; + protected: void SetChildMode(ChildMode mode) { child_mode_ = mode; } diff --git a/include/cru/ui/render/WindowRenderObject.hpp b/include/cru/ui/render/WindowRenderObject.hpp index 4c254f42..d2ca5526 100644 --- a/include/cru/ui/render/WindowRenderObject.hpp +++ b/include/cru/ui/render/WindowRenderObject.hpp @@ -1,6 +1,8 @@ #pragma once #include "RenderObject.hpp" +#include <string_view> + namespace cru::ui::render { class WindowRenderObject : public RenderObject { public: @@ -13,6 +15,9 @@ class WindowRenderObject : public RenderObject { RenderObject* HitTest(const Point& point) override; + public: + std::u16string_view GetName() const override; + protected: Size OnMeasureContent(const MeasureRequirement& requirement, const MeasureSize& preferred_size) override; diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 6a18ef2b..73ad9456 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -7,6 +7,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}/Format.hpp ${CRU_BASE_INCLUDE_DIR}/Logger.hpp ${CRU_BASE_INCLUDE_DIR}/PreConfig.hpp ${CRU_BASE_INCLUDE_DIR}/SelfResolvable.hpp diff --git a/src/common/Logger.cpp b/src/common/Logger.cpp index dfa25347..af1dd692 100644 --- a/src/common/Logger.cpp +++ b/src/common/Logger.cpp @@ -73,7 +73,6 @@ void Logger::Log(LogLevel level, std::u16string_view tag, } #endif for (const auto &source : sources_) { - auto now = std::time(nullptr); source->Write(level, fmt::format(u"[{}] {} {}: {}\n", GetLogTime(), LogLevelToString(level), tag, s)); } diff --git a/src/ui/UiManager.cpp b/src/ui/UiManager.cpp index 4cd38efa..8a2029b9 100644 --- a/src/ui/UiManager.cpp +++ b/src/ui/UiManager.cpp @@ -30,7 +30,10 @@ UiManager* UiManager::GetInstance() { UiManager::UiManager() { const auto factory = GetGraphFactory(); - theme_resource_.default_font = factory->CreateFont(u"等线", 24.0f); + theme_resource_.default_font_family = u"等线"; + + theme_resource_.default_font = + factory->CreateFont(theme_resource_.default_font_family, 24.0f); const auto black_brush = std::shared_ptr<platform::graph::ISolidColorBrush>( CreateSolidColorBrush(factory, colors::black)); diff --git a/src/ui/render/FlexLayoutRenderObject.cpp b/src/ui/render/FlexLayoutRenderObject.cpp index ade230b5..1c39cc8f 100644 --- a/src/ui/render/FlexLayoutRenderObject.cpp +++ b/src/ui/render/FlexLayoutRenderObject.cpp @@ -10,6 +10,10 @@ namespace cru::ui::render { +std::u16string_view FlexLayoutRenderObject::GetName() const { + return u"FlexLayoutRenderObject"; +} + struct tag_horizontal_t {}; struct tag_vertical_t {}; @@ -64,7 +68,7 @@ template <typename TSize> constexpr TSize CreateTSize(decltype(std::declval<TSize>().width) main, decltype(std::declval<TSize>().height) cross, tag_vertical_t) { - return TSize{main, cross}; + return TSize{cross, main}; } enum class FlexLayoutAdjustType { None, Expand, Shrink }; diff --git a/src/ui/render/RenderObject.cpp b/src/ui/render/RenderObject.cpp index 30433868..bc2228d3 100644 --- a/src/ui/render/RenderObject.cpp +++ b/src/ui/render/RenderObject.cpp @@ -5,6 +5,9 @@ #include "cru/ui/UiHost.hpp" #include <algorithm> +#include <string> +#include <string_view> +#include <vector> namespace cru::ui::render { void RenderObject::AddChild(RenderObject* render_object, const Index position) { @@ -66,7 +69,19 @@ void RenderObject::Measure(const MeasureRequirement& requirement, MeasureSize merged_preferred_size = preferred_size.OverrideBy(preferred_size_); +#if CRUUI_DEBUG_LAYOUT + log::Debug(u"{} Measure begins :\nrequirement: {}\npreferred size: {}", + this->GetDebugPathInTree(), requirement.ToDebugString(), + preferred_size.ToDebugString()); +#endif + size_ = OnMeasureCore(merged_requirement, merged_preferred_size); + +#if CRUUI_DEBUG_LAYOUT + log::Debug(u"{} Measure ends :\nresult size: {}", this->GetDebugPathInTree(), + size_.ToDebugString()); +#endif + Ensures(size_.width >= 0); Ensures(size_.height >= 0); Ensures(requirement.Satisfy(size_)); @@ -256,6 +271,27 @@ void RenderObject::InvalidatePaint() { if (ui_host_ != nullptr) ui_host_->InvalidatePaint(); } +constexpr std::u16string_view kUnamedName(u"UNNAMED"); + +std::u16string_view RenderObject::GetName() const { return kUnamedName; } + +std::u16string RenderObject::GetDebugPathInTree() const { + std::vector<std::u16string_view> chain; + const RenderObject* parent = this; + while (parent != nullptr) { + chain.push_back(parent->GetName()); + parent = parent->GetParent(); + } + + std::u16string result(chain.back()); + for (auto iter = chain.crbegin() + 1; iter != chain.crend(); ++iter) { + result += u" -> "; + result += *iter; + } + + return result; +} + void RenderObject::NotifyAfterLayoutRecursive(RenderObject* render_object) { render_object->OnAfterLayout(); for (const auto o : render_object->GetChildren()) { diff --git a/src/ui/render/WindowRenderObject.cpp b/src/ui/render/WindowRenderObject.cpp index 4adf559e..a136c1e9 100644 --- a/src/ui/render/WindowRenderObject.cpp +++ b/src/ui/render/WindowRenderObject.cpp @@ -24,6 +24,10 @@ RenderObject* WindowRenderObject::HitTest(const Point& point) { return Rect{Point{}, GetSize()}.IsPointInside(point) ? this : nullptr; } +std::u16string_view WindowRenderObject::GetName() const { + return u"WindowRenderObject"; +} + Size WindowRenderObject::OnMeasureContent(const MeasureRequirement& requirement, const MeasureSize& preferred_size) { if (const auto child = GetChild()) { diff --git a/src/win/CMakeLists.txt b/src/win/CMakeLists.txt index 75b0a7ca..06f947a1 100644 --- a/src/win/CMakeLists.txt +++ b/src/win/CMakeLists.txt @@ -2,6 +2,7 @@ set(CRU_WIN_BASE_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/win/) add_library(cru_win_base STATIC DebugLogger.hpp + StdOutLogger.hpp Exception.cpp HeapDebug.cpp diff --git a/src/win/StdOutLogger.hpp b/src/win/StdOutLogger.hpp new file mode 100644 index 00000000..bff8b30e --- /dev/null +++ b/src/win/StdOutLogger.hpp @@ -0,0 +1,24 @@ +#include "cru/common/Base.hpp" +#include "cru/win/WinPreConfig.hpp" + +#include "cru/common/Logger.hpp" + +#include <cwchar> + +namespace cru::platform::win { +class WinStdOutLoggerSource : public ::cru::log::ILogSource { + public: + WinStdOutLoggerSource() = default; + + CRU_DELETE_COPY(WinStdOutLoggerSource) + CRU_DELETE_MOVE(WinStdOutLoggerSource) + + ~WinStdOutLoggerSource() = default; + + void Write(::cru::log::LogLevel level, const std::u16string& s) override { + CRU_UNUSED(level) + + std::fputws(reinterpret_cast<const wchar_t*>(s.c_str()), stdout); + } +}; +} // namespace cru::platform::win diff --git a/src/win/native/UiApplication.cpp b/src/win/native/UiApplication.cpp index a806db88..198f03f2 100644 --- a/src/win/native/UiApplication.cpp +++ b/src/win/native/UiApplication.cpp @@ -1,6 +1,7 @@ #include "cru/win/native/UiApplication.hpp" #include "../DebugLogger.hpp" +#include "../StdOutLogger.hpp" #include "TimerManager.hpp" #include "WindowManager.hpp" #include "cru/common/Logger.hpp" @@ -30,6 +31,8 @@ WinUiApplication::WinUiApplication() { log::Logger::GetInstance()->AddSource( std::make_unique<::cru::platform::win::WinDebugLoggerSource>()); + log::Logger::GetInstance()->AddSource( + std::make_unique<::cru::platform::win::WinStdOutLoggerSource>()); graph_factory_ = std::make_unique<cru::platform::graph::win::direct::DirectGraphFactory>(); |