From 18d344609fc15c15110fd629a4b1d33b35ab0f85 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Wed, 5 May 2021 22:15:09 +0200 Subject: [PATCH] LibGUI: Add ScrollableContainerWidget :^) This widget provides a scrollable view onto another (child) widget. If the child is larger than the parent, scrollbars are provided for panning around the child. --- Userland/Libraries/LibGUI/CMakeLists.txt | 1 + .../LibGUI/ScrollableContainerWidget.cpp | 74 +++++++++++++++++++ .../LibGUI/ScrollableContainerWidget.h | 36 +++++++++ 3 files changed, 111 insertions(+) create mode 100644 Userland/Libraries/LibGUI/ScrollableContainerWidget.cpp create mode 100644 Userland/Libraries/LibGUI/ScrollableContainerWidget.h diff --git a/Userland/Libraries/LibGUI/CMakeLists.txt b/Userland/Libraries/LibGUI/CMakeLists.txt index 84f32ff05f..65362b1184 100644 --- a/Userland/Libraries/LibGUI/CMakeLists.txt +++ b/Userland/Libraries/LibGUI/CMakeLists.txt @@ -74,6 +74,7 @@ set(SOURCES RegularEditingEngine.cpp ResizeCorner.cpp RunningProcessesModel.cpp + ScrollableContainerWidget.cpp Scrollbar.cpp SeparatorWidget.cpp Shortcut.cpp diff --git a/Userland/Libraries/LibGUI/ScrollableContainerWidget.cpp b/Userland/Libraries/LibGUI/ScrollableContainerWidget.cpp new file mode 100644 index 0000000000..d3b4c4728f --- /dev/null +++ b/Userland/Libraries/LibGUI/ScrollableContainerWidget.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +namespace GUI { + +ScrollableContainerWidget::ScrollableContainerWidget() +{ +} + +ScrollableContainerWidget::~ScrollableContainerWidget() +{ +} + +void ScrollableContainerWidget::did_scroll() +{ + AbstractScrollableWidget::did_scroll(); + update_widget_position(); +} + +void ScrollableContainerWidget::update_widget_position() +{ + if (!m_widget) + return; + m_widget->move_to(-horizontal_scrollbar().value(), -vertical_scrollbar().value()); +} + +void ScrollableContainerWidget::update_widget_size() +{ + if (!m_widget) + return; + m_widget->do_layout(); + if (m_widget->is_shrink_to_fit() && m_widget->layout()) { + auto new_size = frame_inner_rect().size(); + auto preferred_size = m_widget->layout()->preferred_size(); + if (preferred_size.width() != -1) + new_size.set_width(preferred_size.width()); + if (preferred_size.height() != -1) + new_size.set_height(preferred_size.height()); + m_widget->resize(new_size); + set_content_size(new_size); + } +} + +void ScrollableContainerWidget::resize_event(GUI::ResizeEvent& event) +{ + AbstractScrollableWidget::resize_event(event); + update_widget_size(); +} + +void ScrollableContainerWidget::set_widget(GUI::Widget* widget) +{ + if (m_widget == widget) + return; + + if (m_widget) + remove_child(*m_widget); + + m_widget = widget; + + if (m_widget) { + add_child(*m_widget); + m_widget->move_to_back(); + } + update_widget_size(); + update_widget_position(); +} + +} diff --git a/Userland/Libraries/LibGUI/ScrollableContainerWidget.h b/Userland/Libraries/LibGUI/ScrollableContainerWidget.h new file mode 100644 index 0000000000..0d2410a7a3 --- /dev/null +++ b/Userland/Libraries/LibGUI/ScrollableContainerWidget.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace GUI { + +class ScrollableContainerWidget : public GUI::AbstractScrollableWidget { + C_OBJECT(ScrollableContainerWidget); + +public: + virtual ~ScrollableContainerWidget(); + + void set_widget(GUI::Widget*); + GUI::Widget* widget() { return m_widget; } + GUI::Widget const* widget() const { return m_widget; } + +protected: + virtual void did_scroll() override; + virtual void resize_event(GUI::ResizeEvent&) override; + +private: + void update_widget_size(); + void update_widget_position(); + + ScrollableContainerWidget(); + + RefPtr m_widget; +}; + +}