From 8cc531e283fbf08b0280b0a11c2e6498296f98a9 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Wed, 10 Jan 2024 23:06:05 +0100 Subject: [PATCH] Implement mouse event propagation --- .../ZWidget/include/zwidget/core/widget.h | 10 ++- .../widgets/checkboxlabel/checkboxlabel.h | 4 +- .../zwidget/widgets/lineedit/lineedit.h | 6 +- .../zwidget/widgets/listview/listview.h | 6 +- .../zwidget/widgets/pushbutton/pushbutton.h | 4 +- .../zwidget/widgets/scrollbar/scrollbar.h | 4 +- .../zwidget/widgets/tabwidget/tabwidget.h | 5 +- .../zwidget/widgets/textedit/textedit.h | 6 +- libraries/ZWidget/src/core/widget.cpp | 78 ++++++++++++++++--- .../widgets/checkboxlabel/checkboxlabel.cpp | 6 +- .../ZWidget/src/widgets/lineedit/lineedit.cpp | 9 ++- .../ZWidget/src/widgets/listview/listview.cpp | 9 ++- .../src/widgets/pushbutton/pushbutton.cpp | 6 +- .../src/widgets/scrollbar/scrollbar.cpp | 6 +- .../src/widgets/tabwidget/tabwidget.cpp | 22 +++--- .../ZWidget/src/widgets/textedit/textedit.cpp | 9 ++- src/common/widgets/errorwindow.cpp | 3 +- src/common/widgets/errorwindow.h | 2 +- 18 files changed, 135 insertions(+), 60 deletions(-) diff --git a/libraries/ZWidget/include/zwidget/core/widget.h b/libraries/ZWidget/include/zwidget/core/widget.h index 639bfe09c4..34faa14e98 100644 --- a/libraries/ZWidget/include/zwidget/core/widget.h +++ b/libraries/ZWidget/include/zwidget/core/widget.h @@ -72,6 +72,7 @@ public: bool HasFocus(); bool IsEnabled(); bool IsVisible(); + bool IsHidden(); void SetFocus(); void SetEnabled(bool value); @@ -113,11 +114,11 @@ public: protected: virtual void OnPaintFrame(Canvas* canvas) { } virtual void OnPaint(Canvas* canvas) { } + virtual bool OnMouseDown(const Point& pos, int key) { return false; } + virtual bool OnMouseDoubleclick(const Point& pos, int key) { return false; } + virtual bool OnMouseUp(const Point& pos, int key) { return false; } + virtual bool OnMouseWheel(const Point& pos, EInputKey key) { return false; } virtual void OnMouseMove(const Point& pos) { } - virtual void OnMouseDown(const Point& pos, int key) { } - virtual void OnMouseDoubleclick(const Point& pos, int key) { } - virtual void OnMouseUp(const Point& pos, int key) { } - virtual void OnMouseWheel(const Point& pos, EInputKey key) { } virtual void OnMouseLeave() { } virtual void OnRawMouseMove(int dx, int dy) { } virtual void OnKeyChar(std::string chars) { } @@ -180,6 +181,7 @@ private: Widget* FocusWidget = nullptr; Widget* CaptureWidget = nullptr; Widget* HoverWidget = nullptr; + bool HiddenFlag = false; StandardCursor CurrentCursor = StandardCursor::arrow; diff --git a/libraries/ZWidget/include/zwidget/widgets/checkboxlabel/checkboxlabel.h b/libraries/ZWidget/include/zwidget/widgets/checkboxlabel/checkboxlabel.h index 03d9089ebe..c3f3fb4653 100644 --- a/libraries/ZWidget/include/zwidget/widgets/checkboxlabel/checkboxlabel.h +++ b/libraries/ZWidget/include/zwidget/widgets/checkboxlabel/checkboxlabel.h @@ -21,8 +21,8 @@ public: protected: void OnPaint(Canvas* canvas) override; - void OnMouseDown(const Point& pos, int key) override; - void OnMouseUp(const Point& pos, int key) override; + bool OnMouseDown(const Point& pos, int key) override; + bool OnMouseUp(const Point& pos, int key) override; void OnMouseLeave() override; void OnKeyUp(EInputKey key) override; diff --git a/libraries/ZWidget/include/zwidget/widgets/lineedit/lineedit.h b/libraries/ZWidget/include/zwidget/widgets/lineedit/lineedit.h index c34ab11905..526d9eee91 100644 --- a/libraries/ZWidget/include/zwidget/widgets/lineedit/lineedit.h +++ b/libraries/ZWidget/include/zwidget/widgets/lineedit/lineedit.h @@ -72,9 +72,9 @@ protected: void OnPaintFrame(Canvas* canvas) override; void OnPaint(Canvas* canvas) override; void OnMouseMove(const Point& pos) override; - void OnMouseDown(const Point& pos, int key) override; - void OnMouseDoubleclick(const Point& pos, int key) override; - void OnMouseUp(const Point& pos, int key) override; + bool OnMouseDown(const Point& pos, int key) override; + bool OnMouseDoubleclick(const Point& pos, int key) override; + bool OnMouseUp(const Point& pos, int key) override; void OnKeyChar(std::string chars) override; void OnKeyDown(EInputKey key) override; void OnKeyUp(EInputKey key) override; diff --git a/libraries/ZWidget/include/zwidget/widgets/listview/listview.h b/libraries/ZWidget/include/zwidget/widgets/listview/listview.h index 879bda114d..2b150abc06 100644 --- a/libraries/ZWidget/include/zwidget/widgets/listview/listview.h +++ b/libraries/ZWidget/include/zwidget/widgets/listview/listview.h @@ -25,9 +25,9 @@ public: protected: void OnPaint(Canvas* canvas) override; void OnPaintFrame(Canvas* canvas) override; - void OnMouseDown(const Point& pos, int key) override; - void OnMouseDoubleclick(const Point& pos, int key) override; - void OnMouseWheel(const Point& pos, EInputKey key) override; + bool OnMouseDown(const Point& pos, int key) override; + bool OnMouseDoubleclick(const Point& pos, int key) override; + bool OnMouseWheel(const Point& pos, EInputKey key) override; void OnKeyDown(EInputKey key) override; void OnGeometryChanged() override; void OnScrollbarScroll(); diff --git a/libraries/ZWidget/include/zwidget/widgets/pushbutton/pushbutton.h b/libraries/ZWidget/include/zwidget/widgets/pushbutton/pushbutton.h index 80d827d392..b9b6c9654d 100644 --- a/libraries/ZWidget/include/zwidget/widgets/pushbutton/pushbutton.h +++ b/libraries/ZWidget/include/zwidget/widgets/pushbutton/pushbutton.h @@ -21,9 +21,9 @@ public: protected: void OnPaintFrame(Canvas* canvas) override; void OnPaint(Canvas* canvas) override; + bool OnMouseDown(const Point& pos, int key) override; + bool OnMouseUp(const Point& pos, int key) override; void OnMouseMove(const Point& pos) override; - void OnMouseDown(const Point& pos, int key) override; - void OnMouseUp(const Point& pos, int key) override; void OnMouseLeave() override; void OnKeyDown(EInputKey key) override; void OnKeyUp(EInputKey key) override; diff --git a/libraries/ZWidget/include/zwidget/widgets/scrollbar/scrollbar.h b/libraries/ZWidget/include/zwidget/widgets/scrollbar/scrollbar.h index 38afda3832..5ec95c8410 100644 --- a/libraries/ZWidget/include/zwidget/widgets/scrollbar/scrollbar.h +++ b/libraries/ZWidget/include/zwidget/widgets/scrollbar/scrollbar.h @@ -47,9 +47,9 @@ public: std::function FuncScrollEnd; protected: + bool OnMouseDown(const Point& pos, int key) override; + bool OnMouseUp(const Point& pos, int key) override; void OnMouseMove(const Point& pos) override; - void OnMouseDown(const Point& pos, int key) override; - void OnMouseUp(const Point& pos, int key) override; void OnMouseLeave() override; void OnPaint(Canvas* canvas) override; void OnEnableChanged() override; diff --git a/libraries/ZWidget/include/zwidget/widgets/tabwidget/tabwidget.h b/libraries/ZWidget/include/zwidget/widgets/tabwidget/tabwidget.h index 56bb345a8e..357ef8f3b1 100644 --- a/libraries/ZWidget/include/zwidget/widgets/tabwidget/tabwidget.h +++ b/libraries/ZWidget/include/zwidget/widgets/tabwidget/tabwidget.h @@ -85,9 +85,9 @@ public: protected: void OnPaintFrame(Canvas* canvas) override; void OnGeometryChanged() override; + bool OnMouseDown(const Point& pos, int key) override; + bool OnMouseUp(const Point& pos, int key) override; void OnMouseMove(const Point& pos) override; - void OnMouseDown(const Point& pos, int key) override; - void OnMouseUp(const Point& pos, int key) override; void OnMouseLeave() override; private: @@ -95,7 +95,6 @@ private: ImageBox* Icon = nullptr; TextLabel* Label = nullptr; - bool mouseDown = false; bool hot = false; }; diff --git a/libraries/ZWidget/include/zwidget/widgets/textedit/textedit.h b/libraries/ZWidget/include/zwidget/widgets/textedit/textedit.h index e2c6c760c9..ed80eec367 100644 --- a/libraries/ZWidget/include/zwidget/widgets/textedit/textedit.h +++ b/libraries/ZWidget/include/zwidget/widgets/textedit/textedit.h @@ -56,9 +56,9 @@ protected: void OnPaintFrame(Canvas* canvas) override; void OnPaint(Canvas* canvas) override; void OnMouseMove(const Point& pos) override; - void OnMouseDown(const Point& pos, int key) override; - void OnMouseDoubleclick(const Point& pos, int key) override; - void OnMouseUp(const Point& pos, int key) override; + bool OnMouseDown(const Point& pos, int key) override; + bool OnMouseDoubleclick(const Point& pos, int key) override; + bool OnMouseUp(const Point& pos, int key) override; void OnKeyChar(std::string chars) override; void OnKeyDown(EInputKey key) override; void OnKeyUp(EInputKey key) override; diff --git a/libraries/ZWidget/src/core/widget.cpp b/libraries/ZWidget/src/core/widget.cpp index f323855838..7ddc1ca59c 100644 --- a/libraries/ZWidget/src/core/widget.cpp +++ b/libraries/ZWidget/src/core/widget.cpp @@ -172,6 +172,11 @@ void Widget::Show() { DispWindow->Show(); } + else if (HiddenFlag) + { + HiddenFlag = false; + Update(); + } } void Widget::ShowFullscreen() @@ -213,6 +218,11 @@ void Widget::Hide() if (DispWindow) DispWindow->Hide(); } + else if (!HiddenFlag) + { + HiddenFlag = true; + Update(); + } } void Widget::ActivateWindow() @@ -299,7 +309,7 @@ void Widget::Paint(Canvas* canvas) OnPaint(canvas); for (Widget* w = FirstChild(); w != nullptr; w = w->NextSibling()) { - if (w->Type == WidgetType::Child) + if (w->Type == WidgetType::Child && !w->HiddenFlag) w->Paint(canvas); } canvas->setOrigin(oldOrigin); @@ -323,9 +333,21 @@ bool Widget::IsEnabled() return true; } +bool Widget::IsHidden() +{ + return !IsVisible(); +} + bool Widget::IsVisible() { - return true; + if (Type != WidgetType::Child) + { + return true; // DispWindow->IsVisible(); + } + else + { + return !HiddenFlag; + } } void Widget::SetFocus() @@ -441,7 +463,7 @@ Widget* Widget::ChildAt(const Point& pos) { for (Widget* cur = LastChild(); cur != nullptr; cur = cur->PrevSibling()) { - if (cur->FrameGeometry.contains(pos)) + if (!cur->HiddenFlag && cur->FrameGeometry.contains(pos)) { Widget* cur2 = cur->ChildAt(pos - cur->ContentGeometry.topLeft()); return cur2 ? cur2 : cur; @@ -523,12 +545,26 @@ void Widget::OnWindowMouseMove(const Point& pos) if (HoverWidget != widget) { if (HoverWidget) - HoverWidget->OnMouseLeave(); + { + for (Widget* w = HoverWidget; w != widget && w != this; w = w->Parent()) + { + Widget* p = w->Parent(); + if (!w->FrameGeometry.contains(p->MapFrom(this, pos))) + { + w->OnMouseLeave(); + } + } + } HoverWidget = widget; } DispWindow->SetCursor(widget->CurrentCursor); - widget->OnMouseMove(widget->MapFrom(this, pos)); + + do + { + widget->OnMouseMove(widget->MapFrom(this, pos)); + widget = widget->Parent(); + } while (widget != this); } } @@ -543,7 +579,13 @@ void Widget::OnWindowMouseDown(const Point& pos, EInputKey key) Widget* widget = ChildAt(pos); if (!widget) widget = this; - widget->OnMouseDown(widget->MapFrom(this, pos), key); + while (widget) + { + bool stopPropagation = widget->OnMouseDown(widget->MapFrom(this, pos), key); + if (stopPropagation || widget == this) + break; + widget = widget->Parent(); + } } } @@ -558,7 +600,13 @@ void Widget::OnWindowMouseDoubleclick(const Point& pos, EInputKey key) Widget* widget = ChildAt(pos); if (!widget) widget = this; - widget->OnMouseDoubleclick(widget->MapFrom(this, pos), key); + while (widget) + { + bool stopPropagation = widget->OnMouseDoubleclick(widget->MapFrom(this, pos), key); + if (stopPropagation || widget == this) + break; + widget = widget->Parent(); + } } } @@ -573,7 +621,13 @@ void Widget::OnWindowMouseUp(const Point& pos, EInputKey key) Widget* widget = ChildAt(pos); if (!widget) widget = this; - widget->OnMouseUp(widget->MapFrom(this, pos), key); + while (widget) + { + bool stopPropagation = widget->OnMouseUp(widget->MapFrom(this, pos), key); + if (stopPropagation || widget == this) + break; + widget = widget->Parent(); + } } } @@ -588,7 +642,13 @@ void Widget::OnWindowMouseWheel(const Point& pos, EInputKey key) Widget* widget = ChildAt(pos); if (!widget) widget = this; - widget->OnMouseWheel(widget->MapFrom(this, pos), key); + while (widget) + { + bool stopPropagation = widget->OnMouseWheel(widget->MapFrom(this, pos), key); + if (stopPropagation || widget == this) + break; + widget = widget->Parent(); + } } } diff --git a/libraries/ZWidget/src/widgets/checkboxlabel/checkboxlabel.cpp b/libraries/ZWidget/src/widgets/checkboxlabel/checkboxlabel.cpp index deed9d5078..6cf90badf0 100644 --- a/libraries/ZWidget/src/widgets/checkboxlabel/checkboxlabel.cpp +++ b/libraries/ZWidget/src/widgets/checkboxlabel/checkboxlabel.cpp @@ -56,19 +56,21 @@ void CheckboxLabel::OnPaint(Canvas* canvas) canvas->drawText(Point(14.0, GetHeight() - 5.0), Colorf::fromRgba8(255, 255, 255), text); } -void CheckboxLabel::OnMouseDown(const Point& pos, int key) +bool CheckboxLabel::OnMouseDown(const Point& pos, int key) { mouseDownActive = true; SetFocus(); + return true; } -void CheckboxLabel::OnMouseUp(const Point& pos, int key) +bool CheckboxLabel::OnMouseUp(const Point& pos, int key) { if (mouseDownActive) { Toggle(); } mouseDownActive = false; + return true; } void CheckboxLabel::OnMouseLeave() diff --git a/libraries/ZWidget/src/widgets/lineedit/lineedit.cpp b/libraries/ZWidget/src/widgets/lineedit/lineedit.cpp index 8a7af4ec42..34391fd19a 100644 --- a/libraries/ZWidget/src/widgets/lineedit/lineedit.cpp +++ b/libraries/ZWidget/src/widgets/lineedit/lineedit.cpp @@ -301,7 +301,7 @@ void LineEdit::OnMouseMove(const Point& pos) } } -void LineEdit::OnMouseDown(const Point& pos, int key) +bool LineEdit::OnMouseDown(const Point& pos, int key) { if (key == IK_LeftMouse) { @@ -318,13 +318,15 @@ void LineEdit::OnMouseDown(const Point& pos, int key) } Update(); } + return true; } -void LineEdit::OnMouseDoubleclick(const Point& pos, int key) +bool LineEdit::OnMouseDoubleclick(const Point& pos, int key) { + return true; } -void LineEdit::OnMouseUp(const Point& pos, int key) +bool LineEdit::OnMouseUp(const Point& pos, int key) { if (mouse_selecting && key == IK_LeftMouse) { @@ -346,6 +348,7 @@ void LineEdit::OnMouseUp(const Point& pos, int key) Update(); } } + return true; } void LineEdit::OnKeyChar(std::string chars) diff --git a/libraries/ZWidget/src/widgets/listview/listview.cpp b/libraries/ZWidget/src/widgets/listview/listview.cpp index 680b41d143..717f958272 100644 --- a/libraries/ZWidget/src/widgets/listview/listview.cpp +++ b/libraries/ZWidget/src/widgets/listview/listview.cpp @@ -96,7 +96,7 @@ void ListView::OnPaintFrame(Canvas* canvas) canvas->fillRect(Rect::xywh(w - 1.0, 0.0, 1.0, h - 0.0), bordercolor); } -void ListView::OnMouseDown(const Point& pos, int key) +bool ListView::OnMouseDown(const Point& pos, int key) { SetFocus(); @@ -109,17 +109,19 @@ void ListView::OnMouseDown(const Point& pos, int key) ScrollToItem(selectedItem); } } + return true; } -void ListView::OnMouseDoubleclick(const Point& pos, int key) +bool ListView::OnMouseDoubleclick(const Point& pos, int key) { if (key == IK_LeftMouse) { Activate(); } + return true; } -void ListView::OnMouseWheel(const Point& pos, EInputKey key) +bool ListView::OnMouseWheel(const Point& pos, EInputKey key) { if (key == IK_MouseWheelUp) { @@ -129,6 +131,7 @@ void ListView::OnMouseWheel(const Point& pos, EInputKey key) { scrollbar->SetPosition(std::min(scrollbar->GetPosition() + 20.0, scrollbar->GetMax())); } + return true; } void ListView::OnKeyDown(EInputKey key) diff --git a/libraries/ZWidget/src/widgets/pushbutton/pushbutton.cpp b/libraries/ZWidget/src/widgets/pushbutton/pushbutton.cpp index 2e2e348cb5..d838fe4249 100644 --- a/libraries/ZWidget/src/widgets/pushbutton/pushbutton.cpp +++ b/libraries/ZWidget/src/widgets/pushbutton/pushbutton.cpp @@ -57,14 +57,15 @@ void PushButton::OnMouseMove(const Point& pos) } } -void PushButton::OnMouseDown(const Point& pos, int key) +bool PushButton::OnMouseDown(const Point& pos, int key) { SetFocus(); buttonDown = true; Update(); + return true; } -void PushButton::OnMouseUp(const Point& pos, int key) +bool PushButton::OnMouseUp(const Point& pos, int key) { if (buttonDown) { @@ -73,6 +74,7 @@ void PushButton::OnMouseUp(const Point& pos, int key) Repaint(); Click(); } + return true; } void PushButton::OnMouseLeave() diff --git a/libraries/ZWidget/src/widgets/scrollbar/scrollbar.cpp b/libraries/ZWidget/src/widgets/scrollbar/scrollbar.cpp index 1462981630..489a663438 100644 --- a/libraries/ZWidget/src/widgets/scrollbar/scrollbar.cpp +++ b/libraries/ZWidget/src/widgets/scrollbar/scrollbar.cpp @@ -169,7 +169,7 @@ void Scrollbar::OnMouseMove(const Point& pos) Update(); } -void Scrollbar::OnMouseDown(const Point& pos, int key) +bool Scrollbar::OnMouseDown(const Point& pos, int key) { mouse_drag_start_pos = pos; @@ -254,9 +254,10 @@ void Scrollbar::OnMouseDown(const Point& pos, int key) Update(); CaptureMouse(); + return true; } -void Scrollbar::OnMouseUp(const Point& pos, int key) +bool Scrollbar::OnMouseUp(const Point& pos, int key) { if (mouse_down_mode == mouse_down_thumb_drag) { @@ -269,6 +270,7 @@ void Scrollbar::OnMouseUp(const Point& pos, int key) Update(); ReleaseMouseCapture(); + return true; } void Scrollbar::OnMouseLeave() diff --git a/libraries/ZWidget/src/widgets/tabwidget/tabwidget.cpp b/libraries/ZWidget/src/widgets/tabwidget/tabwidget.cpp index 2d8b26ba81..d22b7e2e65 100644 --- a/libraries/ZWidget/src/widgets/tabwidget/tabwidget.cpp +++ b/libraries/ZWidget/src/widgets/tabwidget/tabwidget.cpp @@ -104,6 +104,7 @@ int TabBar::AddTab(const std::shared_ptr& icon, const std::string& label) TabBarTab* tab = new TabBarTab(this); tab->SetIcon(icon); tab->SetText(label); + tab->OnClick = [=]() { OnTabClicked(tab); }; int pageIndex = Tabs.size(); Tabs.push_back(tab); if (CurrentIndex == -1) @@ -270,27 +271,21 @@ void TabBarTab::OnMouseMove(const Point& pos) } } -void TabBarTab::OnMouseDown(const Point& pos, int key) +bool TabBarTab::OnMouseDown(const Point& pos, int key) { - mouseDown = true; - Update(); + if (OnClick) + OnClick(); + return true; } -void TabBarTab::OnMouseUp(const Point& pos, int key) +bool TabBarTab::OnMouseUp(const Point& pos, int key) { - if (mouseDown) - { - mouseDown = false; - Repaint(); - if (OnClick) - OnClick(); - } + return true; } void TabBarTab::OnMouseLeave() { hot = false; - mouseDown = false; Update(); } @@ -309,7 +304,10 @@ void TabWidgetStack::SetCurrentWidget(Widget* widget) CurrentWidget->SetVisible(false); CurrentWidget = widget; if (CurrentWidget) + { CurrentWidget->SetVisible(true); + OnGeometryChanged(); + } } } diff --git a/libraries/ZWidget/src/widgets/textedit/textedit.cpp b/libraries/ZWidget/src/widgets/textedit/textedit.cpp index 9ddb5fba49..dca840a1bf 100644 --- a/libraries/ZWidget/src/widgets/textedit/textedit.cpp +++ b/libraries/ZWidget/src/widgets/textedit/textedit.cpp @@ -286,7 +286,7 @@ void TextEdit::OnMouseMove(const Point& pos) } } -void TextEdit::OnMouseDown(const Point& pos, int key) +bool TextEdit::OnMouseDown(const Point& pos, int key) { if (key == IK_LeftMouse) { @@ -298,13 +298,15 @@ void TextEdit::OnMouseDown(const Point& pos, int key) Update(); } + return true; } -void TextEdit::OnMouseDoubleclick(const Point& pos, int key) +bool TextEdit::OnMouseDoubleclick(const Point& pos, int key) { + return true; } -void TextEdit::OnMouseUp(const Point& pos, int key) +bool TextEdit::OnMouseUp(const Point& pos, int key) { if (mouse_selecting && key == IK_LeftMouse) { @@ -326,6 +328,7 @@ void TextEdit::OnMouseUp(const Point& pos, int key) Update(); } } + return true; } void TextEdit::OnKeyChar(std::string chars) diff --git a/src/common/widgets/errorwindow.cpp b/src/common/widgets/errorwindow.cpp index 6b6b71035c..e0af0730b7 100644 --- a/src/common/widgets/errorwindow.cpp +++ b/src/common/widgets/errorwindow.cpp @@ -212,7 +212,7 @@ void LogViewer::OnPaint(Canvas* canvas) } } -void LogViewer::OnMouseWheel(const Point& pos, EInputKey key) +bool LogViewer::OnMouseWheel(const Point& pos, EInputKey key) { if (key == IK_MouseWheelUp) { @@ -222,6 +222,7 @@ void LogViewer::OnMouseWheel(const Point& pos, EInputKey key) { ScrollDown(4); } + return true; } void LogViewer::OnKeyDown(EInputKey key) diff --git a/src/common/widgets/errorwindow.h b/src/common/widgets/errorwindow.h index 63304b33f1..f38eb676cb 100644 --- a/src/common/widgets/errorwindow.h +++ b/src/common/widgets/errorwindow.h @@ -43,7 +43,7 @@ public: protected: void OnPaintFrame(Canvas* canvas) override; void OnPaint(Canvas* canvas) override; - void OnMouseWheel(const Point& pos, EInputKey key) override; + bool OnMouseWheel(const Point& pos, EInputKey key) override; void OnKeyDown(EInputKey key) override; void OnGeometryChanged() override;