From d42abb3c7bc14d882320b03e048ace62c155692a Mon Sep 17 00:00:00 2001 From: Tobias Christiansen Date: Sun, 2 Jan 2022 17:16:14 +0100 Subject: [PATCH] PixelPaint: Use the wrapped filters for the Filter Gallery Now, the filters can supply the Filter Gallery with a GUI::Widget such that the user can interact with the filter. The Filter Gallery in turn only calls apply() on the filter once it should be run. This decouples the PixelPaint filters a lot from the ones supported by LibGfx and paves the way to filters with settings. For now there still are just the plain LibGfx filters so this change feels like introducing a lot of boilerplate, but in the future there will be a lot more to see. --- .../Applications/PixelPaint/FilterGallery.cpp | 31 ++-- .../Applications/PixelPaint/FilterGallery.h | 5 + .../Applications/PixelPaint/FilterModel.cpp | 143 +++--------------- .../Applications/PixelPaint/FilterModel.h | 17 ++- 4 files changed, 55 insertions(+), 141 deletions(-) diff --git a/Userland/Applications/PixelPaint/FilterGallery.cpp b/Userland/Applications/PixelPaint/FilterGallery.cpp index 97cc33dd11..bdbfd27e6f 100644 --- a/Userland/Applications/PixelPaint/FilterGallery.cpp +++ b/Userland/Applications/PixelPaint/FilterGallery.cpp @@ -25,30 +25,41 @@ FilterGallery::FilterGallery(GUI::Window* parent_window, ImageEditor* editor) if (!main_widget.load_from_gml(filter_gallery_gml)) VERIFY_NOT_REACHED(); - auto filter_tree = main_widget.find_descendant_of_type_named("tree_view"); + m_filter_tree = main_widget.find_descendant_of_type_named("tree_view"); auto apply_button = main_widget.find_descendant_of_type_named("apply_button"); auto cancel_button = main_widget.find_descendant_of_type_named("cancel_button"); - auto config_widget = main_widget.find_descendant_of_type_named("config_widget"); + m_config_widget = main_widget.find_descendant_of_type_named("config_widget"); - VERIFY(filter_tree); + VERIFY(m_filter_tree); VERIFY(apply_button); VERIFY(cancel_button); - VERIFY(config_widget); + VERIFY(m_config_widget); auto filter_model = FilterModel::create(editor); - filter_tree->set_model(filter_model); - filter_tree->expand_tree(); + m_filter_tree->set_model(filter_model); + m_filter_tree->expand_tree(); - apply_button->on_click = [this, filter_tree](auto) { - auto selected_index = filter_tree->selection().first(); + m_filter_tree->on_selection_change = [this]() { + auto selected_index = m_filter_tree->selection().first(); if (!selected_index.is_valid()) - done(ExecResult::ExecAborted); + return; auto selected_filter = static_cast(selected_index.internal_data()); if (selected_filter->type != FilterModel::FilterInfo::Type::Filter) + return; + + m_selected_filter = selected_filter->filter; + + m_selected_filter_config_widget = m_selected_filter->get_settings_widget(); + m_config_widget->remove_all_children(); + m_config_widget->add_child(*m_selected_filter_config_widget); + }; + + apply_button->on_click = [this](auto) { + if (!m_selected_filter) done(ExecResult::ExecAborted); - selected_filter->apply_filter(); + m_selected_filter->apply(); done(ExecResult::ExecOK); }; diff --git a/Userland/Applications/PixelPaint/FilterGallery.h b/Userland/Applications/PixelPaint/FilterGallery.h index 8fe642a061..39ddcea584 100644 --- a/Userland/Applications/PixelPaint/FilterGallery.h +++ b/Userland/Applications/PixelPaint/FilterGallery.h @@ -6,6 +6,7 @@ #pragma once +#include "Filters/Filter.h" #include "ImageEditor.h" #include @@ -16,6 +17,10 @@ class FilterGallery final : public GUI::Dialog { private: FilterGallery(GUI::Window* parent_window, ImageEditor*); + GUI::TreeView* m_filter_tree { nullptr }; + GUI::Widget* m_config_widget { nullptr }; + RefPtr m_selected_filter_config_widget { nullptr }; + Filter* m_selected_filter { nullptr }; }; } diff --git a/Userland/Applications/PixelPaint/FilterModel.cpp b/Userland/Applications/PixelPaint/FilterModel.cpp index 8357370449..fef27ba6ce 100644 --- a/Userland/Applications/PixelPaint/FilterModel.cpp +++ b/Userland/Applications/PixelPaint/FilterModel.cpp @@ -7,144 +7,39 @@ #include "FilterModel.h" #include "FilterParams.h" +#include "Filters/BoxBlur3.h" +#include "Filters/BoxBlur5.h" +#include "Filters/GaussBlur3.h" +#include "Filters/GaussBlur5.h" +#include "Filters/Grayscale.h" +#include "Filters/Invert.h" +#include "Filters/LaplaceCardinal.h" +#include "Filters/LaplaceDiagonal.h" +#include "Filters/Sharpen.h" #include "Layer.h" #include -#include namespace PixelPaint { FilterModel::FilterModel(ImageEditor* editor) { auto spatial_category = FilterInfo::create_category("Spatial"); - auto edge_detect_category = FilterInfo::create_category("Edge Detect", spatial_category); - auto laplace_cardinal_filter = FilterInfo::create_filter( - "Laplacian (Cardinal)", [editor]() { - if (!editor) - return; - if (auto* layer = editor->active_layer()) { - Gfx::LaplacianFilter filter; - if (auto parameters = PixelPaint::FilterParameters::get(false)) { - filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect(), *parameters); - layer->did_modify_bitmap(layer->rect()); - editor->did_complete_action(); - } - } - }, - edge_detect_category); - auto laplace_diagonal_filter = FilterInfo::create_filter( - "Laplacian (Diagonal)", [editor]() { - if (!editor) - return; - if (auto* layer = editor->active_layer()) { - Gfx::LaplacianFilter filter; - if (auto parameters = PixelPaint::FilterParameters::get(true)) { - filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect(), *parameters); - layer->did_modify_bitmap(layer->rect()); - editor->did_complete_action(); - } - } - }, - edge_detect_category); + auto edge_detect_category = FilterInfo::create_category("Edge Detection", spatial_category); + auto laplace_cardinal_filter = FilterInfo::create_filter(editor, edge_detect_category); + auto laplace_diagonal_filter = FilterInfo::create_filter(editor, edge_detect_category); auto blur_category = FilterInfo::create_category("Blur & Sharpen", spatial_category); - auto gaussian_blur_filter_3 = FilterInfo::create_filter( - "Gaussian Blur (3x3)", [editor]() { - if (!editor) - return; - if (auto* layer = editor->active_layer()) { - Gfx::SpatialGaussianBlurFilter<3> filter; - if (auto parameters = PixelPaint::FilterParameters>::get()) { - filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect(), *parameters); - layer->did_modify_bitmap(layer->rect()); - editor->did_complete_action(); - } - } - }, - blur_category); - auto gaussian_blur_filter_5 = FilterInfo::create_filter( - "Gaussian Blur (5x5)", [editor]() { - if (!editor) - return; - if (auto* layer = editor->active_layer()) { - Gfx::SpatialGaussianBlurFilter<5> filter; - if (auto parameters = PixelPaint::FilterParameters>::get()) { - filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect(), *parameters); - layer->did_modify_bitmap(layer->rect()); - editor->did_complete_action(); - } - } - }, - blur_category); - auto box_blur_filter_3 = FilterInfo::create_filter( - "Box Blur (3x3)", [editor]() { - if (!editor) - return; - if (auto* layer = editor->active_layer()) { - Gfx::BoxBlurFilter<3> filter; - if (auto parameters = PixelPaint::FilterParameters>::get()) { - filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect(), *parameters); - layer->did_modify_bitmap(layer->rect()); - editor->did_complete_action(); - } - } - }, - blur_category); - auto box_blur_filter_5 = FilterInfo::create_filter( - "Box Blur (5x5)", [editor]() { - if (!editor) - return; - if (auto* layer = editor->active_layer()) { - Gfx::BoxBlurFilter<5> filter; - if (auto parameters = PixelPaint::FilterParameters>::get()) { - filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect(), *parameters); - layer->did_modify_bitmap(layer->rect()); - editor->did_complete_action(); - } - } - }, - blur_category); - auto sharpen_filter = FilterInfo::create_filter( - "Sharpen", [editor]() { - if (!editor) - return; - if (auto* layer = editor->active_layer()) { - Gfx::SharpenFilter filter; - if (auto parameters = PixelPaint::FilterParameters::get()) { - filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect(), *parameters); - layer->did_modify_bitmap(layer->rect()); - editor->did_complete_action(); - } - } - }, - blur_category); + auto gaussian_blur_filter_3 = FilterInfo::create_filter(editor, blur_category); + auto gaussian_blur_filter_5 = FilterInfo::create_filter(editor, blur_category); + auto box_blur_filter_3 = FilterInfo::create_filter(editor, blur_category); + auto box_blur_filter_5 = FilterInfo::create_filter(editor, blur_category); + auto sharpen_filter = FilterInfo::create_filter(editor, blur_category); m_filters.append(spatial_category); auto color_category = FilterInfo::create_category("Color"); - auto grayscale_filter = FilterInfo::create_filter( - "Grayscale", [editor]() { - if (!editor) - return; - if (auto* layer = editor->active_layer()) { - Gfx::GrayscaleFilter filter; - filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect()); - layer->did_modify_bitmap(layer->rect()); - editor->did_complete_action(); - } - }, - color_category); - auto invert_filter = FilterInfo::create_filter( - "Invert", [editor]() { - if (!editor) - return; - if (auto* layer = editor->active_layer()) { - Gfx::InvertFilter filter; - filter.apply(layer->bitmap(), layer->rect(), layer->bitmap(), layer->rect()); - layer->did_modify_bitmap(layer->rect()); - editor->did_complete_action(); - } - }, - color_category); + auto grayscale_filter = FilterInfo::create_filter(editor, color_category); + auto invert_filter = FilterInfo::create_filter(editor, color_category); m_filters.append(color_category); diff --git a/Userland/Applications/PixelPaint/FilterModel.h b/Userland/Applications/PixelPaint/FilterModel.h index 01a7c25d2d..e63363d858 100644 --- a/Userland/Applications/PixelPaint/FilterModel.h +++ b/Userland/Applications/PixelPaint/FilterModel.h @@ -6,6 +6,7 @@ #pragma once +#include "Filters/Filter.h" #include "ImageEditor.h" #include #include @@ -24,19 +25,21 @@ public: String text; - Function apply_filter; + Filter* filter { nullptr }; NonnullRefPtrVector children; FilterInfo* parent; - static NonnullRefPtr create_filter(String const& text, Function apply_filter, FilterInfo* parent = nullptr) + template + static NonnullRefPtr create_filter(ImageEditor* editor, FilterInfo* parent = nullptr) { - auto filter = adopt_ref(*new FilterInfo(Type::Filter, text, parent)); - filter->ref(); - filter->apply_filter = move(apply_filter); + auto filter = static_cast(new FilterType(editor)); + auto filter_info = adopt_ref(*new FilterInfo(Type::Filter, filter->filter_name(), parent)); + filter_info->filter = filter; + filter_info->ref(); if (parent) - parent->children.append(filter); - return filter; + parent->children.append(filter_info); + return filter_info; } static NonnullRefPtr create_category(String const& text, FilterInfo* parent = nullptr)