aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2022-01-12 23:13:10 +0800
committerGitHub <noreply@github.com>2022-01-12 23:13:10 +0800
commit276ae73fa444c16f34a379ae9d8f58c883056b4a (patch)
tree96f4d7103976836e918b4fa1db0fdbb80777986e
parent01f98ce88950cdb729f5db58bf26f2fffa1c326c (diff)
parent65c799c5339ba37bea2217b168e96b15aceaef85 (diff)
downloadcru-276ae73fa444c16f34a379ae9d8f58c883056b4a.tar.gz
cru-276ae73fa444c16f34a379ae9d8f58c883056b4a.tar.bz2
cru-276ae73fa444c16f34a379ae9d8f58c883056b4a.zip
Merge pull request #44 from crupest/dev
Windows development.
-rw-r--r--include/cru/common/PropertyTree.hpp4
-rw-r--r--include/cru/common/String.hpp16
-rw-r--r--include/cru/common/StringUtil.hpp2
-rw-r--r--include/cru/osx/graphics/quartz/Painter.hpp3
-rw-r--r--include/cru/parse/Base.hpp11
-rw-r--r--include/cru/parse/Grammar.hpp2
-rw-r--r--include/cru/parse/Nonterminal.hpp2
-rw-r--r--include/cru/parse/ParsingAlgorithm.hpp2
-rw-r--r--include/cru/parse/ParsingAlgorithmContext.hpp2
-rw-r--r--include/cru/parse/ParsingContext.hpp2
-rw-r--r--include/cru/parse/ParsingTreeNode.hpp2
-rw-r--r--include/cru/parse/Production.hpp2
-rw-r--r--include/cru/parse/RecursiveDescentAlgorithm.hpp2
-rw-r--r--include/cru/parse/RecursiveDescentAlgorithmContext.hpp2
-rw-r--r--include/cru/parse/Symbol.hpp4
-rw-r--r--include/cru/parse/Terminal.hpp2
-rw-r--r--include/cru/parse/TokenType.hpp4
-rw-r--r--include/cru/platform/graphics/Base.hpp11
-rw-r--r--include/cru/platform/graphics/Brush.hpp4
-rw-r--r--include/cru/platform/graphics/Factory.hpp2
-rw-r--r--include/cru/platform/graphics/Font.hpp2
-rw-r--r--include/cru/platform/graphics/Geometry.hpp4
-rw-r--r--include/cru/platform/graphics/NullPainter.hpp53
-rw-r--r--include/cru/platform/graphics/Painter.hpp5
-rw-r--r--include/cru/platform/graphics/Resource.hpp2
-rw-r--r--include/cru/platform/graphics/TextLayout.hpp2
-rw-r--r--include/cru/platform/gui/Window.hpp1
-rw-r--r--include/cru/toml/Base.hpp11
-rw-r--r--include/cru/toml/TomlDocument.hpp6
-rw-r--r--include/cru/toml/TomlParser.hpp4
-rw-r--r--include/cru/win/WinPreConfig.hpp1
-rw-r--r--include/cru/win/graphics/direct/Brush.hpp4
-rw-r--r--include/cru/win/graphics/direct/Factory.hpp15
-rw-r--r--include/cru/win/graphics/direct/Font.hpp6
-rw-r--r--include/cru/win/graphics/direct/Geometry.hpp8
-rw-r--r--include/cru/win/graphics/direct/Painter.hpp10
-rw-r--r--include/cru/win/graphics/direct/Resource.hpp20
-rw-r--r--include/cru/win/graphics/direct/TextLayout.hpp23
-rw-r--r--include/cru/win/graphics/direct/WindowRenderTarget.hpp6
-rw-r--r--include/cru/win/gui/GodWindow.hpp1
-rw-r--r--include/cru/win/gui/InputMethod.hpp6
-rw-r--r--include/cru/win/gui/UiApplication.hpp22
-rw-r--r--include/cru/win/gui/Window.hpp55
-rw-r--r--include/cru/xml/Base.hpp11
-rw-r--r--include/cru/xml/XmlNode.hpp12
-rw-r--r--include/cru/xml/XmlParser.hpp4
-rw-r--r--src/common/String.cpp11
-rw-r--r--src/common/StringUtil.cpp2
-rw-r--r--src/osx/graphics/quartz/Painter.cpp2
-rw-r--r--src/parse/CMakeLists.txt1
-rw-r--r--src/parse/RecursiveDescentAlgorithm.cpp1
-rw-r--r--src/parse/RecursiveDescentAlgorithmContext.cpp1
-rw-r--r--src/platform/graphics/CMakeLists.txt2
-rw-r--r--src/platform/graphics/ForDllExport.cpp7
-rw-r--r--src/toml/CMakeLists.txt1
-rw-r--r--src/ui/components/Menu.cpp2
-rw-r--r--src/ui/controls/TextHostControlService.cpp31
-rw-r--r--src/ui/render/TextRenderObject.cpp1
-rw-r--r--src/win/DebugLogger.hpp5
-rw-r--r--src/win/Exception.cpp10
-rw-r--r--src/win/HeapDebug.cpp4
-rw-r--r--src/win/StdOutLogger.hpp5
-rw-r--r--src/win/graphics/direct/Brush.cpp4
-rw-r--r--src/win/graphics/direct/Factory.cpp20
-rw-r--r--src/win/graphics/direct/Font.cpp4
-rw-r--r--src/win/graphics/direct/Geometry.cpp10
-rw-r--r--src/win/graphics/direct/Painter.cpp42
-rw-r--r--src/win/graphics/direct/Resource.cpp6
-rw-r--r--src/win/graphics/direct/TextLayout.cpp59
-rw-r--r--src/win/graphics/direct/WindowRenderTarget.cpp2
-rw-r--r--src/win/gui/InputMethod.cpp14
-rw-r--r--src/win/gui/UiApplication.cpp24
-rw-r--r--src/win/gui/Window.cpp268
-rw-r--r--src/win/gui/WindowManager.cpp3
-rw-r--r--src/xml/CMakeLists.txt1
75 files changed, 643 insertions, 275 deletions
diff --git a/include/cru/common/PropertyTree.hpp b/include/cru/common/PropertyTree.hpp
index 01b50dac..613bcc47 100644
--- a/include/cru/common/PropertyTree.hpp
+++ b/include/cru/common/PropertyTree.hpp
@@ -8,7 +8,7 @@
namespace cru {
class PropertyTree;
-class PropertySubTreeRef {
+class CRU_BASE_API PropertySubTreeRef {
public:
static String CombineKey(StringView left, StringView right);
@@ -37,7 +37,7 @@ class PropertySubTreeRef {
String path_;
};
-class PropertyTree {
+class CRU_BASE_API PropertyTree {
public:
static String CombineKey(StringView left, StringView right);
diff --git a/include/cru/common/String.hpp b/include/cru/common/String.hpp
index 8acb6a87..dd3da52f 100644
--- a/include/cru/common/String.hpp
+++ b/include/cru/common/String.hpp
@@ -80,6 +80,8 @@ class CRU_BASE_API String {
}
}
+ String(size_type size, value_type ch = 0);
+
String(std::initializer_list<value_type> l);
explicit String(StringView str);
@@ -328,16 +330,16 @@ std::enable_if_t<std::is_integral_v<T>, String> ToString(T value) {
auto result =
std::to_chars(buffer.data(), buffer.data() + buffer.size(), value);
+ if (result.ec == std::errc{}) {
+ } else {
+ throw std::invalid_argument("Failed to convert value to chars.");
+ }
+
auto size = result.ptr - buffer.data();
auto b = new char16_t[size + 1];
b[size] = 0;
std::copy(buffer.data(), result.ptr, b);
return String::FromBuffer(b, size, size);
-
- if (result.ec == std::errc{}) {
- } else {
- throw std::invalid_argument("Failed to convert value to chars.");
- }
}
template <typename T>
@@ -346,7 +348,7 @@ std::enable_if_t<std::is_floating_point_v<T>, String> ToString(T value) {
return String(str.cbegin(), str.cend());
}
-inline String ToString(String value) { return std::move(value); }
+inline String ToString(String value) { return value; }
namespace details {
enum class FormatTokenType { PlaceHolder, Text };
@@ -366,7 +368,7 @@ template <typename TA, typename... T>
void FormatAppendFromFormatTokenList(
String& current, const std::vector<FormatToken>& format_token_list,
Index index, TA&& args0, T&&... args) {
- for (Index i = index; i < format_token_list.size(); i++) {
+ for (Index i = index; i < static_cast<Index>(format_token_list.size()); i++) {
const auto& token = format_token_list[i];
if (token.type == FormatTokenType::PlaceHolder) {
current += ToString(std::forward<TA>(args0));
diff --git a/include/cru/common/StringUtil.hpp b/include/cru/common/StringUtil.hpp
index a0cb6b0b..27ad4b43 100644
--- a/include/cru/common/StringUtil.hpp
+++ b/include/cru/common/StringUtil.hpp
@@ -49,7 +49,7 @@ class CodePointIterator {
struct past_end_tag_t {};
explicit CodePointIterator(const CharType* ptr, Index size, Index current = 0)
- : ptr_(ptr), size_(size), position_(0) {}
+ : ptr_(ptr), size_(size), position_(current) {}
explicit CodePointIterator(const CharType* ptr, Index size, past_end_tag_t)
: ptr_(ptr), size_(size), position_(size) {}
diff --git a/include/cru/osx/graphics/quartz/Painter.hpp b/include/cru/osx/graphics/quartz/Painter.hpp
index 0889d413..83f15516 100644
--- a/include/cru/osx/graphics/quartz/Painter.hpp
+++ b/include/cru/osx/graphics/quartz/Painter.hpp
@@ -40,8 +40,7 @@ class QuartzCGContextPainter : public OsxQuartzResource,
void FillRectangle(const Rect& rectangle, IBrush* brush) override;
void StrokeEllipse(const Rect& outline_rect, IBrush* brush,
float width) override;
- void FillEllipse(const Rect& outline_rect, IBrush* brush,
- float width) override;
+ void FillEllipse(const Rect& outline_rect, IBrush* brush) override;
void StrokeGeometry(IGeometry* geometry, IBrush* brush, float width) override;
void FillGeometry(IGeometry* geometry, IBrush* brush) override;
diff --git a/include/cru/parse/Base.hpp b/include/cru/parse/Base.hpp
new file mode 100644
index 00000000..8f3a05e9
--- /dev/null
+++ b/include/cru/parse/Base.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#ifdef CRU_PLATFORM_WINDOWS
+#ifdef CRU_PARSE_EXPORT_API
+#define CRU_PARSE_API __declspec(dllexport)
+#else
+#define CRU_PARSE_API __declspec(dllimport)
+#endif
+#else
+#define CRU_PARSE_API
+#endif
diff --git a/include/cru/parse/Grammar.hpp b/include/cru/parse/Grammar.hpp
index 606fcc33..8dc1833f 100644
--- a/include/cru/parse/Grammar.hpp
+++ b/include/cru/parse/Grammar.hpp
@@ -5,7 +5,7 @@
#include <vector>
namespace cru::parse {
-class Grammar : public Object {
+class CRU_PARSE_API Grammar : public Object {
public:
Grammar();
diff --git a/include/cru/parse/Nonterminal.hpp b/include/cru/parse/Nonterminal.hpp
index 1bc6f9ff..b01c7c8a 100644
--- a/include/cru/parse/Nonterminal.hpp
+++ b/include/cru/parse/Nonterminal.hpp
@@ -2,7 +2,7 @@
#include "Symbol.hpp"
namespace cru::parse {
-class Nonterminal : public Symbol {
+class CRU_PARSE_API Nonterminal : public Symbol {
public:
Nonterminal(Grammar* grammar, String name);
diff --git a/include/cru/parse/ParsingAlgorithm.hpp b/include/cru/parse/ParsingAlgorithm.hpp
index acca159e..8f38c0ab 100644
--- a/include/cru/parse/ParsingAlgorithm.hpp
+++ b/include/cru/parse/ParsingAlgorithm.hpp
@@ -7,7 +7,7 @@ class ParsingAlgorithmContext;
// Represents a parsing algorithm.
// It does not relate to any specific grammar.
// It is used to validate a grammar and create a parsing algorithm context.
-class ParsingAlgorithm {
+class CRU_PARSE_API ParsingAlgorithm {
public:
ParsingAlgorithm() = default;
diff --git a/include/cru/parse/ParsingAlgorithmContext.hpp b/include/cru/parse/ParsingAlgorithmContext.hpp
index f67ccbbc..b959462c 100644
--- a/include/cru/parse/ParsingAlgorithmContext.hpp
+++ b/include/cru/parse/ParsingAlgorithmContext.hpp
@@ -10,7 +10,7 @@ class ParsingAlgorithm;
// A parsing algorithm context contains all data a parsing algorithm needs to
// parse for a grammar. It does not relate to any input. For example, it can
// contain any state machine.
-class ParsingAlgorithmContext {
+class CRU_PARSE_API ParsingAlgorithmContext {
public:
ParsingAlgorithmContext(Grammar* grammar, const ParsingAlgorithm* algorithm);
diff --git a/include/cru/parse/ParsingContext.hpp b/include/cru/parse/ParsingContext.hpp
index ebb7115a..cfb850b9 100644
--- a/include/cru/parse/ParsingContext.hpp
+++ b/include/cru/parse/ParsingContext.hpp
@@ -5,7 +5,7 @@
namespace cru::parse {
// A parsing context contains all info that a program needs to know when parsing
// a input sequence of terminals.
-class ParsingContext {
+class CRU_PARSE_API ParsingContext {
public:
ParsingContext(const ParsingAlgorithmContext* parsing_algorithm_context,
std::vector<Terminal*> input);
diff --git a/include/cru/parse/ParsingTreeNode.hpp b/include/cru/parse/ParsingTreeNode.hpp
index d1c3d058..7119ca0b 100644
--- a/include/cru/parse/ParsingTreeNode.hpp
+++ b/include/cru/parse/ParsingTreeNode.hpp
@@ -4,7 +4,7 @@
#include <vector>
namespace cru::parse {
-class ParsingTreeNode {
+class CRU_PARSE_API ParsingTreeNode {
public:
ParsingTreeNode(Symbol* symbol, Production* production);
diff --git a/include/cru/parse/Production.hpp b/include/cru/parse/Production.hpp
index 8a1331b9..cb3c79c0 100644
--- a/include/cru/parse/Production.hpp
+++ b/include/cru/parse/Production.hpp
@@ -7,7 +7,7 @@
#include <vector>
namespace cru::parse {
-class Production : public Object {
+class CRU_PARSE_API Production : public Object {
public:
Production(Grammar* grammar, String name, Nonterminal* left,
std::vector<Symbol*> right);
diff --git a/include/cru/parse/RecursiveDescentAlgorithm.hpp b/include/cru/parse/RecursiveDescentAlgorithm.hpp
index c12a84f6..373724ea 100644
--- a/include/cru/parse/RecursiveDescentAlgorithm.hpp
+++ b/include/cru/parse/RecursiveDescentAlgorithm.hpp
@@ -3,7 +3,7 @@
#include "ParsingAlgorithm.hpp"
namespace cru::parse {
-class RecursiveDescentAlgorithm : public ParsingAlgorithm {
+class CRU_PARSE_API RecursiveDescentAlgorithm : public ParsingAlgorithm {
public:
RecursiveDescentAlgorithm() = default;
diff --git a/include/cru/parse/RecursiveDescentAlgorithmContext.hpp b/include/cru/parse/RecursiveDescentAlgorithmContext.hpp
index 1b888da9..b29ee1a1 100644
--- a/include/cru/parse/RecursiveDescentAlgorithmContext.hpp
+++ b/include/cru/parse/RecursiveDescentAlgorithmContext.hpp
@@ -6,7 +6,7 @@
#include "cru/parse/Terminal.hpp"
namespace cru::parse {
-class RecursiveDescentAlgorithmContext : public ParsingAlgorithmContext {
+class CRU_PARSE_API RecursiveDescentAlgorithmContext : public ParsingAlgorithmContext {
public:
RecursiveDescentAlgorithmContext(Grammar* grammar,
const RecursiveDescentAlgorithm* algorithm);
diff --git a/include/cru/parse/Symbol.hpp b/include/cru/parse/Symbol.hpp
index e22fb9bc..7404a5e7 100644
--- a/include/cru/parse/Symbol.hpp
+++ b/include/cru/parse/Symbol.hpp
@@ -1,11 +1,13 @@
#pragma once
+#include "Base.hpp"
+
#include "cru/common/String.hpp"
namespace cru::parse {
class Grammar;
// Base class of Terminal and Nonterminal.
-class Symbol : public Object {
+class CRU_PARSE_API Symbol : public Object {
public:
explicit Symbol(Grammar* grammar, String name);
diff --git a/include/cru/parse/Terminal.hpp b/include/cru/parse/Terminal.hpp
index 8d4a31b6..4ff8f898 100644
--- a/include/cru/parse/Terminal.hpp
+++ b/include/cru/parse/Terminal.hpp
@@ -2,7 +2,7 @@
#include "Symbol.hpp"
namespace cru::parse {
-class Terminal : public Symbol {
+class CRU_PARSE_API Terminal : public Symbol {
public:
Terminal(Grammar* grammar, String name);
diff --git a/include/cru/parse/TokenType.hpp b/include/cru/parse/TokenType.hpp
index 54bdf712..49415d3b 100644
--- a/include/cru/parse/TokenType.hpp
+++ b/include/cru/parse/TokenType.hpp
@@ -1,9 +1,11 @@
#pragma once
+#include "Base.hpp"
+
#include "cru/common/Base.hpp"
#include "cru/common/String.hpp"
namespace cru::parse {
-class TokenType : public Object {
+class CRU_PARSE_API TokenType : public Object {
public:
explicit TokenType(String name);
diff --git a/include/cru/platform/graphics/Base.hpp b/include/cru/platform/graphics/Base.hpp
index 26ae725a..3a18e39d 100644
--- a/include/cru/platform/graphics/Base.hpp
+++ b/include/cru/platform/graphics/Base.hpp
@@ -6,6 +6,17 @@
#include <memory>
+#ifdef CRU_PLATFORM_WINDOWS
+#ifdef CRU_PLATFORM_GRAPHICS_EXPORT_API
+#define CRU_PLATFORM_GRAPHICS_API __declspec(dllexport)
+#else
+#define CRU_PLATFORM_GRAPHICS_API __declspec(dllimport)
+#endif
+#else
+#define CRU_PLATFORM_GRAPHICS_API
+#endif
+
+
namespace cru::platform::graphics {
// forward declarations
struct IGraphicsFactory;
diff --git a/include/cru/platform/graphics/Brush.hpp b/include/cru/platform/graphics/Brush.hpp
index aa21f79d..772edd5c 100644
--- a/include/cru/platform/graphics/Brush.hpp
+++ b/include/cru/platform/graphics/Brush.hpp
@@ -2,9 +2,9 @@
#include "Resource.hpp"
namespace cru::platform::graphics {
-struct IBrush : virtual IGraphicsResource {};
+struct CRU_PLATFORM_GRAPHICS_API IBrush : virtual IGraphicsResource {};
-struct ISolidColorBrush : virtual IBrush {
+struct CRU_PLATFORM_GRAPHICS_API ISolidColorBrush : virtual IBrush {
virtual Color GetColor() = 0;
virtual void SetColor(const Color& color) = 0;
};
diff --git a/include/cru/platform/graphics/Factory.hpp b/include/cru/platform/graphics/Factory.hpp
index b79e1c4f..f3802651 100644
--- a/include/cru/platform/graphics/Factory.hpp
+++ b/include/cru/platform/graphics/Factory.hpp
@@ -8,7 +8,7 @@
namespace cru::platform::graphics {
// Entry point of the graphics module.
-struct IGraphicsFactory : virtual IPlatformResource {
+struct CRU_PLATFORM_GRAPHICS_API IGraphicsFactory : 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 e1a419eb..2d1bc9a6 100644
--- a/include/cru/platform/graphics/Font.hpp
+++ b/include/cru/platform/graphics/Font.hpp
@@ -2,7 +2,7 @@
#include "Resource.hpp"
namespace cru::platform::graphics {
-struct IFont : virtual IGraphicsResource {
+struct CRU_PLATFORM_GRAPHICS_API IFont : virtual IGraphicsResource {
virtual float GetFontSize() = 0;
};
} // namespace cru::platform::graphics
diff --git a/include/cru/platform/graphics/Geometry.hpp b/include/cru/platform/graphics/Geometry.hpp
index f01132fb..e83d1c51 100644
--- a/include/cru/platform/graphics/Geometry.hpp
+++ b/include/cru/platform/graphics/Geometry.hpp
@@ -2,13 +2,13 @@
#include "Resource.hpp"
namespace cru::platform::graphics {
-struct IGeometry : virtual IGraphicsResource {
+struct CRU_PLATFORM_GRAPHICS_API IGeometry : virtual IGraphicsResource {
virtual bool FillContains(const Point& point) = 0;
};
// After called Build, calling every method will throw a
-struct IGeometryBuilder : virtual IGraphicsResource {
+struct CRU_PLATFORM_GRAPHICS_API IGeometryBuilder : virtual IGraphicsResource {
virtual void BeginFigure(const Point& point) = 0;
virtual void LineTo(const Point& point) = 0;
virtual void QuadraticBezierTo(const Point& control_point,
diff --git a/include/cru/platform/graphics/NullPainter.hpp b/include/cru/platform/graphics/NullPainter.hpp
index cf790ccf..b5c796d3 100644
--- a/include/cru/platform/graphics/NullPainter.hpp
+++ b/include/cru/platform/graphics/NullPainter.hpp
@@ -1,8 +1,9 @@
#pragma once
#include "Painter.hpp"
+#include "cru/common/Base.hpp"
namespace cru::platform::graphics {
-class NullPainter : public Object, public virtual IPainter {
+class CRU_PLATFORM_GRAPHICS_API NullPainter : public Object, public virtual IPainter {
public:
NullPainter() = default;
@@ -17,30 +18,54 @@ class NullPainter : public Object, public virtual IPainter {
String GetDebugString() override { return u"NullPainter"; }
Matrix GetTransform() override { return Matrix(); }
- void SetTransform(const Matrix& matrix) override {}
+ void SetTransform(const Matrix& matrix) override { CRU_UNUSED(matrix) }
- void ConcatTransform(const Matrix& matrix) override {}
+ void ConcatTransform(const Matrix& matrix) override { CRU_UNUSED(matrix) }
- void Clear(const Color& color) override {}
+ void Clear(const Color& color) override { CRU_UNUSED(color) }
void DrawLine(const Point& start, const Point& end, IBrush* brush,
- float width) override{};
+ float width) override {
+ CRU_UNUSED(start) CRU_UNUSED(end) CRU_UNUSED(brush) CRU_UNUSED(width)
+ }
void StrokeRectangle(const Rect& rectangle, IBrush* brush,
- float width) override {}
- void FillRectangle(const Rect& rectangle, IBrush* brush) override {}
+ float width) override {
+ CRU_UNUSED(rectangle) CRU_UNUSED(brush) CRU_UNUSED(width)
+ }
+ void FillRectangle(const Rect& rectangle, IBrush* brush) override {
+ CRU_UNUSED(rectangle)
+ CRU_UNUSED(brush)
+ }
void StrokeEllipse(const Rect& outline_rect, IBrush* brush,
- float width) override {}
- void FillEllipse(const Rect& outline_rect, IBrush* brush,
- float width) override {}
+ float width) override {
+ CRU_UNUSED(outline_rect)
+ CRU_UNUSED(brush)
+ CRU_UNUSED(width)
+ }
+ void FillEllipse(const Rect& outline_rect, IBrush* brush) override {
+ CRU_UNUSED(outline_rect)
+ CRU_UNUSED(brush)
+ }
void StrokeGeometry(IGeometry* geometry, IBrush* brush,
- float width) override {}
- void FillGeometry(IGeometry* geometry, IBrush* brush) override {}
+ float width) override {
+ CRU_UNUSED(geometry)
+ CRU_UNUSED(brush)
+ CRU_UNUSED(width)
+ }
+ void FillGeometry(IGeometry* geometry, IBrush* brush) override {
+ CRU_UNUSED(geometry)
+ CRU_UNUSED(brush)
+ }
void DrawText(const Point& offset, ITextLayout* text_layout,
- IBrush* brush) override {}
+ IBrush* brush) override {
+ CRU_UNUSED(offset)
+ CRU_UNUSED(text_layout)
+ CRU_UNUSED(brush)
+ }
- void PushLayer(const Rect& bounds) override{};
+ void PushLayer(const Rect& bounds) override { CRU_UNUSED(bounds) }
void PopLayer() override {}
diff --git a/include/cru/platform/graphics/Painter.hpp b/include/cru/platform/graphics/Painter.hpp
index 4f1724ec..4104a752 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 IPlatformResource {
+struct CRU_PLATFORM_GRAPHICS_API IPainter : virtual IPlatformResource {
virtual Matrix GetTransform() = 0;
virtual void SetTransform(const Matrix& matrix) = 0;
@@ -18,8 +18,7 @@ struct IPainter : virtual IPlatformResource {
virtual void FillRectangle(const Rect& rectangle, IBrush* brush) = 0;
virtual void StrokeEllipse(const Rect& outline_rect, IBrush* brush,
float width) = 0;
- virtual void FillEllipse(const Rect& outline_rect, IBrush* brush,
- float width) = 0;
+ virtual void FillEllipse(const Rect& outline_rect, IBrush* brush) = 0;
virtual void StrokeGeometry(IGeometry* geometry, IBrush* brush,
float width) = 0;
diff --git a/include/cru/platform/graphics/Resource.hpp b/include/cru/platform/graphics/Resource.hpp
index cd1e5283..e559b0e9 100644
--- a/include/cru/platform/graphics/Resource.hpp
+++ b/include/cru/platform/graphics/Resource.hpp
@@ -4,7 +4,7 @@
namespace cru::platform::graphics {
struct IGraphicsFactory;
-struct IGraphicsResource : virtual IPlatformResource {
+struct CRU_PLATFORM_GRAPHICS_API IGraphicsResource : virtual IPlatformResource {
virtual IGraphicsFactory* GetGraphicsFactory() = 0;
};
} // namespace cru::platform::graphics
diff --git a/include/cru/platform/graphics/TextLayout.hpp b/include/cru/platform/graphics/TextLayout.hpp
index a040ec3b..f9ccc824 100644
--- a/include/cru/platform/graphics/TextLayout.hpp
+++ b/include/cru/platform/graphics/TextLayout.hpp
@@ -7,7 +7,7 @@
namespace cru::platform::graphics {
// Requirement:
// All text must be left-top aligned.
-struct ITextLayout : virtual IGraphicsResource {
+struct CRU_PLATFORM_GRAPHICS_API ITextLayout : virtual IGraphicsResource {
virtual String GetText() = 0;
virtual void SetText(String new_text) = 0;
diff --git a/include/cru/platform/gui/Window.hpp b/include/cru/platform/gui/Window.hpp
index bab5e8fe..9f17b976 100644
--- a/include/cru/platform/gui/Window.hpp
+++ b/include/cru/platform/gui/Window.hpp
@@ -85,7 +85,6 @@ struct INativeWindow : virtual IPlatformResource {
// Remember to call EndDraw on return value and destroy it.
virtual std::unique_ptr<graphics::IPainter> BeginPaint() = 0;
- // Don't use this instance after receive this event.
virtual IEvent<std::nullptr_t>* CreateEvent() = 0;
virtual IEvent<std::nullptr_t>* DestroyEvent() = 0;
virtual IEvent<std::nullptr_t>* PaintEvent() = 0;
diff --git a/include/cru/toml/Base.hpp b/include/cru/toml/Base.hpp
new file mode 100644
index 00000000..de1d558c
--- /dev/null
+++ b/include/cru/toml/Base.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#ifdef CRU_PLATFORM_WINDOWS
+#ifdef CRU_TOML_EXPORT_API
+#define CRU_TOML_API __declspec(dllexport)
+#else
+#define CRU_TOML_API __declspec(dllimport)
+#endif
+#else
+#define CRU_TOML_API
+#endif
diff --git a/include/cru/toml/TomlDocument.hpp b/include/cru/toml/TomlDocument.hpp
index 637690f7..1e5caf71 100644
--- a/include/cru/toml/TomlDocument.hpp
+++ b/include/cru/toml/TomlDocument.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include "Base.hpp"
+
#include "cru/common/Base.hpp"
#include "cru/common/String.hpp"
@@ -7,7 +9,7 @@
#include <unordered_map>
namespace cru::toml {
-class TomlSection {
+class CRU_TOML_API TomlSection {
public:
CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(TomlSection)
CRU_DEFAULT_COPY(TomlSection)
@@ -29,7 +31,7 @@ class TomlSection {
std::unordered_map<String, String> values_;
};
-class TomlDocument {
+class CRU_TOML_API TomlDocument {
public:
CRU_DEFAULT_CONSTRUCTOR_DESTRUCTOR(TomlDocument)
CRU_DEFAULT_COPY(TomlDocument)
diff --git a/include/cru/toml/TomlParser.hpp b/include/cru/toml/TomlParser.hpp
index 52332506..c3091bad 100644
--- a/include/cru/toml/TomlParser.hpp
+++ b/include/cru/toml/TomlParser.hpp
@@ -7,12 +7,12 @@
namespace cru::toml {
// A very simple and tolerant TOML parser.
-class TomlParsingException : public Exception {
+class CRU_TOML_API TomlParsingException : public Exception {
public:
using Exception::Exception;
};
-class TomlParser {
+class CRU_TOML_API TomlParser {
public:
explicit TomlParser(String input);
diff --git a/include/cru/win/WinPreConfig.hpp b/include/cru/win/WinPreConfig.hpp
index 1613da95..1bd494f2 100644
--- a/include/cru/win/WinPreConfig.hpp
+++ b/include/cru/win/WinPreConfig.hpp
@@ -8,6 +8,7 @@
#undef CreateWindow
#undef DrawText
#undef CreateFont
+#undef CreateEvent
#include <d2d1_2.h>
#include <d3d11.h>
diff --git a/include/cru/win/graphics/direct/Brush.hpp b/include/cru/win/graphics/direct/Brush.hpp
index fbff83b5..9d8e5384 100644
--- a/include/cru/win/graphics/direct/Brush.hpp
+++ b/include/cru/win/graphics/direct/Brush.hpp
@@ -9,12 +9,12 @@ struct ID2DBrush : virtual IBrush {
virtual ID2D1Brush* GetD2DBrushInterface() const = 0;
};
-class D2DSolidColorBrush : public DirectGraphResource,
+class D2DSolidColorBrush : public DirectGraphicsResource,
public virtual ISolidColorBrush,
public virtual ID2DBrush,
public virtual IComResource<ID2D1SolidColorBrush> {
public:
- explicit D2DSolidColorBrush(DirectGraphFactory* factory);
+ explicit D2DSolidColorBrush(DirectGraphicsFactory* factory);
CRU_DELETE_COPY(D2DSolidColorBrush)
CRU_DELETE_MOVE(D2DSolidColorBrush)
diff --git a/include/cru/win/graphics/direct/Factory.hpp b/include/cru/win/graphics/direct/Factory.hpp
index 70f3ede1..efcebba7 100644
--- a/include/cru/win/graphics/direct/Factory.hpp
+++ b/include/cru/win/graphics/direct/Factory.hpp
@@ -4,14 +4,15 @@
#include "cru/platform/graphics/Factory.hpp"
namespace cru::platform::graphics::win::direct {
-class DirectGraphFactory : public DirectResource, public virtual IGraphFactory {
+class DirectGraphicsFactory : public DirectResource,
+ public virtual IGraphicsFactory {
public:
- DirectGraphFactory();
+ DirectGraphicsFactory();
- CRU_DELETE_COPY(DirectGraphFactory)
- CRU_DELETE_MOVE(DirectGraphFactory)
+ CRU_DELETE_COPY(DirectGraphicsFactory)
+ CRU_DELETE_MOVE(DirectGraphicsFactory)
- ~DirectGraphFactory() override;
+ ~DirectGraphicsFactory() override;
public:
ID3D11Device* GetD3D11Device() const { return d3d11_device_.Get(); }
@@ -38,11 +39,11 @@ class DirectGraphFactory : public DirectResource, public virtual IGraphFactory {
std::unique_ptr<IGeometryBuilder> CreateGeometryBuilder() override;
- std::unique_ptr<IFont> CreateFont(std::u16string font_family,
+ std::unique_ptr<IFont> CreateFont(String font_family,
float font_size) override;
std::unique_ptr<ITextLayout> CreateTextLayout(std::shared_ptr<IFont> font,
- std::u16string text) override;
+ String text) override;
private:
Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_;
diff --git a/include/cru/win/graphics/direct/Font.hpp b/include/cru/win/graphics/direct/Font.hpp
index fd3921a3..3cd94f82 100644
--- a/include/cru/win/graphics/direct/Font.hpp
+++ b/include/cru/win/graphics/direct/Font.hpp
@@ -7,11 +7,11 @@
#include <string_view>
namespace cru::platform::graphics::win::direct {
-class DWriteFont : public DirectGraphResource,
+class DWriteFont : public DirectGraphicsResource,
public virtual IFont,
public virtual IComResource<IDWriteTextFormat> {
public:
- DWriteFont(DirectGraphFactory* factory, std::u16string font_family,
+ DWriteFont(DirectGraphicsFactory* factory, String font_family,
float font_size);
CRU_DELETE_COPY(DWriteFont)
@@ -27,7 +27,7 @@ class DWriteFont : public DirectGraphResource,
float GetFontSize() override;
private:
- std::u16string font_family_;
+ String font_family_;
Microsoft::WRL::ComPtr<IDWriteTextFormat> text_format_;
};
} // namespace cru::platform::graphics::win::direct
diff --git a/include/cru/win/graphics/direct/Geometry.hpp b/include/cru/win/graphics/direct/Geometry.hpp
index edfec590..b3b82f9c 100644
--- a/include/cru/win/graphics/direct/Geometry.hpp
+++ b/include/cru/win/graphics/direct/Geometry.hpp
@@ -5,10 +5,10 @@
#include "cru/platform/graphics/Geometry.hpp"
namespace cru::platform::graphics::win::direct {
-class D2DGeometryBuilder : public DirectGraphResource,
+class D2DGeometryBuilder : public DirectGraphicsResource,
public virtual IGeometryBuilder {
public:
- explicit D2DGeometryBuilder(DirectGraphFactory* factory);
+ explicit D2DGeometryBuilder(DirectGraphicsFactory* factory);
CRU_DELETE_COPY(D2DGeometryBuilder)
CRU_DELETE_MOVE(D2DGeometryBuilder)
@@ -33,11 +33,11 @@ class D2DGeometryBuilder : public DirectGraphResource,
Microsoft::WRL::ComPtr<ID2D1GeometrySink> geometry_sink_;
};
-class D2DGeometry : public DirectGraphResource,
+class D2DGeometry : public DirectGraphicsResource,
public virtual IGeometry,
public IComResource<ID2D1Geometry> {
public:
- D2DGeometry(DirectGraphFactory* factory,
+ D2DGeometry(DirectGraphicsFactory* factory,
Microsoft::WRL::ComPtr<ID2D1PathGeometry> geometry);
CRU_DELETE_COPY(D2DGeometry)
diff --git a/include/cru/win/graphics/direct/Painter.hpp b/include/cru/win/graphics/direct/Painter.hpp
index b34c1563..d7b90d19 100644
--- a/include/cru/win/graphics/direct/Painter.hpp
+++ b/include/cru/win/graphics/direct/Painter.hpp
@@ -24,6 +24,7 @@ class D2DPainter : public DirectResource,
public:
Matrix GetTransform() override;
void SetTransform(const platform::Matrix& matrix) override;
+ void ConcatTransform(const Matrix& matrix) override;
void Clear(const Color& color) override;
@@ -32,6 +33,9 @@ class D2DPainter : public DirectResource,
void StrokeRectangle(const Rect& rectangle, IBrush* brush,
float width) override;
void FillRectangle(const Rect& rectangle, IBrush* brush) override;
+ void StrokeEllipse(const Rect& outline_rect, IBrush* brush,
+ float width) override;
+ void FillEllipse(const Rect& outline_rect, IBrush* brush) override;
void StrokeGeometry(IGeometry* geometry, IBrush* brush, float width) override;
void FillGeometry(IGeometry* geometry, IBrush* brush) override;
@@ -40,9 +44,11 @@ class D2DPainter : public DirectResource,
IBrush* brush) override;
void PushLayer(const Rect& bounds) override;
-
void PopLayer() override;
+ void PushState() override;
+ void PopState() override;
+
void EndDraw() override final;
protected:
@@ -56,6 +62,8 @@ class D2DPainter : public DirectResource,
ID2D1RenderTarget* render_target_;
std::vector<Microsoft::WRL::ComPtr<ID2D1Layer>> layers_;
+ std::vector<Microsoft::WRL::ComPtr<ID2D1DrawingStateBlock>>
+ drawing_state_stack_;
bool is_drawing_ = true;
};
diff --git a/include/cru/win/graphics/direct/Resource.hpp b/include/cru/win/graphics/direct/Resource.hpp
index e6ffb203..c376628d 100644
--- a/include/cru/win/graphics/direct/Resource.hpp
+++ b/include/cru/win/graphics/direct/Resource.hpp
@@ -6,7 +6,7 @@
#include <string_view>
namespace cru::platform::graphics::win::direct {
-class DirectGraphFactory;
+class DirectGraphicsFactory;
class DirectResource : public Object, public virtual IPlatformResource {
public:
@@ -25,25 +25,25 @@ class DirectResource : public Object, public virtual IPlatformResource {
String GetPlatformId() const final { return kPlatformId; }
};
-class DirectGraphResource : public DirectResource,
- public virtual IGraphResource {
+class DirectGraphicsResource : public DirectResource,
+ public virtual IGraphicsResource {
protected:
// Param factory can't be null.
- explicit DirectGraphResource(DirectGraphFactory* factory);
+ explicit DirectGraphicsResource(DirectGraphicsFactory* factory);
public:
- CRU_DELETE_COPY(DirectGraphResource)
- CRU_DELETE_MOVE(DirectGraphResource)
+ CRU_DELETE_COPY(DirectGraphicsResource)
+ CRU_DELETE_MOVE(DirectGraphicsResource)
- ~DirectGraphResource() override = default;
+ ~DirectGraphicsResource() override = default;
public:
- IGraphFactory* GetGraphFactory() final;
+ IGraphicsFactory* GetGraphicsFactory() final;
public:
- DirectGraphFactory* GetDirectFactory() const { return factory_; }
+ DirectGraphicsFactory* GetDirectFactory() const { return factory_; }
private:
- DirectGraphFactory* factory_;
+ DirectGraphicsFactory* factory_;
};
} // namespace cru::platform::graphics::win::direct
diff --git a/include/cru/win/graphics/direct/TextLayout.hpp b/include/cru/win/graphics/direct/TextLayout.hpp
index aa040278..b1843dd7 100644
--- a/include/cru/win/graphics/direct/TextLayout.hpp
+++ b/include/cru/win/graphics/direct/TextLayout.hpp
@@ -10,12 +10,12 @@
namespace cru::platform::graphics::win::direct {
class DWriteFont;
-class DWriteTextLayout : public DirectGraphResource,
+class DWriteTextLayout : public DirectGraphicsResource,
public virtual ITextLayout,
public virtual IComResource<IDWriteTextLayout> {
public:
- DWriteTextLayout(DirectGraphFactory* factory, std::shared_ptr<IFont> font,
- std::u16string text);
+ DWriteTextLayout(DirectGraphicsFactory* factory, std::shared_ptr<IFont> font,
+ String text);
CRU_DELETE_COPY(DWriteTextLayout)
CRU_DELETE_MOVE(DWriteTextLayout)
@@ -28,9 +28,8 @@ class DWriteTextLayout : public DirectGraphResource,
}
public:
- std::u16string GetText() override;
- std::u16string_view GetTextView() override;
- void SetText(std::u16string new_text) override;
+ String GetText() override;
+ void SetText(String new_text) override;
std::shared_ptr<IFont> GetFont() override;
void SetFont(std::shared_ptr<IFont> font) override;
@@ -38,15 +37,23 @@ class DWriteTextLayout : public DirectGraphResource,
void SetMaxWidth(float max_width) override;
void SetMaxHeight(float max_height) override;
+ bool IsEditMode() override;
+ void SetEditMode(bool enable) override;
+
+ Index GetLineIndexFromCharIndex(Index char_index) override;
+ float GetLineHeight(Index line_index) override;
+ Index GetLineCount() override;
+
Rect GetTextBounds(bool includingTrailingSpace = false) override;
// Return empty vector if text_range.count is 0. Text range could be in
// reverse direction, it should be normalized first in implementation.
std::vector<Rect> TextRangeRect(const TextRange& text_range) override;
- Point TextSinglePoint(Index position, bool trailing) override;
+ Rect TextSinglePoint(Index position, bool trailing) override;
TextHitTestResult HitTest(const Point& point) override;
private:
- std::u16string text_;
+ bool edit_mode_ = false;
+ String text_;
std::shared_ptr<DWriteFont> font_;
float max_width_ = std::numeric_limits<float>::max();
float max_height_ = std::numeric_limits<float>::max();
diff --git a/include/cru/win/graphics/direct/WindowRenderTarget.hpp b/include/cru/win/graphics/direct/WindowRenderTarget.hpp
index 75b1bf20..c197841d 100644
--- a/include/cru/win/graphics/direct/WindowRenderTarget.hpp
+++ b/include/cru/win/graphics/direct/WindowRenderTarget.hpp
@@ -5,7 +5,7 @@ namespace cru::platform::graphics::win::direct {
// Represents a window render target.
class D2DWindowRenderTarget : public Object {
public:
- D2DWindowRenderTarget(gsl::not_null<DirectGraphFactory*> factory, HWND hwnd);
+ D2DWindowRenderTarget(gsl::not_null<DirectGraphicsFactory*> factory, HWND hwnd);
CRU_DELETE_COPY(D2DWindowRenderTarget)
CRU_DELETE_MOVE(D2DWindowRenderTarget)
@@ -13,7 +13,7 @@ class D2DWindowRenderTarget : public Object {
~D2DWindowRenderTarget() override = default;
public:
- graphics::win::direct::DirectGraphFactory* GetDirectFactory() const {
+ graphics::win::direct::DirectGraphicsFactory* GetDirectFactory() const {
return factory_;
}
@@ -33,7 +33,7 @@ class D2DWindowRenderTarget : public Object {
void CreateTargetBitmap();
private:
- DirectGraphFactory* factory_;
+ DirectGraphicsFactory* factory_;
HWND hwnd_;
Microsoft::WRL::ComPtr<ID2D1DeviceContext> d2d1_device_context_;
Microsoft::WRL::ComPtr<IDXGISwapChain1> dxgi_swap_chain_;
diff --git a/include/cru/win/gui/GodWindow.hpp b/include/cru/win/gui/GodWindow.hpp
index 0343b159..d9a128e6 100644
--- a/include/cru/win/gui/GodWindow.hpp
+++ b/include/cru/win/gui/GodWindow.hpp
@@ -3,6 +3,7 @@
#include "WindowNativeMessageEventArgs.hpp"
#include "cru/common/Event.hpp"
+#include "cru/common/String.hpp"
#include <memory>
diff --git a/include/cru/win/gui/InputMethod.hpp b/include/cru/win/gui/InputMethod.hpp
index 51a007d8..3784dcda 100644
--- a/include/cru/win/gui/InputMethod.hpp
+++ b/include/cru/win/gui/InputMethod.hpp
@@ -65,12 +65,12 @@ class WinInputMethodContext : public WinNativeResource,
IEvent<std::nullptr_t>* CompositionEvent() override;
- IEvent<std::u16string_view>* TextEvent() override;
+ IEvent<StringView>* TextEvent() override;
private:
void OnWindowNativeMessage(WindowNativeMessageEventArgs& args);
- std::u16string GetResultString();
+ String GetResultString();
AutoHIMC GetHIMC();
@@ -82,6 +82,6 @@ class WinInputMethodContext : public WinNativeResource,
Event<std::nullptr_t> composition_start_event_;
Event<std::nullptr_t> composition_end_event_;
Event<std::nullptr_t> composition_event_;
- Event<std::u16string_view> text_event_;
+ Event<StringView> text_event_;
};
} // namespace cru::platform::gui::win
diff --git a/include/cru/win/gui/UiApplication.hpp b/include/cru/win/gui/UiApplication.hpp
index 4cf46858..4b972fee 100644
--- a/include/cru/win/gui/UiApplication.hpp
+++ b/include/cru/win/gui/UiApplication.hpp
@@ -7,7 +7,7 @@
#include <memory>
namespace cru::platform::graphics::win::direct {
-class DirectGraphFactory;
+class DirectGraphicsFactory;
}
namespace cru::platform::gui::win {
@@ -33,6 +33,13 @@ class WinUiApplication : public WinNativeResource,
void AddOnQuitHandler(std::function<void()> handler) override;
+ bool IsQuitOnAllWindowClosed() override {
+ return is_quit_on_all_window_closed_;
+ }
+ void SetQuitOnAllWindowClosed(bool quit_on_all_window_closed) override {
+ is_quit_on_all_window_closed_ = quit_on_all_window_closed;
+ }
+
long long SetImmediate(std::function<void()> action) override;
long long SetTimeout(std::chrono::milliseconds milliseconds,
std::function<void()> action) override;
@@ -41,16 +48,19 @@ class WinUiApplication : public WinNativeResource,
void CancelTimer(long long id) override;
std::vector<INativeWindow*> GetAllWindow() override;
- INativeWindow* CreateWindow(INativeWindow* parent, CreateWindowFlag flag) override;
+ INativeWindow* CreateWindow() override;
- cru::platform::graphics::IGraphFactory* GetGraphFactory() override;
+ cru::platform::graphics::IGraphicsFactory* GetGraphicsFactory() override;
- cru::platform::graphics::win::direct::DirectGraphFactory* GetDirectFactory() {
+ cru::platform::graphics::win::direct::DirectGraphicsFactory*
+ GetDirectFactory() {
return graph_factory_.get();
}
ICursorManager* GetCursorManager() override;
+ IClipboard* GetClipboard() override;
+
HINSTANCE GetInstanceHandle() const { return instance_handle_; }
GodWindow* GetGodWindow() const { return god_window_.get(); }
@@ -60,7 +70,9 @@ class WinUiApplication : public WinNativeResource,
private:
HINSTANCE instance_handle_;
- std::unique_ptr<cru::platform::graphics::win::direct::DirectGraphFactory>
+ bool is_quit_on_all_window_closed_ = true;
+
+ std::unique_ptr<cru::platform::graphics::win::direct::DirectGraphicsFactory>
graph_factory_;
std::unique_ptr<GodWindow> god_window_;
diff --git a/include/cru/win/gui/Window.hpp b/include/cru/win/gui/Window.hpp
index 97a74fa7..41eac5fa 100644
--- a/include/cru/win/gui/Window.hpp
+++ b/include/cru/win/gui/Window.hpp
@@ -2,7 +2,6 @@
#include "Resource.hpp"
#include "WindowNativeMessageEventArgs.hpp"
-#include "cru/platform/GraphBase.hpp"
#include "cru/platform/gui/Base.hpp"
#include "cru/platform/gui/Window.hpp"
#include "cru/win/graphics/direct/WindowRenderTarget.hpp"
@@ -14,8 +13,7 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow {
CRU_DEFINE_CLASS_LOG_TAG(u"cru::platform::gui::win::WinNativeWindow")
public:
- WinNativeWindow(WinUiApplication* application, WindowClass* window_class,
- DWORD window_style, WinNativeWindow* parent);
+ explicit WinNativeWindow(WinUiApplication* application);
CRU_DELETE_COPY(WinNativeWindow)
CRU_DELETE_MOVE(WinNativeWindow)
@@ -26,13 +24,20 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow {
void Close() override;
WinNativeWindow* GetParent() override { return parent_window_; }
+ void SetParent(INativeWindow* parent) override;
- bool IsVisible() override;
- void SetVisible(bool is_visible) override;
+ WindowStyleFlag GetStyleFlag() override { return style_flag_; }
+ void SetStyleFlag(WindowStyleFlag flag) override;
+
+ WindowVisibilityType GetVisibility() override { return visibility_; }
+ void SetVisibility(WindowVisibilityType visibility) override;
Size GetClientSize() override;
void SetClientSize(const Size& size) override;
+ Rect GetClientRect() override;
+ void SetClientRect(const Rect& rect) override;
+
// Get the rect of the window containing frame.
// The lefttop of the rect is relative to screen lefttop.
Rect GetWindowRect() override;
@@ -41,6 +46,8 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow {
// The lefttop of the rect is relative to screen lefttop.
void SetWindowRect(const Rect& rect) override;
+ bool RequestFocus() override;
+
Point GetMousePosition() override;
bool CaptureMouse() override;
@@ -51,8 +58,12 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow {
void SetCursor(std::shared_ptr<ICursor> cursor) override;
+ IEvent<std::nullptr_t>* CreateEvent() override { return &create_event_; }
IEvent<std::nullptr_t>* DestroyEvent() override { return &destroy_event_; }
IEvent<std::nullptr_t>* PaintEvent() override { return &paint_event_; }
+ IEvent<WindowVisibilityType>* VisibilityChangeEvent() override {
+ return &visibility_change_event_;
+ }
IEvent<Size>* ResizeEvent() override { return &resize_event_; }
IEvent<FocusChangeType>* FocusEvent() override { return &focus_event_; }
IEvent<MouseEnterLeaveType>* MouseEnterLeaveEvent() override {
@@ -106,6 +117,15 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow {
return result;
}
+ inline RECT DipToPixel(const Rect& dip_rect) {
+ RECT result;
+ result.left = DipToPixel(dip_rect.left);
+ result.top = DipToPixel(dip_rect.top);
+ result.right = DipToPixel(dip_rect.GetRight());
+ result.bottom = DipToPixel(dip_rect.GetBottom());
+ return result;
+ }
+
inline float PixelToDip(const int pixel) {
return static_cast<float>(pixel) * 96.0f / GetDpi();
}
@@ -114,14 +134,24 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow {
return Point(PixelToDip(pi_point.x), PixelToDip(pi_point.y));
}
+ inline Rect PixelToDip(const RECT& pi_rect) {
+ return Rect::FromVertices(PixelToDip(pi_rect.left), PixelToDip(pi_rect.top),
+ PixelToDip(pi_rect.right),
+ PixelToDip(pi_rect.bottom));
+ }
+
private:
// Get the client rect in pixel.
RECT GetClientRectPixel();
+ void RecreateWindow();
+
//*************** region: native messages ***************
+ void OnCreateInternal();
void OnDestroyInternal();
void OnPaintInternal();
+ void OnMoveInternal(int new_left, int new_top);
void OnResizeInternal(int new_width, int new_height);
void OnSetFocusInternal();
@@ -142,15 +172,12 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow {
private:
WinUiApplication* application_;
- // when delete is called first, it set this to true to indicate
- // destroy message handler not to double delete this instance;
- // when destroy handler is called first (by user action or method
- // Close), it set this to true to indicate delete not call Close
- // again.
- bool sync_flag_ = false;
+ WindowStyleFlag style_flag_{};
+ WindowVisibilityType visibility_ = WindowVisibilityType::Hide;
+ Rect client_rect_{100, 100, 400, 300};
- HWND hwnd_;
- WinNativeWindow* parent_window_;
+ HWND hwnd_ = nullptr;
+ WinNativeWindow* parent_window_ = nullptr;
float dpi_;
@@ -164,9 +191,11 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow {
std::unique_ptr<WinInputMethodContext> input_method_context_;
+ Event<std::nullptr_t> create_event_;
Event<std::nullptr_t> destroy_event_;
Event<std::nullptr_t> paint_event_;
Event<Size> resize_event_;
+ Event<WindowVisibilityType> visibility_change_event_;
Event<FocusChangeType> focus_event_;
Event<MouseEnterLeaveType> mouse_enter_leave_event_;
Event<Point> mouse_move_event_;
diff --git a/include/cru/xml/Base.hpp b/include/cru/xml/Base.hpp
new file mode 100644
index 00000000..5d6fe144
--- /dev/null
+++ b/include/cru/xml/Base.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#ifdef CRU_PLATFORM_WINDOWS
+#ifdef CRU_XML_EXPORT_API
+#define CRU_XML_API __declspec(dllexport)
+#else
+#define CRU_XML_API __declspec(dllimport)
+#endif
+#else
+#define CRU_XML_API
+#endif
diff --git a/include/cru/xml/XmlNode.hpp b/include/cru/xml/XmlNode.hpp
index cf2543c9..38f09d14 100644
--- a/include/cru/xml/XmlNode.hpp
+++ b/include/cru/xml/XmlNode.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include "Base.hpp"
+
#include "cru/common/String.hpp"
#include <algorithm>
@@ -10,7 +12,7 @@ namespace cru::xml {
class XmlElementNode;
class XmlTextNode;
-class XmlNode {
+class CRU_XML_API XmlNode {
friend XmlElementNode;
public:
@@ -40,7 +42,7 @@ class XmlNode {
XmlElementNode* parent_ = nullptr;
};
-class XmlTextNode : public XmlNode {
+class CRU_XML_API XmlTextNode : public XmlNode {
public:
XmlTextNode() : XmlNode(Type::Text) {}
explicit XmlTextNode(String text)
@@ -61,7 +63,7 @@ class XmlTextNode : public XmlNode {
String text_;
};
-class XmlElementNode : public XmlNode {
+class CRU_XML_API XmlElementNode : public XmlNode {
public:
XmlElementNode() : XmlNode(Type::Element) {}
explicit XmlElementNode(String tag,
@@ -86,9 +88,9 @@ class XmlElementNode : public XmlNode {
}
const std::vector<XmlNode*> GetChildren() const { return children_; }
- int GetChildCount() const { return children_.size(); }
+ Index GetChildCount() const { return children_.size(); }
String GetAttribute(const String& key) const { return attributes_.at(key); }
- XmlNode* GetChildAt(int index) const { return children_[index]; }
+ XmlNode* GetChildAt(Index index) const { return children_[index]; }
void AddAttribute(String key, String value);
void AddChild(XmlNode* child);
diff --git a/include/cru/xml/XmlParser.hpp b/include/cru/xml/XmlParser.hpp
index 188a08f2..e916cc53 100644
--- a/include/cru/xml/XmlParser.hpp
+++ b/include/cru/xml/XmlParser.hpp
@@ -8,12 +8,12 @@
#include <optional>
namespace cru::xml {
-class XmlParsingException : public Exception {
+class CRU_XML_API XmlParsingException : public Exception {
public:
using Exception::Exception;
};
-class XmlParser {
+class CRU_XML_API XmlParser {
public:
explicit XmlParser(String xml);
diff --git a/src/common/String.cpp b/src/common/String.cpp
index 1c2ff022..21f3f235 100644
--- a/src/common/String.cpp
+++ b/src/common/String.cpp
@@ -39,13 +39,20 @@ String::String(const_pointer str, Index size) {
this->capacity_ = size;
}
+String::String(size_type size, value_type ch) : String() {
+ reserve(size);
+ for (Index i = 0; i < size; i++) {
+ append(ch);
+ }
+}
+
String::String(std::initializer_list<char16_t> l)
: String(l.begin(), l.size()) {}
#ifdef CRU_PLATFORM_WINDOWS
String::String(const wchar_t* str) : String(str, GetStrSize(str)) {}
String::String(const wchar_t* str, Index size)
- : String(reinterpret_cast<const std::uint16_t*>(str), size) {}
+ : String(reinterpret_cast<const char16_t*>(str), size) {}
#endif
String::String(const String& other) {
@@ -426,7 +433,7 @@ std::vector<FormatToken> ParseToFormatTokenList(const String& str) {
void FormatAppendFromFormatTokenList(
String& current, const std::vector<FormatToken>& format_token_list,
Index index) {
- for (Index i = index; i < format_token_list.size(); i++) {
+ for (Index i = index; i < static_cast<Index>(format_token_list.size()); i++) {
const auto& token = format_token_list[i];
if (token.type == FormatTokenType::PlaceHolder) {
current += u"{}";
diff --git a/src/common/StringUtil.cpp b/src/common/StringUtil.cpp
index 440db8c4..6e478033 100644
--- a/src/common/StringUtil.cpp
+++ b/src/common/StringUtil.cpp
@@ -113,6 +113,8 @@ CodePoint Utf16NextCodePoint(const char16_t* ptr, Index size, Index current,
CodePoint Utf16PreviousCodePoint(const char16_t* ptr, Index size, Index current,
Index* previous_position) {
+ CRU_UNUSED(size)
+
CodePoint result;
if (current <= 0) {
result = k_invalid_code_point;
diff --git a/src/osx/graphics/quartz/Painter.cpp b/src/osx/graphics/quartz/Painter.cpp
index 798e1256..9750d6a5 100644
--- a/src/osx/graphics/quartz/Painter.cpp
+++ b/src/osx/graphics/quartz/Painter.cpp
@@ -109,7 +109,7 @@ void QuartzCGContextPainter::StrokeEllipse(const Rect& outline_rect,
}
void QuartzCGContextPainter::FillEllipse(const Rect& outline_rect,
- IBrush* brush, float width) {
+ IBrush* brush) {
Validate();
QuartzBrush* b = CheckPlatform<QuartzBrush>(brush, GetPlatformId());
diff --git a/src/parse/CMakeLists.txt b/src/parse/CMakeLists.txt
index 72bac707..17b26a3a 100644
--- a/src/parse/CMakeLists.txt
+++ b/src/parse/CMakeLists.txt
@@ -13,4 +13,5 @@ add_library(cru_parse SHARED
Token.cpp
TokenType.cpp
)
+target_compile_definitions(cru_parse PRIVATE CRU_PARSE_EXPORT_API)
target_link_libraries(cru_parse PUBLIC cru_base)
diff --git a/src/parse/RecursiveDescentAlgorithm.cpp b/src/parse/RecursiveDescentAlgorithm.cpp
index a6549f8a..8ff2571d 100644
--- a/src/parse/RecursiveDescentAlgorithm.cpp
+++ b/src/parse/RecursiveDescentAlgorithm.cpp
@@ -4,6 +4,7 @@
namespace cru::parse {
bool RecursiveDescentAlgorithm::CanHandle(Grammar *grammar) const {
+ CRU_UNUSED(grammar);
return true;
}
diff --git a/src/parse/RecursiveDescentAlgorithmContext.cpp b/src/parse/RecursiveDescentAlgorithmContext.cpp
index 8de0abc4..acfd9eee 100644
--- a/src/parse/RecursiveDescentAlgorithmContext.cpp
+++ b/src/parse/RecursiveDescentAlgorithmContext.cpp
@@ -10,6 +10,7 @@ RecursiveDescentAlgorithmContext::~RecursiveDescentAlgorithmContext() = default;
ParsingTreeNode* RecursiveDescentAlgorithmContext::Parse(
const std::vector<Terminal*>& input) {
+ CRU_UNUSED(input)
// TODO: Implement this.
return nullptr;
}
diff --git a/src/platform/graphics/CMakeLists.txt b/src/platform/graphics/CMakeLists.txt
index 7d86db40..692f8e70 100644
--- a/src/platform/graphics/CMakeLists.txt
+++ b/src/platform/graphics/CMakeLists.txt
@@ -1,5 +1,6 @@
set(CRU_PLATFORM_GRAPHICS_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/platform/graphics)
add_library(cru_platform_graphics SHARED
+ ForDllExport.cpp
NullPainter.cpp
)
target_sources(cru_platform_graphics PUBLIC
@@ -14,4 +15,5 @@ target_sources(cru_platform_graphics PUBLIC
${CRU_PLATFORM_GRAPHICS_INCLUDE_DIR}/TextLayout.hpp
${CRU_PLATFORM_GRAPHICS_INCLUDE_DIR}/util/Painter.hpp
)
+target_compile_definitions(cru_platform_graphics PRIVATE CRU_PLATFORM_GRAPHICS_EXPORT_API)
target_link_libraries(cru_platform_graphics PUBLIC cru_platform_base)
diff --git a/src/platform/graphics/ForDllExport.cpp b/src/platform/graphics/ForDllExport.cpp
new file mode 100644
index 00000000..1a571365
--- /dev/null
+++ b/src/platform/graphics/ForDllExport.cpp
@@ -0,0 +1,7 @@
+#include "cru/platform/graphics/Brush.hpp"
+#include "cru/platform/graphics/Factory.hpp"
+#include "cru/platform/graphics/Font.hpp"
+#include "cru/platform/graphics/Geometry.hpp"
+#include "cru/platform/graphics/Painter.hpp"
+#include "cru/platform/graphics/Resource.hpp"
+#include "cru/platform/graphics/TextLayout.hpp"
diff --git a/src/toml/CMakeLists.txt b/src/toml/CMakeLists.txt
index 0285b454..be04ad79 100644
--- a/src/toml/CMakeLists.txt
+++ b/src/toml/CMakeLists.txt
@@ -2,4 +2,5 @@ add_library(cru_toml SHARED
TomlDocument.cpp
TomlParser.cpp
)
+target_compile_definitions(cru_toml PRIVATE CRU_TOML_EXPORT_API)
target_link_libraries(cru_toml PUBLIC cru_base)
diff --git a/src/ui/components/Menu.cpp b/src/ui/components/Menu.cpp
index 681b44b7..05324865 100644
--- a/src/ui/components/Menu.cpp
+++ b/src/ui/components/Menu.cpp
@@ -92,7 +92,7 @@ PopupMenu::PopupMenu(controls::Control* attached_control)
menu_ = new Menu();
- menu_->SetOnItemClick([this](Index _) { this->Close(); });
+ menu_->SetOnItemClick([this](Index) { this->Close(); });
popup_->AddChild(menu_->GetRootControl(), 0);
}
diff --git a/src/ui/controls/TextHostControlService.cpp b/src/ui/controls/TextHostControlService.cpp
index 61e6aef6..0f136034 100644
--- a/src/ui/controls/TextHostControlService.cpp
+++ b/src/ui/controls/TextHostControlService.cpp
@@ -1,6 +1,7 @@
#include "cru/ui/controls/TextHostControlService.hpp"
#include "../Helper.hpp"
+#include "cru/common/Base.hpp"
#include "cru/common/Logger.hpp"
#include "cru/common/String.hpp"
#include "cru/common/StringUtil.hpp"
@@ -28,6 +29,7 @@ TextControlMovePattern TextControlMovePattern::kLeft(
u"Left", helper::ShortcutKeyBind(platform::gui::KeyCode::Left),
[](TextHostControlService* service, StringView text,
gsl::index current_position) {
+ CRU_UNUSED(service)
Utf16PreviousCodePoint(text, current_position, &current_position);
return current_position;
});
@@ -35,6 +37,7 @@ TextControlMovePattern TextControlMovePattern::kRight(
u"Right", helper::ShortcutKeyBind(platform::gui::KeyCode::Right),
[](TextHostControlService* service, StringView text,
gsl::index current_position) {
+ CRU_UNUSED(service)
Utf16NextCodePoint(text, current_position, &current_position);
return current_position;
});
@@ -44,6 +47,7 @@ TextControlMovePattern TextControlMovePattern::kCtrlLeft(
platform::gui::KeyModifiers::ctrl),
[](TextHostControlService* service, StringView text,
gsl::index current_position) {
+ CRU_UNUSED(service)
return Utf16PreviousWord(text, current_position);
});
TextControlMovePattern TextControlMovePattern::kCtrlRight(
@@ -52,12 +56,14 @@ TextControlMovePattern TextControlMovePattern::kCtrlRight(
platform::gui::KeyModifiers::ctrl),
[](TextHostControlService* service, StringView text,
gsl::index current_position) {
+ CRU_UNUSED(service)
return Utf16NextWord(text, current_position);
});
TextControlMovePattern TextControlMovePattern::kUp(
u"Up", helper::ShortcutKeyBind(platform::gui::KeyCode::Up),
[](TextHostControlService* service, StringView text,
gsl::index current_position) {
+ CRU_UNUSED(text)
auto text_render_object = service->GetTextRenderObject();
auto rect = text_render_object->TextSinglePoint(current_position, false);
rect.top -= 0.1f;
@@ -68,6 +74,7 @@ TextControlMovePattern TextControlMovePattern::kDown(
u"Down", helper::ShortcutKeyBind(platform::gui::KeyCode::Down),
[](TextHostControlService* service, StringView text,
gsl::index current_position) {
+ CRU_UNUSED(text)
auto text_render_object = service->GetTextRenderObject();
auto rect = text_render_object->TextSinglePoint(current_position, false);
rect.top += rect.height + 0.1f;
@@ -78,32 +85,46 @@ TextControlMovePattern TextControlMovePattern::kHome(
u"Home(Line Begin)", helper::ShortcutKeyBind(platform::gui::KeyCode::Home),
[](TextHostControlService* service, StringView text,
gsl::index current_position) {
+ CRU_UNUSED(service)
return Utf16BackwardUntil(text, current_position,
- [](char16_t c) { return c == u'\n'; });
+ [](CodePoint c) { return c == u'\n'; });
});
TextControlMovePattern TextControlMovePattern::kEnd(
u"End(Line End)", helper::ShortcutKeyBind(platform::gui::KeyCode::End),
[](TextHostControlService* service, StringView text,
gsl::index current_position) {
+ CRU_UNUSED(service)
return Utf16ForwardUntil(text, current_position,
- [](char16_t c) { return c == u'\n'; });
+ [](CodePoint c) { return c == u'\n'; });
});
TextControlMovePattern TextControlMovePattern::kCtrlHome(
u"Ctrl+Home(Document Begin)",
helper::ShortcutKeyBind(platform::gui::KeyCode::Home,
platform::gui::KeyModifiers::ctrl),
[](TextHostControlService* service, StringView text,
- gsl::index current_position) { return 0; });
+ gsl::index current_position) {
+ CRU_UNUSED(service)
+ CRU_UNUSED(text)
+ CRU_UNUSED(current_position)
+ return 0;
+ });
TextControlMovePattern TextControlMovePattern::kCtrlEnd(
u"Ctrl+End(Document End)",
helper::ShortcutKeyBind(platform::gui::KeyCode::End,
platform::gui::KeyModifiers::ctrl),
[](TextHostControlService* service, StringView text,
- gsl::index current_position) { return text.size(); });
+ gsl::index current_position) {
+ CRU_UNUSED(service)
+ CRU_UNUSED(text)
+ CRU_UNUSED(current_position)
+ return text.size();
+ });
TextControlMovePattern TextControlMovePattern::kPageUp(
u"PageUp", helper::ShortcutKeyBind(platform::gui::KeyCode::PageUp),
[](TextHostControlService* service, StringView text,
gsl::index current_position) {
+ CRU_UNUSED(service)
+ CRU_UNUSED(text)
// TODO: Implement this.
return current_position;
});
@@ -111,6 +132,8 @@ TextControlMovePattern TextControlMovePattern::kPageDown(
u"PageDown", helper::ShortcutKeyBind(platform::gui::KeyCode::PageDown),
[](TextHostControlService* service, StringView text,
gsl::index current_position) {
+ CRU_UNUSED(service)
+ CRU_UNUSED(text)
// TODO: Implement this.
return current_position;
});
diff --git a/src/ui/render/TextRenderObject.cpp b/src/ui/render/TextRenderObject.cpp
index 0e65da92..f7665beb 100644
--- a/src/ui/render/TextRenderObject.cpp
+++ b/src/ui/render/TextRenderObject.cpp
@@ -147,7 +147,6 @@ Rect TextRenderObject::GetCaretRectInContent() {
const auto caret_top_center =
this->text_layout_->TextSinglePoint(caret_pos, false);
- const auto font_height = this->font_->GetFontSize();
const auto caret_width = this->caret_width_;
auto rect = Rect{caret_top_center.left - caret_width / 2.0f,
diff --git a/src/win/DebugLogger.hpp b/src/win/DebugLogger.hpp
index 598ee9e8..5e78af22 100644
--- a/src/win/DebugLogger.hpp
+++ b/src/win/DebugLogger.hpp
@@ -13,10 +13,11 @@ class WinDebugLoggerSource : public ::cru::log::ILogSource {
~WinDebugLoggerSource() = default;
- void Write(::cru::log::LogLevel level, const std::u16string& s) override {
+ void Write(::cru::log::LogLevel level, StringView s) override {
CRU_UNUSED(level)
- ::OutputDebugStringW(reinterpret_cast<const wchar_t*>(s.c_str()));
+ String m = s.ToString();
+ ::OutputDebugStringW(reinterpret_cast<const wchar_t*>(m.c_str()));
}
};
} // namespace cru::platform::win
diff --git a/src/win/Exception.cpp b/src/win/Exception.cpp
index df2103fd..2664b092 100644
--- a/src/win/Exception.cpp
+++ b/src/win/Exception.cpp
@@ -1,6 +1,5 @@
#include "cru/win/Exception.hpp"
-#include <fmt/format.h>
#include <optional>
namespace cru::platform::win {
@@ -8,10 +7,9 @@ namespace cru::platform::win {
inline String HResultMakeMessage(HRESULT h_result,
std::optional<String> message) {
if (message.has_value())
- return fmt::format(FMT_STRING(L"HRESULT: {:#08x}. Message: {}"), h_result,
- message->WinCStr());
+ return Format(u"HRESULT: {}. Message: {}", h_result, message->WinCStr());
else
- return fmt::format(FMT_STRING(L"HRESULT: {:#08x}."), h_result);
+ return Format(u"HRESULT: {}.", h_result);
}
HResultError::HResultError(HRESULT h_result)
@@ -26,8 +24,8 @@ HResultError::HResultError(HRESULT h_result,
h_result_(h_result) {}
inline String Win32MakeMessage(DWORD error_code, String message) {
- return fmt::format(L"Last error code: {:#04x}.\nMessage: {}\n", error_code,
- message.WinCStr());
+ return Format(u"Last error code: {}.\nMessage: {}\n", error_code,
+ message.WinCStr());
}
Win32Error::Win32Error(std::string_view message)
diff --git a/src/win/HeapDebug.cpp b/src/win/HeapDebug.cpp
index 6ec1ffcc..b1b9fe1a 100644
--- a/src/win/HeapDebug.cpp
+++ b/src/win/HeapDebug.cpp
@@ -1,11 +1,9 @@
#include "cru/win/WinPreConfig.hpp"
-#include "cru/platform/HeapDebug.hpp"
-
#include <crtdbg.h>
namespace cru::platform {
void SetupHeapDebug() {
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
}
-}
+} // namespace cru::platform
diff --git a/src/win/StdOutLogger.hpp b/src/win/StdOutLogger.hpp
index bff8b30e..b3a22dd5 100644
--- a/src/win/StdOutLogger.hpp
+++ b/src/win/StdOutLogger.hpp
@@ -15,10 +15,11 @@ class WinStdOutLoggerSource : public ::cru::log::ILogSource {
~WinStdOutLoggerSource() = default;
- void Write(::cru::log::LogLevel level, const std::u16string& s) override {
+ void Write(::cru::log::LogLevel level, StringView s) override {
CRU_UNUSED(level)
- std::fputws(reinterpret_cast<const wchar_t*>(s.c_str()), stdout);
+ String m = s.ToString();
+ std::fputws(reinterpret_cast<const wchar_t*>(m.c_str()), stdout);
}
};
} // namespace cru::platform::win
diff --git a/src/win/graphics/direct/Brush.cpp b/src/win/graphics/direct/Brush.cpp
index b7842b97..eb6ea973 100644
--- a/src/win/graphics/direct/Brush.cpp
+++ b/src/win/graphics/direct/Brush.cpp
@@ -5,8 +5,8 @@
#include "cru/win/graphics/direct/Factory.hpp"
namespace cru::platform::graphics::win::direct {
-D2DSolidColorBrush::D2DSolidColorBrush(DirectGraphFactory* factory)
- : DirectGraphResource(factory) {
+D2DSolidColorBrush::D2DSolidColorBrush(DirectGraphicsFactory* factory)
+ : DirectGraphicsResource(factory) {
ThrowIfFailed(factory->GetDefaultD2D1DeviceContext()->CreateSolidColorBrush(
Convert(color_), &brush_));
}
diff --git a/src/win/graphics/direct/Factory.cpp b/src/win/graphics/direct/Factory.cpp
index 6694801f..4c4f1a9a 100644
--- a/src/win/graphics/direct/Factory.cpp
+++ b/src/win/graphics/direct/Factory.cpp
@@ -27,7 +27,7 @@ void InitializeCom() {
void UninitializeCom() { ::CoUninitialize(); }
} // namespace
-DirectGraphFactory::DirectGraphFactory() {
+DirectGraphicsFactory::DirectGraphicsFactory() {
// TODO! Detect repeated creation. Because I don't think we can create two d2d
// and dwrite factory so we need to prevent the "probably dangerous" behavior.
@@ -76,31 +76,33 @@ DirectGraphFactory::DirectGraphFactory() {
&dwrite_system_font_collection_));
}
-DirectGraphFactory::~DirectGraphFactory() { UninitializeCom(); }
+DirectGraphicsFactory::~DirectGraphicsFactory() { UninitializeCom(); }
Microsoft::WRL::ComPtr<ID2D1DeviceContext>
-DirectGraphFactory::CreateD2D1DeviceContext() {
+DirectGraphicsFactory::CreateD2D1DeviceContext() {
Microsoft::WRL::ComPtr<ID2D1DeviceContext> d2d1_device_context;
ThrowIfFailed(d2d1_device_->CreateDeviceContext(
D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &d2d1_device_context));
return d2d1_device_context;
}
-std::unique_ptr<ISolidColorBrush> DirectGraphFactory::CreateSolidColorBrush() {
+std::unique_ptr<ISolidColorBrush>
+DirectGraphicsFactory::CreateSolidColorBrush() {
return std::make_unique<D2DSolidColorBrush>(this);
}
-std::unique_ptr<IGeometryBuilder> DirectGraphFactory::CreateGeometryBuilder() {
+std::unique_ptr<IGeometryBuilder>
+DirectGraphicsFactory::CreateGeometryBuilder() {
return std::make_unique<D2DGeometryBuilder>(this);
}
-std::unique_ptr<IFont> DirectGraphFactory::CreateFont(
- std::u16string font_family, float font_size) {
+std::unique_ptr<IFont> DirectGraphicsFactory::CreateFont(String font_family,
+ float font_size) {
return std::make_unique<DWriteFont>(this, std::move(font_family), font_size);
}
-std::unique_ptr<ITextLayout> DirectGraphFactory::CreateTextLayout(
- std::shared_ptr<IFont> font, std::u16string text) {
+std::unique_ptr<ITextLayout> DirectGraphicsFactory::CreateTextLayout(
+ std::shared_ptr<IFont> font, String text) {
return std::make_unique<DWriteTextLayout>(this, std::move(font),
std::move(text));
}
diff --git a/src/win/graphics/direct/Font.cpp b/src/win/graphics/direct/Font.cpp
index 1d6a5c88..413c998b 100644
--- a/src/win/graphics/direct/Font.cpp
+++ b/src/win/graphics/direct/Font.cpp
@@ -7,9 +7,9 @@
#include <utility>
namespace cru::platform::graphics::win::direct {
-DWriteFont::DWriteFont(DirectGraphFactory* factory, std::u16string font_family,
+DWriteFont::DWriteFont(DirectGraphicsFactory* factory, String font_family,
float font_size)
- : DirectGraphResource(factory), font_family_(std::move(font_family)) {
+ : DirectGraphicsResource(factory), font_family_(std::move(font_family)) {
// Get locale
std::array<wchar_t, LOCALE_NAME_MAX_LENGTH> buffer;
if (!::GetUserDefaultLocaleName(buffer.data(),
diff --git a/src/win/graphics/direct/Geometry.cpp b/src/win/graphics/direct/Geometry.cpp
index d07a819f..b37dd9f4 100644
--- a/src/win/graphics/direct/Geometry.cpp
+++ b/src/win/graphics/direct/Geometry.cpp
@@ -5,15 +5,15 @@
#include "cru/win/graphics/direct/Factory.hpp"
namespace cru::platform::graphics::win::direct {
-D2DGeometryBuilder::D2DGeometryBuilder(DirectGraphFactory* factory)
- : DirectGraphResource(factory) {
+D2DGeometryBuilder::D2DGeometryBuilder(DirectGraphicsFactory* factory)
+ : DirectGraphicsResource(factory) {
ThrowIfFailed(factory->GetD2D1Factory()->CreatePathGeometry(&geometry_));
ThrowIfFailed(geometry_->Open(&geometry_sink_));
}
void D2DGeometryBuilder::CheckValidation() {
if (!IsValid())
- throw ReuseException(L"The geometry builder is already disposed.");
+ throw ReuseException(u"The geometry builder is already disposed.");
}
void D2DGeometryBuilder::BeginFigure(const Point& point) {
@@ -49,9 +49,9 @@ std::unique_ptr<IGeometry> D2DGeometryBuilder::Build() {
return geometry;
}
-D2DGeometry::D2DGeometry(DirectGraphFactory* factory,
+D2DGeometry::D2DGeometry(DirectGraphicsFactory* factory,
Microsoft::WRL::ComPtr<ID2D1PathGeometry> geometry)
- : DirectGraphResource(factory), geometry_(std::move(geometry)) {}
+ : DirectGraphicsResource(factory), geometry_(std::move(geometry)) {}
bool D2DGeometry::FillContains(const Point& point) {
BOOL result;
diff --git a/src/win/graphics/direct/Painter.cpp b/src/win/graphics/direct/Painter.cpp
index 26ef92ec..1a43d1d0 100644
--- a/src/win/graphics/direct/Painter.cpp
+++ b/src/win/graphics/direct/Painter.cpp
@@ -27,6 +27,10 @@ void D2DPainter::SetTransform(const platform::Matrix& matrix) {
render_target_->SetTransform(Convert(matrix));
}
+void D2DPainter::ConcatTransform(const Matrix& matrix) {
+ SetTransform(GetTransform() * matrix);
+}
+
void D2DPainter::Clear(const Color& color) {
CheckValidation();
render_target_->Clear(Convert(color));
@@ -54,6 +58,24 @@ void D2DPainter::FillRectangle(const Rect& rectangle, IBrush* brush) {
render_target_->FillRectangle(Convert(rectangle), b->GetD2DBrushInterface());
}
+void D2DPainter::StrokeEllipse(const Rect& outline_rect, IBrush* brush,
+ float width) {
+ CheckValidation();
+ const auto b = CheckPlatform<ID2DBrush>(brush, GetPlatformId());
+ render_target_->DrawEllipse(
+ D2D1::Ellipse(Convert(outline_rect.GetCenter()),
+ outline_rect.width / 2.0f, outline_rect.height / 2.0f),
+ b->GetD2DBrushInterface(), width);
+}
+void D2DPainter::FillEllipse(const Rect& outline_rect, IBrush* brush) {
+ CheckValidation();
+ const auto b = CheckPlatform<ID2DBrush>(brush, GetPlatformId());
+ render_target_->FillEllipse(
+ D2D1::Ellipse(Convert(outline_rect.GetCenter()),
+ outline_rect.width / 2.0f, outline_rect.height / 2.0f),
+ b->GetD2DBrushInterface());
+}
+
void D2DPainter::StrokeGeometry(IGeometry* geometry, IBrush* brush,
float width) {
CheckValidation();
@@ -96,6 +118,24 @@ void D2DPainter::PopLayer() {
layers_.pop_back();
}
+void D2DPainter::PushState() {
+ Microsoft::WRL::ComPtr<ID2D1Factory> factory = nullptr;
+ render_target_->GetFactory(&factory);
+
+ Microsoft::WRL::ComPtr<ID2D1DrawingStateBlock> state_block;
+ factory->CreateDrawingStateBlock(&state_block);
+ render_target_->SaveDrawingState(state_block.Get());
+
+ drawing_state_stack_.push_back(std::move(state_block));
+}
+
+void D2DPainter::PopState() {
+ Expects(!drawing_state_stack_.empty());
+ auto drawing_state = drawing_state_stack_.back();
+ drawing_state_stack_.pop_back();
+ render_target_->RestoreDrawingState(drawing_state.Get());
+}
+
void D2DPainter::EndDraw() {
if (is_drawing_) {
is_drawing_ = false;
@@ -106,7 +146,7 @@ void D2DPainter::EndDraw() {
void D2DPainter::CheckValidation() {
if (!is_drawing_) {
throw cru::platform::ReuseException(
- L"Can't do that on painter after end drawing.");
+ u"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 6ae74e64..0e9719f4 100644
--- a/src/win/graphics/direct/Resource.cpp
+++ b/src/win/graphics/direct/Resource.cpp
@@ -5,10 +5,12 @@
namespace cru::platform::graphics::win::direct {
String DirectResource::kPlatformId = u"Windows Direct";
-DirectGraphResource::DirectGraphResource(DirectGraphFactory* factory)
+DirectGraphicsResource::DirectGraphicsResource(DirectGraphicsFactory* factory)
: factory_(factory) {
Expects(factory);
}
-IGraphFactory* DirectGraphResource::GetGraphFactory() { return factory_; }
+IGraphicsFactory* DirectGraphicsResource::GetGraphicsFactory() {
+ return factory_;
+}
} // namespace cru::platform::graphics::win::direct
diff --git a/src/win/graphics/direct/TextLayout.cpp b/src/win/graphics/direct/TextLayout.cpp
index 0b3c68ca..bec4a972 100644
--- a/src/win/graphics/direct/TextLayout.cpp
+++ b/src/win/graphics/direct/TextLayout.cpp
@@ -1,4 +1,5 @@
#include "cru/win/graphics/direct/TextLayout.hpp"
+#include <dwrite.h>
#include "cru/common/Logger.hpp"
#include "cru/platform/Check.hpp"
@@ -9,10 +10,9 @@
#include <utility>
namespace cru::platform::graphics::win::direct {
-DWriteTextLayout::DWriteTextLayout(DirectGraphFactory* factory,
- std::shared_ptr<IFont> font,
- std::u16string text)
- : DirectGraphResource(factory), text_(std::move(text)) {
+DWriteTextLayout::DWriteTextLayout(DirectGraphicsFactory* factory,
+ std::shared_ptr<IFont> font, String text)
+ : DirectGraphicsResource(factory), text_(std::move(text)) {
Expects(font);
font_ = CheckPlatform<DWriteFont>(font, GetPlatformId());
@@ -24,12 +24,10 @@ DWriteTextLayout::DWriteTextLayout(DirectGraphFactory* factory,
DWriteTextLayout::~DWriteTextLayout() = default;
-std::u16string DWriteTextLayout::GetText() { return text_; }
+String DWriteTextLayout::GetText() { return text_; }
-std::u16string_view DWriteTextLayout::GetTextView() { return text_; }
-
-void DWriteTextLayout::SetText(std::u16string new_text) {
- text_.swap(new_text);
+void DWriteTextLayout::SetText(String new_text) {
+ text_ = std::move(new_text);
ThrowIfFailed(GetDirectFactory()->GetDWriteFactory()->CreateTextLayout(
reinterpret_cast<const wchar_t*>(text_.c_str()),
static_cast<UINT32>(text_.size()), font_->GetComInterface(), max_width_,
@@ -58,6 +56,44 @@ void DWriteTextLayout::SetMaxHeight(float max_height) {
ThrowIfFailed(text_layout_->SetMaxHeight(max_height_));
}
+bool DWriteTextLayout::IsEditMode() { return edit_mode_; }
+
+void DWriteTextLayout::SetEditMode(bool enable) {
+ edit_mode_ = enable;
+ // TODO: Implement this.
+}
+
+Index DWriteTextLayout::GetLineIndexFromCharIndex(Index char_index) {
+ if (char_index < 0 || char_index >= text_.size()) {
+ return -1;
+ }
+
+ auto line_index = 0;
+ for (Index i = 0; i < char_index; ++i) {
+ if (text_[i] == u'\n') {
+ line_index++;
+ }
+ }
+
+ return line_index;
+}
+
+float DWriteTextLayout::GetLineHeight(Index line_index) {
+ Index count = GetLineCount();
+ std::vector<DWRITE_LINE_METRICS> line_metrics(count);
+
+ UINT32 actual_line_count = 0;
+ text_layout_->GetLineMetrics(line_metrics.data(), static_cast<UINT32>(count),
+ &actual_line_count);
+ return line_metrics[line_index].height;
+}
+
+Index DWriteTextLayout::GetLineCount() {
+ UINT32 line_count = 0;
+ text_layout_->GetLineMetrics(nullptr, 0, &line_count);
+ return line_count;
+}
+
Rect DWriteTextLayout::GetTextBounds(bool includingTrailingSpace) {
DWRITE_TEXT_METRICS metrics;
ThrowIfFailed(text_layout_->GetMetrics(&metrics));
@@ -100,14 +136,14 @@ std::vector<Rect> DWriteTextLayout::TextRangeRect(
return result;
}
-Point DWriteTextLayout::TextSinglePoint(Index position, bool trailing) {
+Rect DWriteTextLayout::TextSinglePoint(Index position, bool trailing) {
DWRITE_HIT_TEST_METRICS metrics;
FLOAT left;
FLOAT top;
ThrowIfFailed(text_layout_->HitTestTextPosition(static_cast<UINT32>(position),
static_cast<BOOL>(trailing),
&left, &top, &metrics));
- return Point{left, top};
+ return Rect{left, top, 0, GetFont()->GetFontSize()};
}
TextHitTestResult DWriteTextLayout::HitTest(const Point& point) {
@@ -121,7 +157,6 @@ TextHitTestResult DWriteTextLayout::HitTest(const Point& point) {
TextHitTestResult result;
result.position = metrics.textPosition;
result.trailing = trailing != 0;
- result.insideText = inside != 0;
return result;
}
} // namespace cru::platform::graphics::win::direct
diff --git a/src/win/graphics/direct/WindowRenderTarget.cpp b/src/win/graphics/direct/WindowRenderTarget.cpp
index 7479ae24..020ce4b4 100644
--- a/src/win/graphics/direct/WindowRenderTarget.cpp
+++ b/src/win/graphics/direct/WindowRenderTarget.cpp
@@ -5,7 +5,7 @@
namespace cru::platform::graphics::win::direct {
D2DWindowRenderTarget::D2DWindowRenderTarget(
- gsl::not_null<DirectGraphFactory*> factory, HWND hwnd)
+ gsl::not_null<DirectGraphicsFactory*> factory, HWND hwnd)
: factory_(factory), hwnd_(hwnd) {
const auto d3d11_device = factory->GetD3D11Device();
const auto dxgi_factory = factory->GetDxgiFactory();
diff --git a/src/win/gui/InputMethod.cpp b/src/win/gui/InputMethod.cpp
index cc237e88..47e17109 100644
--- a/src/win/gui/InputMethod.cpp
+++ b/src/win/gui/InputMethod.cpp
@@ -104,19 +104,19 @@ CompositionClauses GetCompositionClauses(HIMC imm_context, int target_start,
return result;
}
-std::u16string GetString(HIMC imm_context) {
+String GetString(HIMC imm_context) {
LONG string_size =
::ImmGetCompositionString(imm_context, GCS_COMPSTR, NULL, 0);
- std::u16string result((string_size / sizeof(char16_t)), 0);
+ String result((string_size / sizeof(char16_t)), 0);
::ImmGetCompositionString(imm_context, GCS_COMPSTR, result.data(),
string_size);
return result;
}
-std::u16string GetResultString(HIMC imm_context) {
+String GetResultString(HIMC imm_context) {
LONG string_size =
::ImmGetCompositionString(imm_context, GCS_RESULTSTR, NULL, 0);
- std::u16string result((string_size / sizeof(char16_t)), 0);
+ String result((string_size / sizeof(char16_t)), 0);
::ImmGetCompositionString(imm_context, GCS_RESULTSTR, result.data(),
string_size);
return result;
@@ -217,9 +217,7 @@ IEvent<std::nullptr_t>* WinInputMethodContext::CompositionEvent() {
return &composition_event_;
}
-IEvent<std::u16string_view>* WinInputMethodContext::TextEvent() {
- return &text_event_;
-}
+IEvent<StringView>* WinInputMethodContext::TextEvent() { return &text_event_; }
void WinInputMethodContext::OnWindowNativeMessage(
WindowNativeMessageEventArgs& args) {
@@ -275,7 +273,7 @@ void WinInputMethodContext::OnWindowNativeMessage(
}
}
-std::u16string WinInputMethodContext::GetResultString() {
+String WinInputMethodContext::GetResultString() {
auto himc = GetHIMC();
auto result = win::GetResultString(himc.Get());
return result;
diff --git a/src/win/gui/UiApplication.cpp b/src/win/gui/UiApplication.cpp
index f4541dd0..cb0f0a4c 100644
--- a/src/win/gui/UiApplication.cpp
+++ b/src/win/gui/UiApplication.cpp
@@ -37,7 +37,7 @@ WinUiApplication::WinUiApplication() {
std::make_unique<::cru::platform::win::WinStdOutLoggerSource>());
graph_factory_ = std::make_unique<
- cru::platform::graphics::win::direct::DirectGraphFactory>();
+ cru::platform::graphics::win::direct::DirectGraphicsFactory>();
god_window_ = std::make_unique<GodWindow>(this);
timer_manager_ = std::make_unique<TimerManager>(god_window_.get());
@@ -99,24 +99,22 @@ std::vector<INativeWindow*> WinUiApplication::GetAllWindow() {
return result;
}
-INativeWindow* WinUiApplication::CreateWindow(INativeWindow* parent,
- CreateWindowFlag flag) {
- WinNativeWindow* p = nullptr;
- if (parent != nullptr) {
- p = CheckPlatform<WinNativeWindow>(parent, GetPlatformId());
- }
- return new WinNativeWindow(this, window_manager_->GetGeneralWindowClass(),
- flag & CreateWindowFlags::NoCaptionAndBorder
- ? WS_POPUP
- : WS_OVERLAPPEDWINDOW,
- p);
+INativeWindow* WinUiApplication::CreateWindow() {
+ return new WinNativeWindow(this);
}
-cru::platform::graphics::IGraphFactory* WinUiApplication::GetGraphFactory() {
+cru::platform::graphics::IGraphicsFactory*
+WinUiApplication::GetGraphicsFactory() {
return graph_factory_.get();
}
ICursorManager* WinUiApplication::GetCursorManager() {
return cursor_manager_.get();
}
+
+IClipboard* WinUiApplication::GetClipboard() {
+ // TODO: Implement this.
+ return nullptr;
+}
+
} // namespace cru::platform::gui::win
diff --git a/src/win/gui/Window.cpp b/src/win/gui/Window.cpp
index 4c75a319..7ee2fb71 100644
--- a/src/win/gui/Window.cpp
+++ b/src/win/gui/Window.cpp
@@ -3,8 +3,10 @@
#include "WindowManager.hpp"
#include "cru/common/Logger.hpp"
#include "cru/platform/Check.hpp"
+#include "cru/platform/graphics/NullPainter.hpp"
#include "cru/platform/gui/Base.hpp"
#include "cru/platform/gui/DebugFlags.hpp"
+#include "cru/platform/gui/Window.hpp"
#include "cru/win/graphics/direct/WindowPainter.hpp"
#include "cru/win/gui/Cursor.hpp"
#include "cru/win/gui/Exception.hpp"
@@ -13,104 +15,165 @@
#include "cru/win/gui/UiApplication.hpp"
#include "cru/win/gui/WindowClass.hpp"
-#include <imm.h>
#include <windowsx.h>
+#include <winuser.h>
#include <memory>
namespace cru::platform::gui::win {
-WinNativeWindow::WinNativeWindow(WinUiApplication* application,
- WindowClass* window_class, DWORD window_style,
- WinNativeWindow* parent)
- : application_(application), parent_window_(parent) {
- Expects(application); // application can't be null.
+namespace {
+inline int DipToPixel(const float dip, const float dpi) {
+ return static_cast<int>(dip * dpi / 96.0f);
+}
- if (parent != nullptr) {
- throw new std::runtime_error("Can't use a invalid window as parent.");
- }
+inline float PixelToDip(const int pixel, const float dpi) {
+ return static_cast<float>(pixel) * 96.0f / dpi;
+}
- const auto window_manager = application->GetWindowManager();
+DWORD CalcWindowStyle(WindowStyleFlag flag) {
+ return flag & WindowStyleFlags::NoCaptionAndBorder ? WS_POPUP
+ : WS_OVERLAPPEDWINDOW;
+}
- hwnd_ = CreateWindowExW(
- 0, window_class->GetName(), L"", window_style, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
- parent == nullptr ? nullptr : parent->GetWindowHandle(), nullptr,
- application->GetInstanceHandle(), nullptr);
+Rect CalcWindowRectFromClient(const Rect& rect, WindowStyleFlag style_flag,
+ float dpi) {
+ RECT r;
+ r.left = DipToPixel(rect.left, dpi);
+ r.top = DipToPixel(rect.top, dpi);
+ r.right = DipToPixel(rect.GetRight(), dpi);
+ r.bottom = DipToPixel(rect.GetBottom(), dpi);
+ if (!AdjustWindowRectEx(&r, CalcWindowStyle(style_flag), FALSE, 0))
+ throw Win32Error(::GetLastError(), "Failed to invoke AdjustWindowRectEx.");
- if (hwnd_ == nullptr)
- throw Win32Error(::GetLastError(), "Failed to create window.");
+ Rect result =
+ Rect::FromVertices(PixelToDip(r.left, dpi), PixelToDip(r.top, dpi),
+ PixelToDip(r.right, dpi), PixelToDip(r.bottom, dpi));
+ return result;
+}
- auto dpi = ::GetDpiForWindow(hwnd_);
- if (dpi == 0)
- throw Win32Error(::GetLastError(), "Failed to get dpi of window.");
- dpi_ = static_cast<float>(dpi);
- log::Debug(u"Dpi of window is {}.", dpi_);
+Rect CalcClientRectFromWindow(const Rect& rect, WindowStyleFlag style_flag,
+ float dpi) {
+ RECT o{100, 100, 500, 500};
+ RECT s = o;
+ if (!AdjustWindowRectEx(&s, CalcWindowStyle(style_flag), FALSE, 0))
+ throw Win32Error(::GetLastError(), "Failed to invoke AdjustWindowRectEx.");
- window_manager->RegisterWindow(hwnd_, this);
+ Rect result = rect;
+ result.Shrink(Thickness(PixelToDip(s.left - o.left, dpi),
+ PixelToDip(o.top - s.top, dpi),
+ PixelToDip(s.right - o.right, dpi),
+ PixelToDip(s.bottom - o.bottom, dpi)));
- SetCursor(application->GetCursorManager()->GetSystemCursor(
- cru::platform::gui::SystemCursorType::Arrow));
+ return result;
+}
+} // namespace
- window_render_target_ =
- std::make_unique<graphics::win::direct::D2DWindowRenderTarget>(
- application->GetDirectFactory(), hwnd_);
- window_render_target_->SetDpi(dpi_, dpi_);
+WinNativeWindow::WinNativeWindow(WinUiApplication* application)
+ : application_(application) {
+ Expects(application); // application can't be null.
+}
- input_method_context_ = std::make_unique<WinInputMethodContext>(this);
- input_method_context_->DisableIME();
+WinNativeWindow::~WinNativeWindow() { Close(); }
+
+void WinNativeWindow::Close() {
+ if (hwnd_) ::DestroyWindow(hwnd_);
}
-WinNativeWindow::~WinNativeWindow() {
- if (!sync_flag_) {
- sync_flag_ = true;
- Close();
+void WinNativeWindow::SetParent(INativeWindow* parent) {
+ auto p = CheckPlatform<WinNativeWindow>(parent, GetPlatformId());
+ parent_window_ = p;
+
+ if (hwnd_) {
+ ::SetParent(hwnd_, parent_window_->hwnd_);
}
}
-void WinNativeWindow::Close() { ::DestroyWindow(hwnd_); }
+void WinNativeWindow::SetStyleFlag(WindowStyleFlag flag) {
+ if (flag == style_flag_) return;
-bool WinNativeWindow::IsVisible() { return ::IsWindowVisible(hwnd_); }
-
-void WinNativeWindow::SetVisible(bool is_visible) {
- is_visible ? ShowWindow(hwnd_, SW_SHOWNORMAL) : ShowWindow(hwnd_, SW_HIDE);
+ style_flag_ = flag;
+ if (hwnd_) {
+ SetWindowLongPtrW(hwnd_, GWL_STYLE,
+ static_cast<LONG_PTR>(CalcWindowStyle(style_flag_)));
+ }
}
-Size WinNativeWindow::GetClientSize() {
- const auto pixel_rect = GetClientRectPixel();
- return Size(PixelToDip(pixel_rect.right), PixelToDip(pixel_rect.bottom));
+
+void WinNativeWindow::SetVisibility(WindowVisibilityType visibility) {
+ if (visibility == visibility_) return;
+ visibility_ = visibility;
+
+ if (!hwnd_) {
+ RecreateWindow();
+ }
+
+ if (visibility == WindowVisibilityType::Show) {
+ ShowWindow(hwnd_, SW_SHOWNORMAL);
+ } else if (visibility == WindowVisibilityType::Hide) {
+ ShowWindow(hwnd_, SW_HIDE);
+ } else if (visibility == WindowVisibilityType::Minimize) {
+ ShowWindow(hwnd_, SW_MINIMIZE);
+ }
}
+Size WinNativeWindow::GetClientSize() { return GetClientRect().GetSize(); }
+
void WinNativeWindow::SetClientSize(const Size& size) {
- const auto window_style =
- static_cast<DWORD>(GetWindowLongPtr(hwnd_, GWL_STYLE));
- const auto window_ex_style =
- static_cast<DWORD>(GetWindowLongPtr(hwnd_, GWL_EXSTYLE));
+ client_rect_.SetSize(size);
- RECT rect;
- rect.left = 0;
- rect.top = 0;
- rect.right = DipToPixel(size.width);
- rect.bottom = DipToPixel(size.height);
- if (!AdjustWindowRectEx(&rect, window_style, FALSE, window_ex_style))
- throw Win32Error(::GetLastError(), "Failed to invoke AdjustWindowRectEx.");
+ if (hwnd_) {
+ RECT rect =
+ DipToPixel(CalcWindowRectFromClient(client_rect_, style_flag_, dpi_));
- if (!SetWindowPos(hwnd_, nullptr, 0, 0, rect.right - rect.left,
- rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE))
- throw Win32Error(::GetLastError(), "Failed to invoke SetWindowPos.");
+ if (!SetWindowPos(hwnd_, nullptr, 0, 0, rect.right - rect.left,
+ rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE))
+ throw Win32Error(::GetLastError(), "Failed to invoke SetWindowPos.");
+ }
}
-Rect WinNativeWindow::GetWindowRect() {
- RECT rect;
- if (!::GetWindowRect(hwnd_, &rect))
- throw Win32Error(::GetLastError(), "Failed to invoke GetWindowRect.");
+Rect WinNativeWindow::GetClientRect() { return client_rect_; }
+
+void WinNativeWindow::SetClientRect(const Rect& rect) {
+ client_rect_ = rect;
- return Rect::FromVertices(PixelToDip(rect.left), PixelToDip(rect.top),
- PixelToDip(rect.right), PixelToDip(rect.bottom));
+ if (hwnd_) {
+ RECT r =
+ DipToPixel(CalcWindowRectFromClient(client_rect_, style_flag_, dpi_));
+
+ if (!SetWindowPos(hwnd_, nullptr, 0, 0, r.right - r.left, r.bottom - r.top,
+ SWP_NOZORDER | SWP_NOMOVE))
+ throw Win32Error(::GetLastError(), "Failed to invoke SetWindowPos.");
+ }
+}
+
+Rect WinNativeWindow::GetWindowRect() {
+ if (hwnd_) {
+ RECT rect;
+ if (!::GetWindowRect(hwnd_, &rect))
+ throw Win32Error(::GetLastError(), "Failed to invoke GetWindowRect.");
+
+ return Rect::FromVertices(PixelToDip(rect.left), PixelToDip(rect.top),
+ PixelToDip(rect.right), PixelToDip(rect.bottom));
+ } else {
+ return CalcWindowRectFromClient(client_rect_, style_flag_, dpi_);
+ }
}
void WinNativeWindow::SetWindowRect(const Rect& rect) {
- if (!SetWindowPos(hwnd_, nullptr, DipToPixel(rect.left), DipToPixel(rect.top),
- DipToPixel(rect.GetRight()), DipToPixel(rect.GetBottom()),
- SWP_NOZORDER))
- throw Win32Error(::GetLastError(), "Failed to invoke SetWindowPos.");
+ client_rect_ = CalcClientRectFromWindow(rect, style_flag_, dpi_);
+
+ if (hwnd_) {
+ if (!SetWindowPos(hwnd_, nullptr, DipToPixel(rect.left),
+ DipToPixel(rect.top), DipToPixel(rect.GetRight()),
+ DipToPixel(rect.GetBottom()), SWP_NOZORDER))
+ throw Win32Error(::GetLastError(), "Failed to invoke SetWindowPos.");
+ }
+}
+
+bool WinNativeWindow::RequestFocus() {
+ if (hwnd_) {
+ SetFocus(hwnd_);
+ return true;
+ }
+ return false;
}
Point WinNativeWindow::GetMousePosition() {
@@ -143,8 +206,11 @@ void WinNativeWindow::RequestRepaint() {
}
std::unique_ptr<graphics::IPainter> WinNativeWindow::BeginPaint() {
- return std::make_unique<graphics::win::direct::D2DWindowPainter>(
- window_render_target_.get());
+ if (hwnd_)
+ return std::make_unique<graphics::win::direct::D2DWindowPainter>(
+ window_render_target_.get());
+ else
+ return std::make_unique<graphics::NullPainter>();
}
void WinNativeWindow::SetCursor(std::shared_ptr<ICursor> cursor) {
@@ -154,6 +220,8 @@ void WinNativeWindow::SetCursor(std::shared_ptr<ICursor> cursor) {
cursor_ = CheckPlatform<WinCursor>(cursor, GetPlatformId());
+ if (hwnd_) return;
+
if (!::SetClassLongPtrW(hwnd_, GCLP_HCURSOR,
reinterpret_cast<LONG_PTR>(cursor_->GetHandle()))) {
log::TagWarn(log_tag,
@@ -163,9 +231,9 @@ void WinNativeWindow::SetCursor(std::shared_ptr<ICursor> cursor) {
return;
}
- if (!IsVisible()) return;
+ if (GetVisibility() != WindowVisibilityType::Show) return;
- auto lg = [](const std::u16string_view& reason) {
+ auto lg = [](StringView reason) {
log::TagWarn(
log_tag,
u"Failed to set cursor because {} when window is visible. (We need to "
@@ -320,6 +388,14 @@ bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg,
return true;
}
return false;
+ case WM_CREATE:
+ OnCreateInternal();
+ *result = 0;
+ return true;
+ case WM_MOVE:
+ OnMoveInternal(LOWORD(l_param), HIWORD(l_param));
+ *result = 0;
+ return true;
case WM_SIZE:
OnResizeInternal(LOWORD(l_param), HIWORD(l_param));
*result = 0;
@@ -361,19 +437,50 @@ bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg,
RECT WinNativeWindow::GetClientRectPixel() {
RECT rect;
- if (!GetClientRect(hwnd_, &rect))
+ if (!::GetClientRect(hwnd_, &rect))
throw Win32Error(::GetLastError(), "Failed to invoke GetClientRect.");
return rect;
}
+void WinNativeWindow::RecreateWindow() {
+ const auto window_manager = application_->GetWindowManager();
+ auto window_class = window_manager->GetGeneralWindowClass();
+
+ hwnd_ = CreateWindowExW(
+ 0, window_class->GetName(), L"", CalcWindowStyle(style_flag_),
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ parent_window_ == nullptr ? nullptr : parent_window_->GetWindowHandle(),
+ nullptr, application_->GetInstanceHandle(), nullptr);
+
+ if (hwnd_ == nullptr)
+ throw Win32Error(::GetLastError(), "Failed to create window.");
+
+ auto dpi = ::GetDpiForWindow(hwnd_);
+ if (dpi == 0)
+ throw Win32Error(::GetLastError(), "Failed to get dpi of window.");
+ dpi_ = static_cast<float>(dpi);
+ log::Debug(u"Dpi of window is {}.", dpi_);
+
+ window_manager->RegisterWindow(hwnd_, this);
+
+ SetCursor(application_->GetCursorManager()->GetSystemCursor(
+ cru::platform::gui::SystemCursorType::Arrow));
+
+ window_render_target_ =
+ std::make_unique<graphics::win::direct::D2DWindowRenderTarget>(
+ application_->GetDirectFactory(), hwnd_);
+ window_render_target_->SetDpi(dpi_, dpi_);
+
+ input_method_context_ = std::make_unique<WinInputMethodContext>(this);
+ input_method_context_->DisableIME();
+}
+
+void WinNativeWindow::OnCreateInternal() { create_event_.Raise(nullptr); }
+
void WinNativeWindow::OnDestroyInternal() {
destroy_event_.Raise(nullptr);
application_->GetWindowManager()->UnregisterWindow(hwnd_);
hwnd_ = nullptr;
- if (!sync_flag_) {
- sync_flag_ = true;
- delete this;
- }
}
void WinNativeWindow::OnPaintInternal() {
@@ -384,8 +491,15 @@ void WinNativeWindow::OnPaintInternal() {
}
}
+void WinNativeWindow::OnMoveInternal(const int new_left, const int new_top) {
+ client_rect_.left = PixelToDip(new_left);
+ client_rect_.top = PixelToDip(new_top);
+}
+
void WinNativeWindow::OnResizeInternal(const int new_width,
const int new_height) {
+ client_rect_.width = PixelToDip(new_width);
+ client_rect_.height = PixelToDip(new_height);
if (!(new_width == 0 && new_height == 0)) {
window_render_target_->ResizeBuffer(new_width, new_height);
resize_event_.Raise(Size{PixelToDip(new_width), PixelToDip(new_height)});
@@ -399,7 +513,7 @@ void WinNativeWindow::OnSetFocusInternal() {
void WinNativeWindow::OnKillFocusInternal() {
has_focus_ = false;
- focus_event_.Raise(FocusChangeType::Lost);
+ focus_event_.Raise(FocusChangeType::Lose);
}
void WinNativeWindow::OnMouseMoveInternal(const POINT point) {
diff --git a/src/win/gui/WindowManager.cpp b/src/win/gui/WindowManager.cpp
index 4e84e967..31b868b9 100644
--- a/src/win/gui/WindowManager.cpp
+++ b/src/win/gui/WindowManager.cpp
@@ -37,7 +37,8 @@ void WindowManager::UnregisterWindow(HWND hwnd) {
const auto find_result = window_map_.find(hwnd);
Expects(find_result != window_map_.end()); // The hwnd is not in the map.
window_map_.erase(find_result);
- if (window_map_.empty()) application_->RequestQuit(0);
+ if (window_map_.empty() && application_->IsQuitOnAllWindowClosed())
+ application_->RequestQuit(0);
}
WinNativeWindow* WindowManager::FromHandle(HWND hwnd) {
diff --git a/src/xml/CMakeLists.txt b/src/xml/CMakeLists.txt
index 20e889ec..014e820c 100644
--- a/src/xml/CMakeLists.txt
+++ b/src/xml/CMakeLists.txt
@@ -2,4 +2,5 @@ add_library(cru_xml SHARED
XmlNode.cpp
XmlParser.cpp
)
+target_compile_definitions(cru_xml PRIVATE CRU_XML_EXPORT_API)
target_link_libraries(cru_xml PUBLIC cru_base)