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.
This commit is contained in:
Tobias Christiansen 2022-01-02 17:16:14 +01:00 committed by Andreas Kling
parent 0deadcdb28
commit d42abb3c7b
4 changed files with 55 additions and 141 deletions

View file

@ -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<GUI::TreeView>("tree_view");
m_filter_tree = main_widget.find_descendant_of_type_named<GUI::TreeView>("tree_view");
auto apply_button = main_widget.find_descendant_of_type_named<GUI::Button>("apply_button");
auto cancel_button = main_widget.find_descendant_of_type_named<GUI::Button>("cancel_button");
auto config_widget = main_widget.find_descendant_of_type_named<GUI::Widget>("config_widget");
m_config_widget = main_widget.find_descendant_of_type_named<GUI::Widget>("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<const FilterModel::FilterInfo*>(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);
};

View file

@ -6,6 +6,7 @@
#pragma once
#include "Filters/Filter.h"
#include "ImageEditor.h"
#include <LibGUI/Dialog.h>
@ -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<GUI::Widget> m_selected_filter_config_widget { nullptr };
Filter* m_selected_filter { nullptr };
};
}

View file

@ -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 <LibGUI/FileIconProvider.h>
#include <LibGfx/Filters/LaplacianFilter.h>
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<Gfx::LaplacianFilter>::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<Gfx::LaplacianFilter>::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<Filters::LaplaceCardinal>(editor, edge_detect_category);
auto laplace_diagonal_filter = FilterInfo::create_filter<Filters::LaplaceDiagonal>(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<Gfx::SpatialGaussianBlurFilter<3>>::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<Gfx::SpatialGaussianBlurFilter<3>>::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<Gfx::BoxBlurFilter<3>>::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<Gfx::BoxBlurFilter<3>>::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<Gfx::SharpenFilter>::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<Filters::GaussBlur3>(editor, blur_category);
auto gaussian_blur_filter_5 = FilterInfo::create_filter<Filters::GaussBlur5>(editor, blur_category);
auto box_blur_filter_3 = FilterInfo::create_filter<Filters::BoxBlur3>(editor, blur_category);
auto box_blur_filter_5 = FilterInfo::create_filter<Filters::BoxBlur5>(editor, blur_category);
auto sharpen_filter = FilterInfo::create_filter<Filters::Sharpen>(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<Filters::Grayscale>(editor, color_category);
auto invert_filter = FilterInfo::create_filter<Filters::Invert>(editor, color_category);
m_filters.append(color_category);

View file

@ -6,6 +6,7 @@
#pragma once
#include "Filters/Filter.h"
#include "ImageEditor.h"
#include <AK/NonnullRefPtr.h>
#include <LibGUI/Model.h>
@ -24,19 +25,21 @@ public:
String text;
Function<void()> apply_filter;
Filter* filter { nullptr };
NonnullRefPtrVector<FilterInfo> children;
FilterInfo* parent;
static NonnullRefPtr<FilterInfo> create_filter(String const& text, Function<void()> apply_filter, FilterInfo* parent = nullptr)
template<typename FilterType>
static NonnullRefPtr<FilterInfo> 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<Filter*>(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<FilterInfo> create_category(String const& text, FilterInfo* parent = nullptr)