aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/platform/Matrix.hpp5
-rw-r--r--include/cru/platform/graphics/Painter.hpp4
-rw-r--r--include/cru/platform/graphics/util/Painter.hpp2
-rw-r--r--include/cru/ui/render/ScrollBar.hpp3
-rw-r--r--include/cru/win/graphics/direct/Painter.hpp2
-rw-r--r--src/ui/render/ScrollBar.cpp56
-rw-r--r--src/win/graphics/direct/Painter.cpp8
-rw-r--r--test/CMakeLists.txt9
-rw-r--r--test/platform/CMakeLists.txt6
-rw-r--r--test/platform/MatrixTest.cpp37
-rw-r--r--test/win/CMakeLists.txt1
-rw-r--r--test/win/graphics/CMakeLists.txt1
-rw-r--r--test/win/graphics/direct/CMakeLists.txt6
-rw-r--r--test/win/graphics/direct/ConvertTest.cpp29
14 files changed, 157 insertions, 12 deletions
diff --git a/include/cru/platform/Matrix.hpp b/include/cru/platform/Matrix.hpp
index e702df90..8ec5faaa 100644
--- a/include/cru/platform/Matrix.hpp
+++ b/include/cru/platform/Matrix.hpp
@@ -50,10 +50,15 @@ struct Matrix {
return Matrix{1.0f, 0.0f, 0.0f, 1.0f, x, y};
}
+ static Matrix Translation(const Point& point) {
+ return Translation(point.x, point.y);
+ }
+
static Matrix Scale(float sx, float sy) {
return Matrix{sx, 0.0f, 0.0f, sy, 0.0f, 0.0f};
}
+ // Clockwise.
static Matrix Rotation(float angle) {
float r = AngleToRadian(angle);
float s = std::sin(r);
diff --git a/include/cru/platform/graphics/Painter.hpp b/include/cru/platform/graphics/Painter.hpp
index 76140c32..f75ea52b 100644
--- a/include/cru/platform/graphics/Painter.hpp
+++ b/include/cru/platform/graphics/Painter.hpp
@@ -9,6 +9,8 @@ struct IPainter : virtual INativeResource {
virtual void Clear(const Color& color) = 0;
+ virtual void DrawLine(const Point& start, const Point& end, IBrush* brush,
+ float width) = 0;
virtual void StrokeRectangle(const Rect& rectangle, IBrush* brush,
float width) = 0;
virtual void FillRectangle(const Rect& rectangle, IBrush* brush) = 0;
@@ -26,4 +28,4 @@ struct IPainter : virtual INativeResource {
virtual void EndDraw() = 0;
};
-} // namespace cru::platform::graph
+} // namespace cru::platform::graphics
diff --git a/include/cru/platform/graphics/util/Painter.hpp b/include/cru/platform/graphics/util/Painter.hpp
index af3a1997..90457cf4 100644
--- a/include/cru/platform/graphics/util/Painter.hpp
+++ b/include/cru/platform/graphics/util/Painter.hpp
@@ -10,7 +10,7 @@ void WithTransform(IPainter* painter, const Matrix& matrix, const Fn& action) {
static_assert(std::is_invocable_v<decltype(action), IPainter*>,
"Action must can be be invoked with painter.");
const auto old = painter->GetTransform();
- painter->SetTransform(old * matrix);
+ painter->SetTransform(matrix * old);
action(painter);
painter->SetTransform(old);
}
diff --git a/include/cru/ui/render/ScrollBar.hpp b/include/cru/ui/render/ScrollBar.hpp
index 7cfd2576..3293e9d0 100644
--- a/include/cru/ui/render/ScrollBar.hpp
+++ b/include/cru/ui/render/ScrollBar.hpp
@@ -3,6 +3,7 @@
#include "cru/common/Base.hpp"
#include "cru/common/Event.hpp"
#include "cru/platform/graphics/Base.hpp"
+#include "cru/platform/graphics/Geometry.hpp"
#include "cru/platform/graphics/Painter.hpp"
#include "cru/platform/gui/Cursor.hpp"
#include "cru/platform/gui/UiApplication.hpp"
@@ -102,6 +103,8 @@ class ScrollBar : public Object {
protected:
gsl::not_null<ScrollRenderObject*> render_object_;
+ std::unique_ptr<platform::graphics::IGeometry> arrow_geometry_;
+
private:
Direction direction_;
diff --git a/include/cru/win/graphics/direct/Painter.hpp b/include/cru/win/graphics/direct/Painter.hpp
index 93c768e7..b34c1563 100644
--- a/include/cru/win/graphics/direct/Painter.hpp
+++ b/include/cru/win/graphics/direct/Painter.hpp
@@ -27,6 +27,8 @@ class D2DPainter : public DirectResource,
void Clear(const Color& color) override;
+ void DrawLine(const Point& start, const Point& end, IBrush* brush,
+ float width) override;
void StrokeRectangle(const Rect& rectangle, IBrush* brush,
float width) override;
void FillRectangle(const Rect& rectangle, IBrush* brush) override;
diff --git a/src/ui/render/ScrollBar.cpp b/src/ui/render/ScrollBar.cpp
index 02e079e9..7f69c1e2 100644
--- a/src/ui/render/ScrollBar.cpp
+++ b/src/ui/render/ScrollBar.cpp
@@ -4,7 +4,9 @@
#include "cru/common/Base.hpp"
#include "cru/platform/GraphBase.hpp"
#include "cru/platform/graphics/Factory.hpp"
+#include "cru/platform/graphics/Geometry.hpp"
#include "cru/platform/graphics/Painter.hpp"
+#include "cru/platform/graphics/util/Painter.hpp"
#include "cru/platform/gui/Base.hpp"
#include "cru/platform/gui/Cursor.hpp"
#include "cru/ui/Base.hpp"
@@ -16,6 +18,7 @@
#include <cassert>
#include <chrono>
#include <gsl/pointers>
+#include <memory>
#include <optional>
#include <stdexcept>
@@ -24,6 +27,7 @@ using namespace std::chrono_literals;
constexpr float kScrollBarCollapseThumbWidth = 2;
constexpr float kScrollBarCollapsedTriggerExpandAreaWidth = 5;
constexpr float kScrollBarExpandWidth = 10;
+constexpr float kScrollBarArrowHeight = 3.5;
constexpr auto kScrollBarAutoCollapseDelay = 1500ms;
constexpr std::array<ScrollBarAreaKind, 5> kScrollBarAreaKindList{
@@ -31,6 +35,17 @@ constexpr std::array<ScrollBarAreaKind, 5> kScrollBarAreaKindList{
ScrollBarAreaKind::UpSlot, ScrollBarAreaKind::DownSlot,
ScrollBarAreaKind::Thumb};
+namespace {
+std::unique_ptr<platform::graphics::IGeometry> CreateScrollBarArrowGeometry() {
+ auto geometry_builder = GetGraphFactory()->CreateGeometryBuilder();
+ geometry_builder->BeginFigure({-kScrollBarArrowHeight / 2, 0});
+ geometry_builder->LineTo({kScrollBarArrowHeight / 2, kScrollBarArrowHeight});
+ geometry_builder->LineTo({kScrollBarArrowHeight / 2, -kScrollBarArrowHeight});
+ geometry_builder->CloseFigure(true);
+ return geometry_builder->Build();
+}
+} // namespace
+
ScrollBar::ScrollBar(gsl::not_null<ScrollRenderObject*> render_object,
Direction direction)
: render_object_(render_object), direction_(direction) {
@@ -43,10 +58,11 @@ ScrollBar::ScrollBar(gsl::not_null<ScrollRenderObject*> render_object,
expanded_thumb_brush_ = graphics_factory->CreateSolidColorBrush(colors::gray);
expanded_slot_brush_ =
graphics_factory->CreateSolidColorBrush(colors::seashell);
- expanded_arrow_brush_ =
- graphics_factory->CreateSolidColorBrush(colors::white);
+ expanded_arrow_brush_ = graphics_factory->CreateSolidColorBrush(colors::gray);
expanded_arrow_background_brush_ =
- graphics_factory->CreateSolidColorBrush(colors::black);
+ graphics_factory->CreateSolidColorBrush(colors::seashell);
+
+ arrow_geometry_ = CreateScrollBarArrowGeometry();
}
ScrollBar::~ScrollBar() { RestoreCursor(); }
@@ -250,7 +266,7 @@ void ScrollBar::OnDraw(platform::graphics::IPainter* painter,
if (up_arrow) this->DrawUpArrow(painter, *up_arrow);
auto down_arrow = GetExpandedAreaRect(ScrollBarAreaKind::DownArrow);
- if (down_arrow) this->DrawUpArrow(painter, *down_arrow);
+ if (down_arrow) this->DrawDownArrow(painter, *down_arrow);
} else {
auto optional_rect = GetCollapsedThumbRect();
if (optional_rect) {
@@ -313,14 +329,26 @@ HorizontalScrollBar::HorizontalScrollBar(
void HorizontalScrollBar::DrawUpArrow(platform::graphics::IPainter* painter,
const Rect& area) {
- // TODO: Do what you must!
painter->FillRectangle(area, GetExpandedArrowBackgroundBrush().get().get());
+
+ platform::graphics::util::WithTransform(
+ painter, Matrix::Translation(area.GetCenter()),
+ [this](platform::graphics::IPainter* painter) {
+ painter->FillGeometry(arrow_geometry_.get(),
+ GetExpandedArrowBrush().get().get());
+ });
}
void HorizontalScrollBar::DrawDownArrow(platform::graphics::IPainter* painter,
const Rect& area) {
- // TODO: Do what you must!
painter->FillRectangle(area, GetExpandedArrowBackgroundBrush().get().get());
+
+ platform::graphics::util::WithTransform(
+ painter, Matrix::Rotation(180) * Matrix::Translation(area.GetCenter()),
+ [this](platform::graphics::IPainter* painter) {
+ painter->FillGeometry(arrow_geometry_.get(),
+ GetExpandedArrowBrush().get().get());
+ });
}
bool HorizontalScrollBar::IsShowBar() {
@@ -440,14 +468,26 @@ VerticalScrollBar::VerticalScrollBar(
void VerticalScrollBar::DrawUpArrow(platform::graphics::IPainter* painter,
const Rect& area) {
- // TODO: Do what you must!
painter->FillRectangle(area, GetExpandedArrowBackgroundBrush().get().get());
+
+ platform::graphics::util::WithTransform(
+ painter, Matrix::Rotation(90) * Matrix::Translation(area.GetCenter()),
+ [this](platform::graphics::IPainter* painter) {
+ painter->FillGeometry(arrow_geometry_.get(),
+ GetExpandedArrowBrush().get().get());
+ });
}
void VerticalScrollBar::DrawDownArrow(platform::graphics::IPainter* painter,
const Rect& area) {
- // TODO: Do what you must!
painter->FillRectangle(area, GetExpandedArrowBackgroundBrush().get().get());
+
+ platform::graphics::util::WithTransform(
+ painter, Matrix::Rotation(270) * Matrix::Translation(area.GetCenter()),
+ [this](platform::graphics::IPainter* painter) {
+ painter->FillGeometry(arrow_geometry_.get(),
+ GetExpandedArrowBrush().get().get());
+ });
}
bool VerticalScrollBar::IsShowBar() {
diff --git a/src/win/graphics/direct/Painter.cpp b/src/win/graphics/direct/Painter.cpp
index 91392ba7..d6999cfa 100644
--- a/src/win/graphics/direct/Painter.cpp
+++ b/src/win/graphics/direct/Painter.cpp
@@ -32,6 +32,14 @@ void D2DPainter::Clear(const Color& color) {
render_target_->Clear(Convert(color));
}
+void D2DPainter::DrawLine(const Point& start, const Point& end, IBrush* brush,
+ float width) {
+ CheckValidation();
+ const auto b = CheckPlatform<ID2DBrush>(brush, GetPlatformId());
+ render_target_->DrawLine(Convert(start), Convert(end),
+ b->GetD2DBrushInterface(), width);
+}
+
void D2DPainter::StrokeRectangle(const Rect& rectangle, IBrush* brush,
float width) {
CheckValidation();
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index c534b909..3b9567cd 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -2,7 +2,12 @@ find_package(GTest CONFIG REQUIRED)
include(GoogleTest)
-add_subdirectory(common)
-
add_library(cru_test_base INTERFACE)
target_link_libraries(cru_test_base INTERFACE GTest::gtest GTest::gtest_main)
+
+add_subdirectory(common)
+add_subdirectory(platform)
+
+if(WIN32)
+ add_subdirectory(win)
+endif()
diff --git a/test/platform/CMakeLists.txt b/test/platform/CMakeLists.txt
new file mode 100644
index 00000000..9ad8fb51
--- /dev/null
+++ b/test/platform/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_executable(cru_platform_base_test
+ MatrixTest.cpp
+)
+target_link_libraries(cru_platform_base_test PRIVATE cru_platform_base cru_test_base)
+
+gtest_discover_tests(cru_platform_base_test)
diff --git a/test/platform/MatrixTest.cpp b/test/platform/MatrixTest.cpp
new file mode 100644
index 00000000..3b8aab27
--- /dev/null
+++ b/test/platform/MatrixTest.cpp
@@ -0,0 +1,37 @@
+#include "cru/platform/GraphBase.hpp"
+#include "cru/platform/Matrix.hpp"
+
+#include <gtest/gtest.h>
+
+using cru::platform::Matrix;
+using cru::platform::Point;
+
+TEST(Matrix, Rotation) {
+ Point p(1, 1);
+
+ Point p90 = Matrix::Rotation(90).TransformPoint(p);
+ ASSERT_FLOAT_EQ(p90.x, -1);
+ ASSERT_FLOAT_EQ(p90.y, 1);
+
+ Point p180 = Matrix::Rotation(180).TransformPoint(p);
+ ASSERT_FLOAT_EQ(p180.x, -1);
+ ASSERT_FLOAT_EQ(p180.y, -1);
+
+ Point p270 = Matrix::Rotation(270).TransformPoint(p);
+ ASSERT_FLOAT_EQ(p270.x, 1);
+ ASSERT_FLOAT_EQ(p270.y, -1);
+}
+
+TEST(Matrix, TranslationAndRotation) {
+ Point p =
+ (Matrix::Translation(1, 1) * Matrix::Rotation(90)).TransformPoint({1, 1});
+ ASSERT_FLOAT_EQ(p.x, -2);
+ ASSERT_FLOAT_EQ(p.y, 2);
+}
+
+TEST(Matrix, RotationAndTranslation) {
+ Point p =
+ (Matrix::Rotation(90) * Matrix::Translation(1, 1)).TransformPoint({1, 1});
+ ASSERT_FLOAT_EQ(p.x, 0);
+ ASSERT_FLOAT_EQ(p.y, 2);
+}
diff --git a/test/win/CMakeLists.txt b/test/win/CMakeLists.txt
new file mode 100644
index 00000000..0ebdd7fe
--- /dev/null
+++ b/test/win/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(graphics)
diff --git a/test/win/graphics/CMakeLists.txt b/test/win/graphics/CMakeLists.txt
new file mode 100644
index 00000000..c90537ac
--- /dev/null
+++ b/test/win/graphics/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(direct)
diff --git a/test/win/graphics/direct/CMakeLists.txt b/test/win/graphics/direct/CMakeLists.txt
new file mode 100644
index 00000000..69e22ef7
--- /dev/null
+++ b/test/win/graphics/direct/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_executable(cru_win_graphics_direct_test
+ ConvertTest.cpp
+)
+target_link_libraries(cru_win_graphics_direct_test PRIVATE cru_win_graphics_direct cru_test_base)
+
+gtest_discover_tests(cru_win_graphics_direct_test)
diff --git a/test/win/graphics/direct/ConvertTest.cpp b/test/win/graphics/direct/ConvertTest.cpp
new file mode 100644
index 00000000..f8f95dac
--- /dev/null
+++ b/test/win/graphics/direct/ConvertTest.cpp
@@ -0,0 +1,29 @@
+#include "cru/platform/Matrix.hpp"
+#include "cru/win/graphics/direct/ConvertUtil.hpp"
+
+#include <gtest/gtest.h>
+
+using cru::platform::Matrix;
+using cru::platform::graphics::win::direct::Convert;
+
+TEST(MatrixConvert, Rotation) {
+ auto matrix = Convert(Matrix::Rotation(90));
+
+ auto m = *D2D1::Matrix3x2F::ReinterpretBaseType(&matrix);
+
+ auto p = m.TransformPoint({1, 1});
+
+ ASSERT_FLOAT_EQ(p.x, -1);
+ ASSERT_FLOAT_EQ(p.y, 1);
+}
+
+TEST(MatrixConvert, RotationAndTranslation) {
+ auto matrix = Convert(Matrix::Rotation(90) * Matrix::Translation(1, 1));
+
+ auto m = *D2D1::Matrix3x2F::ReinterpretBaseType(&matrix);
+
+ auto p = m.TransformPoint({1, 1});
+
+ ASSERT_FLOAT_EQ(p.x, 0);
+ ASSERT_FLOAT_EQ(p.y, 2);
+}