diff --git a/Applications/PaintBrush/Image.cpp b/Applications/PaintBrush/Image.cpp index 63861acf23..b2fcc459a9 100644 --- a/Applications/PaintBrush/Image.cpp +++ b/Applications/PaintBrush/Image.cpp @@ -26,6 +26,7 @@ #include "Image.h" #include "Layer.h" +#include "LayerModel.h" #include namespace PaintBrush { @@ -63,4 +64,11 @@ void Image::add_layer(NonnullRefPtr layer) m_layers.append(move(layer)); } +GUI::Model& Image::layer_model() +{ + if (!m_layer_model) + m_layer_model = LayerModel::create(*this); + return *m_layer_model; +} + } diff --git a/Applications/PaintBrush/Image.h b/Applications/PaintBrush/Image.h index 76f4cbe188..47950796dd 100644 --- a/Applications/PaintBrush/Image.h +++ b/Applications/PaintBrush/Image.h @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -52,11 +53,14 @@ public: void paint_into(GUI::Painter&, const Gfx::Rect& dest_rect, const Gfx::Rect& src_rect); + GUI::Model& layer_model(); + private: explicit Image(const Gfx::Size&); Gfx::Size m_size; NonnullRefPtrVector m_layers; + RefPtr m_layer_model; }; } diff --git a/Applications/PaintBrush/ImageEditor.cpp b/Applications/PaintBrush/ImageEditor.cpp index 76b052e730..b654b90eef 100644 --- a/Applications/PaintBrush/ImageEditor.cpp +++ b/Applications/PaintBrush/ImageEditor.cpp @@ -27,6 +27,7 @@ #include "ImageEditor.h" #include "Image.h" #include "Layer.h" +#include "LayerModel.h" #include #include @@ -54,6 +55,18 @@ void ImageEditor::paint_event(GUI::PaintEvent& event) if (m_image) { m_image->paint_into(painter, m_image->rect(), m_image->rect()); } + + if (m_active_layer) { + painter.draw_rect(m_active_layer->rect().inflated(2, 2), Color::Black); + } +} + +void ImageEditor::set_active_layer(Layer* layer) +{ + if (m_active_layer == layer) + return; + m_active_layer = layer; + update(); } } diff --git a/Applications/PaintBrush/ImageEditor.h b/Applications/PaintBrush/ImageEditor.h index 0e3869ee8e..aa21c38901 100644 --- a/Applications/PaintBrush/ImageEditor.h +++ b/Applications/PaintBrush/ImageEditor.h @@ -31,6 +31,7 @@ namespace PaintBrush { class Image; +class Layer; class ImageEditor final : public GUI::Frame { C_OBJECT(ImageEditor); @@ -41,12 +42,16 @@ public: void set_image(RefPtr); + Layer* active_layer() { return m_active_layer; } + void set_active_layer(Layer*); + private: ImageEditor(); virtual void paint_event(GUI::PaintEvent&) override; RefPtr m_image; + RefPtr m_active_layer; }; } diff --git a/Applications/PaintBrush/Layer.h b/Applications/PaintBrush/Layer.h index 38188090d1..b0fe8a142d 100644 --- a/Applications/PaintBrush/Layer.h +++ b/Applications/PaintBrush/Layer.h @@ -49,6 +49,8 @@ public: Gfx::Bitmap& bitmap() { return *m_bitmap; } Gfx::Size size() const { return bitmap().size(); } + Gfx::Rect rect() const { return { location(), size() }; } + const String& name() const { return m_name; } void set_name(const String& name) { m_name = name; } diff --git a/Applications/PaintBrush/LayerModel.cpp b/Applications/PaintBrush/LayerModel.cpp new file mode 100644 index 0000000000..9f533d091f --- /dev/null +++ b/Applications/PaintBrush/LayerModel.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020, Andreas Kling + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "LayerModel.h" +#include "Image.h" +#include "Layer.h" + +namespace PaintBrush { + +NonnullRefPtr LayerModel::create(Image& image) +{ + return adopt(*new LayerModel(image)); +} + +LayerModel::LayerModel(Image& image) + : m_image(image) +{ +} + +int LayerModel::row_count(const GUI::ModelIndex&) const +{ + return m_image.layer_count(); +} + +String LayerModel::column_name(int column) const +{ + switch (column) { + case Column::Name: + return "Name"; + case Column::Size: + return "Size"; + case Column::Location: + return "Location"; + } + ASSERT_NOT_REACHED(); +} + +GUI::Variant LayerModel::data(const GUI::ModelIndex& index, Role role) const +{ + auto& layer = m_image.layer(index.row()); + if (role == Role::Display) { + switch (index.column()) { + case Column::Name: + return layer.name(); + case Column::Size: + return layer.size(); + case Column::Location: + return layer.location(); + } + } + return {}; +} + +} diff --git a/Applications/PaintBrush/LayerModel.h b/Applications/PaintBrush/LayerModel.h new file mode 100644 index 0000000000..a6d9884c1e --- /dev/null +++ b/Applications/PaintBrush/LayerModel.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020, Andreas Kling + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include + +namespace PaintBrush { + +class Image; + +class LayerModel final : public GUI::Model { +public: + enum Column { + Name, + Size, + Location, + __Count + }; + + static NonnullRefPtr create(Image&); + + virtual int row_count(const GUI::ModelIndex&) const override; + virtual int column_count(const GUI::ModelIndex&) const override { return Column::__Count; } + virtual String column_name(int) const override; + virtual GUI::Variant data(const GUI::ModelIndex&, Role = Role::Display) const override; + virtual void update() override { did_update(); } + +private: + explicit LayerModel(Image&); + + Image& m_image; +}; + +} diff --git a/Applications/PaintBrush/Makefile b/Applications/PaintBrush/Makefile index 37d2ece633..8a88850c0a 100644 --- a/Applications/PaintBrush/Makefile +++ b/Applications/PaintBrush/Makefile @@ -5,6 +5,7 @@ OBJS = \ Image.o \ ImageEditor.o \ Layer.o \ + LayerModel.o \ LineTool.o \ PaintableWidget.o \ PaletteWidget.o \ diff --git a/Applications/PaintBrush/main.cpp b/Applications/PaintBrush/main.cpp index 94ce7af217..27b01e098c 100644 --- a/Applications/PaintBrush/main.cpp +++ b/Applications/PaintBrush/main.cpp @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include #include #include @@ -79,6 +81,14 @@ int main(int argc, char** argv) paintable_widget.set_preferred_size(0, 0); vertical_container.add(paintable_widget); + auto& right_panel = horizontal_container.add(); + right_panel.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fill); + right_panel.set_preferred_size(230, 0); + right_panel.set_layout(); + + auto& layer_table_view = right_panel.add(); + layer_table_view.set_size_columns_to_fit_content(true); + window->show(); auto menubar = GUI::MenuBar::construct(); @@ -128,6 +138,15 @@ int main(int argc, char** argv) fg_layer_2->set_location({ 300, 350 }); fg_layer_2->bitmap().fill(Color::Yellow); + layer_table_view.set_model(image->layer_model()); + layer_table_view.on_selection_change = [&] { + auto index = layer_table_view.selection().first(); + if (index.is_valid()) + image_editor.set_active_layer(const_cast(&image->layer(index.row()))); + else + image_editor.set_active_layer(nullptr); + }; + image_editor.set_image(image); return app.exec();