aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2020-10-18 21:09:21 +0800
committercrupest <crupest@outlook.com>2020-10-18 21:09:21 +0800
commit5729a5aa1b443e3e25f3e14dee29636d3b31a6f8 (patch)
tree264efb8b0abdbbe1bcff813d9f10288f78cab905
parent58af3c346e7dd72be077bf5231bb7bf193591288 (diff)
downloadcru-5729a5aa1b443e3e25f3e14dee29636d3b31a6f8.tar.gz
cru-5729a5aa1b443e3e25f3e14dee29636d3b31a6f8.tar.bz2
cru-5729a5aa1b443e3e25f3e14dee29636d3b31a6f8.zip
...
-rw-r--r--demos/main/main.cpp34
-rw-r--r--include/cru/common/Format.hpp23
-rw-r--r--include/cru/common/Logger.hpp2
-rw-r--r--include/cru/platform/GraphBase.hpp9
-rw-r--r--include/cru/ui/Base.hpp3
-rw-r--r--include/cru/ui/UiManager.hpp4
-rw-r--r--include/cru/ui/render/FlexLayoutRenderObject.hpp4
-rw-r--r--include/cru/ui/render/MeasureRequirement.hpp28
-rw-r--r--include/cru/ui/render/RenderObject.hpp7
-rw-r--r--include/cru/ui/render/WindowRenderObject.hpp5
-rw-r--r--src/common/CMakeLists.txt1
-rw-r--r--src/common/Logger.cpp1
-rw-r--r--src/ui/UiManager.cpp5
-rw-r--r--src/ui/render/FlexLayoutRenderObject.cpp6
-rw-r--r--src/ui/render/RenderObject.cpp36
-rw-r--r--src/ui/render/WindowRenderObject.cpp4
-rw-r--r--src/win/CMakeLists.txt1
-rw-r--r--src/win/StdOutLogger.hpp24
-rw-r--r--src/win/native/UiApplication.cpp3
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>();