修复滚轮事件不是窗口内位置,新增slot可以覆盖控件的visibility

This commit is contained in:
Nanako 2025-04-04 15:19:25 +08:00
parent fb46da91d4
commit fbf6e7e716
15 changed files with 73 additions and 50 deletions

View File

@ -18,7 +18,7 @@ int main(int argc, char* argv[]) {
manager.add_font(L"C:/Windows/Fonts/seguiemj.ttf");
const auto& text_block = std::make_shared<mtext_block>();
text_block->set_text(U"Hello, World! 你好,世界!\n换行测试1111测试测试测试测试,测试测试😀🐵🙏");
text_block->set_text(U"Hello, World! 你好,世界!\n换行测试1111测试测试测试测试,测试测试😀🐵🙏 😃🐵🙏");
const auto& text_block2 = std::make_shared<mtext_block>();
text_block2->set_text(U"Hello, World!");
@ -26,12 +26,14 @@ int main(int argc, char* argv[]) {
const auto button = mnew(mbutton)
mslot(mbutton)
.margin({10})
.visibility(visibility_t::visible)
[
text_block
];
const auto button2 = mnew(mbutton)
mslot(mbutton)
.visibility(visibility_t::visible)
[
text_block2
];

View File

@ -23,12 +23,12 @@ void platform_window::handle_mouse_button_up(const Eigen::Vector2f& in_window_po
on_mouse_button_up_delegate.broadcast(in_window_pos, in_button);
}
void platform_window::handle_mouse_dbl_click(const Eigen::Vector2f& pos, mouse_button button) {
on_mouse_button_dbl_delegate.broadcast(pos, button);
void platform_window::handle_mouse_dbl_click(const Eigen::Vector2f& in_window_pos, mouse_button button) {
on_mouse_button_dbl_delegate.broadcast(in_window_pos, button);
}
void platform_window::handle_mouse_wheel(const Eigen::Vector2f& pos, wheel_event delta) {
on_mouse_wheel_delegate.broadcast(pos, delta);
void platform_window::handle_mouse_wheel(const Eigen::Vector2f& in_window_pos, wheel_event delta) {
on_mouse_wheel_delegate.broadcast(in_window_pos, delta);
}
void platform_window::handle_mouse_leave() {

View File

@ -179,17 +179,17 @@ public:
/**
* @brief
* @param pos
* @param in_window_pos
* @param button
*/
void handle_mouse_dbl_click(const Eigen::Vector2f& pos, mouse_button button);
void handle_mouse_dbl_click(const Eigen::Vector2f& in_window_pos, mouse_button button);
/**
* @brief
* @param pos
* @param in_window_pos
* @param delta
*/
void handle_mouse_wheel(const Eigen::Vector2f& pos, wheel_event delta);
void handle_mouse_wheel(const Eigen::Vector2f& in_window_pos, wheel_event delta);
/**
* @brief

View File

@ -98,8 +98,15 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
const int x = LOWORD(lParam);
const int y = HIWORD(lParam);
const Eigen::Vector2f pos(static_cast<float>(x), static_cast<float>(y));
POINT screen_point = { x, y };
ScreenToClient(hwnd, &screen_point);
// 现在 screen_point.x 和 screen_point.y 包含相对于窗口客户区的坐标
const Eigen::Vector2f client_pos(static_cast<float>(screen_point.x), static_cast<float>(screen_point.y));
// 计算滚轮事件的增量
const auto delta = platform_event_to_wheel_event(uMsg, wParam, lParam);
window->handle_mouse_wheel(pos, delta);
window->handle_mouse_wheel(client_pos, delta);
}
processed = true;
}

View File

@ -273,7 +273,7 @@ void render_elements::make_image(const Eigen::Vector2f& in_pos, const Eigen::Vec
void render_elements::make_text(const text_layout_t& in_layout, const Eigen::Vector2f& in_pos,
const Eigen::Vector2f& in_size, const geometry_t& in_geometry, const draw_effect& in_effect, const rect_color& in_color,
float in_rotation_radians, const Eigen::Vector2f& in_pivot, const Eigen::Vector2f& in_scale) {
const auto& glyph_sampler = texture_sampler_builder::get_sampler(sampler_type::anisotropic);
const auto& glyph_sampler = texture_sampler_builder::get_sampler(sampler_type::pixel_art);
const auto& emoji_sampler = texture_sampler_builder::get_sampler(sampler_type::anisotropic);
for (const auto& position : in_layout.glyphs) {

View File

@ -66,14 +66,6 @@ void mbutton::on_mouse_leave() {
invalidate(invalidate_reason::paint);
}
hit_test_handle mbutton::on_mouse_move(const Eigen::Vector2f& in_position) {
mborder::on_mouse_move(in_position);
// std::cout << this << ": Mouse moved!" << in_position.x() << ", " << in_position.y() << std::endl;
color_ = {1, 1, 0, 1};
invalidate(invalidate_reason::paint);
return hit_test_handle::handled();
}
hit_test_handle mbutton::on_mouse_button_down(const Eigen::Vector2f& in_position, mouse_button in_button) {
mborder::on_mouse_button_down(in_position, in_button);
std::cout << this << ": Mouse pressed!" << in_position.x() << ", " << in_position.y() << std::endl;
@ -89,11 +81,3 @@ hit_test_handle mbutton::on_mouse_button_up(const Eigen::Vector2f& in_position,
invalidate(invalidate_reason::paint);
return hit_test_handle::handled();
}
hit_test_handle mbutton::on_mouse_wheel(const Eigen::Vector2f& in_position, const wheel_event& in_delta) {
mborder::on_mouse_wheel(in_position, in_delta);
std::cout << this << ": Mouse wheeled!" << in_position.x() << ", " << in_position.y() << std::endl;
color_ = {0, 1, 1, 1};
invalidate(invalidate_reason::paint);
return hit_test_handle::handled();
}

View File

@ -12,10 +12,8 @@ public:
virtual void on_double_click(const Eigen::Vector2f& in_position, mouse_button in_button) override;
virtual void on_mouse_enter() override;
virtual void on_mouse_leave() override;
virtual hit_test_handle on_mouse_move(const Eigen::Vector2f& in_position) override;
virtual hit_test_handle on_mouse_button_down(const Eigen::Vector2f& in_position, mouse_button in_button) override;
virtual hit_test_handle on_mouse_button_up(const Eigen::Vector2f& in_position, mouse_button in_button) override;
virtual hit_test_handle on_mouse_wheel(const Eigen::Vector2f& in_position, const wheel_event& in_delta) override;
private:
linear_color color_;
};

View File

@ -20,6 +20,13 @@ auto mtext_block::compute_desired_size(float in_layout_scale_multiplier) const -
return layout_.total_size;
}
hit_test_handle mtext_block::on_mouse_wheel(const Eigen::Vector2f& in_position, const wheel_event& in_delta) {
font_size_ += in_delta.delta_y;
update_layout();
return mleaf_widget::on_mouse_wheel(in_position, in_delta);
}
void mtext_block::update_layout() {
layout_ = font_manager::instance().layout_text(text_, font_, font_size_, max_width_, line_spacing_);
invalidate(invalidate_reason::layout);
}

View File

@ -39,7 +39,9 @@ public:
auto get_line_spacing() const { return line_spacing_; }
auto get_max_width() const { return max_width_; }
hit_test_handle on_mouse_move(const Eigen::Vector2f& in_position) override { return hit_test_handle::handled(); }
auto compute_desired_size(float in_layout_scale_multiplier) const -> Eigen::Vector2f override;
hit_test_handle on_mouse_wheel(const Eigen::Vector2f& in_position, const wheel_event& in_delta) override;
private:
void update_layout();

View File

@ -37,6 +37,7 @@ struct mcompound_widget_slot {
SLOT_CONTENT()
SLOT_ATTRIBUTE(horizontal_alignment_t, h_alignment)
SLOT_ATTRIBUTE(vertical_alignment_t, v_alignment)
SLOT_OPTIONAL(visibility_t, visibility)
};
/**
@ -71,6 +72,9 @@ public:
slot.set(in_widget);
in_widget->init();
in_widget->set_parent(shared_this);
if (slot_.has_visibility()) {
in_widget->set_visibility(slot_.visibility());
}
return slot;
}
auto& push_slot(const SlotType& in_slot) {
@ -84,6 +88,9 @@ public:
slot_.slot_owner = shared_this;
child_widget->init();
child_widget->set_parent(shared_this);
if (slot_.has_visibility()) {
child_widget->set_visibility(slot_.visibility());
}
return slot_;
}

View File

@ -34,6 +34,8 @@ struct mpanel_widget_slot {
// 插槽功能宏 - 定义内容管理
SLOT_CONTENT()
SLOT_OPTIONAL(visibility_t, visibility)
};
/**
@ -79,6 +81,9 @@ public:
const auto& child_widget = slot.get();
child_widget->init();
child_widget->set_parent(shared_this);
if (slot.has_visibility()) {
child_widget->set_visibility(slot.visibility());
}
invalidate(invalidate_reason::all);
return slot;
}
@ -93,6 +98,9 @@ public:
const auto& child_widget = slot.get();
child_widget->init();
child_widget->set_parent(shared_this);
if (slot.has_visibility()) {
child_widget->set_visibility(slot.visibility());
}
invalidate(invalidate_reason::all);
return slot;
}
@ -105,6 +113,9 @@ public:
const auto& child_widget = slot.get();
child_widget->init();
child_widget->set_parent(shared_this);
if (slot.has_visibility()) {
child_widget->set_visibility(slot.visibility());
}
invalidate(invalidate_reason::all);
return slot;
}

View File

@ -1,4 +1,5 @@
#pragma once
#include <optional>
#define SLOT_ME() auto& me() { return static_cast<T&>(*this) }
@ -12,6 +13,17 @@
protected: \
type name##_{};
#define SLOT_OPTIONAL(type, name) \
public: \
auto& name(type in_##name) { \
name##_ = in_##name; \
return me(); \
} \
const auto& name() const { return name##_.value(); } \
auto has_##name() const { return name##_.has_value(); } \
protected: \
std::optional<type> name##_; \
#define SLOT_CONTENT() \
public: \
auto& set(const std::shared_ptr<mwidget>& in_widget) { \
@ -26,22 +38,6 @@
protected: \
std::shared_ptr<mwidget> widget_{};
#define SLOT_OPTIONAL_ATTRIBUTE(type, name) \
public: \
auto& name(type in_##name) { \
name##_ = in_##name; \
return me(); \
} \
const auto& name() const { return name##_; } \
auto& has_##name(bool in_has_##name) { \
has_##name##_ = in_has_##name; \
return me(); \
} \
const auto& has_##name() const { return has_##name##_; } \
protected: \
type name##_; \
bool has_##name##_{};
#define SLOT_SIZE() \
public: \
auto& stretch(float in_stretch = 1.f) { \

View File

@ -84,6 +84,14 @@ void mwindow::invalidate_all() {
pimpl_->invalidate_all();
}
void mwindow::invalidate(invalidate_reason in_reason) {
mwidget::invalidate(in_reason);
// 如果窗口的布局发生变化,标记为需要重绘
if (has_any_flag(in_reason, invalidate_reason::layout)) {
invalidate(invalidate_reason::paint);
}
}
void mwindow::invalidate_rect(const Eigen::Vector2f& rect) {
pimpl_->invalidate_rect(rect);
}

View File

@ -113,6 +113,8 @@ public:
*/
void invalidate_all();
void invalidate(invalidate_reason in_reason) override;
/**
* @brief
* @param rect

View File

@ -185,7 +185,7 @@ public:
return content_widget_;
}
// 失效处理
// 失效处理
void invalidate_all() {
invalidate_recursive(owner_, invalidate_reason::all);
render_state_.needs_repaint = true;
@ -367,10 +367,9 @@ public:
}
void process_mouse_wheel(const Eigen::Vector2f& window_pos, wheel_event wheel_event) {
std::shared_ptr<mwidget> hover_widget = mouse_.hover_widget.lock();
if (hover_widget) {
hover_widget->on_mouse_wheel(window_pos, wheel_event);
}
const auto& result = perform_hit_test(window_pos, [&](mwidget* widget, const Eigen::Vector2f& local_pos) {
return widget->on_mouse_wheel(local_pos, wheel_event);
});
}
void process_mouse_leave() {