diff options
author | Andreas Kling <kling@serenityos.org> | 2020-05-26 09:51:28 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-05-26 10:18:03 +0200 |
commit | 18d68c8c944e97431b3d0c3ca95dd6c654db2939 (patch) | |
tree | 5c8eab3f140c9be5d2a1dd5c31c3a95f8c7cd221 | |
parent | e4b11a23b709b9c811087b65fe2a33b88a32c7f3 (diff) | |
download | serenity-18d68c8c944e97431b3d0c3ca95dd6c654db2939.zip |
PixelPaint: Add selection functionality to the LayerListWidget
Now we can get rid of the old table view and with it the LayerModel.
-rw-r--r-- | Applications/PixelPaint/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Applications/PixelPaint/Image.cpp | 8 | ||||
-rw-r--r-- | Applications/PixelPaint/Image.h | 8 | ||||
-rw-r--r-- | Applications/PixelPaint/ImageEditor.cpp | 4 | ||||
-rw-r--r-- | Applications/PixelPaint/ImageEditor.h | 2 | ||||
-rw-r--r-- | Applications/PixelPaint/LayerListWidget.cpp | 61 | ||||
-rw-r--r-- | Applications/PixelPaint/LayerListWidget.h | 8 | ||||
-rw-r--r-- | Applications/PixelPaint/LayerModel.cpp | 77 | ||||
-rw-r--r-- | Applications/PixelPaint/LayerModel.h | 60 | ||||
-rw-r--r-- | Applications/PixelPaint/main.cpp | 33 |
10 files changed, 77 insertions, 185 deletions
diff --git a/Applications/PixelPaint/CMakeLists.txt b/Applications/PixelPaint/CMakeLists.txt index 1df90c7782..b5bd9c4283 100644 --- a/Applications/PixelPaint/CMakeLists.txt +++ b/Applications/PixelPaint/CMakeLists.txt @@ -7,7 +7,6 @@ set(SOURCES ImageEditor.cpp Layer.cpp LayerListWidget.cpp - LayerModel.cpp LineTool.cpp main.cpp MoveTool.cpp diff --git a/Applications/PixelPaint/Image.cpp b/Applications/PixelPaint/Image.cpp index f9ee42dac9..f0af8db10f 100644 --- a/Applications/PixelPaint/Image.cpp +++ b/Applications/PixelPaint/Image.cpp @@ -26,7 +26,6 @@ #include "Image.h" #include "Layer.h" -#include "LayerModel.h" #include <LibGUI/Painter.h> //#define PAINT_DEBUG @@ -72,13 +71,6 @@ void Image::add_layer(NonnullRefPtr<Layer> layer) client->image_did_add_layer(m_layers.size() - 1); } -GUI::Model& Image::layer_model() -{ - if (!m_layer_model) - m_layer_model = LayerModel::create(*this); - return *m_layer_model; -} - size_t Image::index_of(const Layer& layer) const { for (size_t i = 0; i < m_layers.size(); ++i) { diff --git a/Applications/PixelPaint/Image.h b/Applications/PixelPaint/Image.h index 28d3ae9cb4..c2faed2c98 100644 --- a/Applications/PixelPaint/Image.h +++ b/Applications/PixelPaint/Image.h @@ -55,6 +55,7 @@ public: size_t layer_count() const { return m_layers.size(); } const Layer& layer(size_t index) const { return m_layers.at(index); } + Layer& layer(size_t index) { return m_layers.at(index); } const Gfx::Size& size() const { return m_size; } Gfx::Rect rect() const { return { {}, m_size }; } @@ -63,8 +64,6 @@ public: void paint_into(GUI::Painter&, const Gfx::Rect& dest_rect); - GUI::Model& layer_model(); - void move_layer_to_front(Layer&); void move_layer_to_back(Layer&); void move_layer_up(Layer&); @@ -77,17 +76,16 @@ public: void layer_did_modify_bitmap(Badge<Layer>, const Layer&); + size_t index_of(const Layer&) const; + private: explicit Image(const Gfx::Size&); void did_change(); void did_modify_layer_stack(); - size_t index_of(const Layer&) const; - Gfx::Size m_size; NonnullRefPtrVector<Layer> m_layers; - RefPtr<GUI::Model> m_layer_model; HashTable<ImageClient*> m_clients; }; diff --git a/Applications/PixelPaint/ImageEditor.cpp b/Applications/PixelPaint/ImageEditor.cpp index 5959eb80fe..ca8d39d774 100644 --- a/Applications/PixelPaint/ImageEditor.cpp +++ b/Applications/PixelPaint/ImageEditor.cpp @@ -27,7 +27,6 @@ #include "ImageEditor.h" #include "Image.h" #include "Layer.h" -#include "LayerModel.h" #include "Tool.h" #include <LibGUI/Painter.h> #include <LibGfx/FloatRect.h> @@ -268,7 +267,7 @@ void ImageEditor::set_active_layer(Layer* layer) break; } if (on_active_layer_change) - on_active_layer_change(m_image->layer_model().index(index)); + on_active_layer_change(layer); } else { if (on_active_layer_change) on_active_layer_change({}); @@ -293,7 +292,6 @@ void ImageEditor::set_active_tool(Tool* tool) void ImageEditor::layers_did_change() { - static_cast<LayerModel&>(m_image->layer_model()).update_without_invalidating_indexes(); update(); } diff --git a/Applications/PixelPaint/ImageEditor.h b/Applications/PixelPaint/ImageEditor.h index 0156bd4b12..ad78c975a2 100644 --- a/Applications/PixelPaint/ImageEditor.h +++ b/Applications/PixelPaint/ImageEditor.h @@ -70,7 +70,7 @@ public: Function<void(Color)> on_primary_color_change; Function<void(Color)> on_secondary_color_change; - Function<void(const GUI::ModelIndex&)> on_active_layer_change; + Function<void(Layer*)> on_active_layer_change; Gfx::FloatRect layer_rect_to_editor_rect(const Layer&, const Gfx::Rect&) const; Gfx::FloatRect image_rect_to_editor_rect(const Gfx::Rect&) const; diff --git a/Applications/PixelPaint/LayerListWidget.cpp b/Applications/PixelPaint/LayerListWidget.cpp index 716f089d11..27460cd82e 100644 --- a/Applications/PixelPaint/LayerListWidget.cpp +++ b/Applications/PixelPaint/LayerListWidget.cpp @@ -26,8 +26,8 @@ #include "LayerListWidget.h" #include "Image.h" +#include "ImageEditor.h" #include "Layer.h" -#include <LibGUI/Model.h> #include <LibGUI/Painter.h> #include <LibGfx/Palette.h> @@ -61,7 +61,7 @@ void LayerListWidget::rebuild_gadgets() m_gadgets.clear(); if (m_image) { for (size_t layer_index = 0; layer_index < m_image->layer_count(); ++layer_index) { - m_gadgets.append({ layer_index, {}, {}, false, {} }); + m_gadgets.append({ layer_index, {}, {}, false, false, {} }); } } relayout_gadgets(); @@ -92,7 +92,12 @@ void LayerListWidget::paint_event(GUI::PaintEvent& event) if (gadget.is_moving) { adjusted_rect.move_by(0, gadget.movement_delta.y()); + } + + if (gadget.is_moving) { painter.fill_rect(adjusted_rect, palette().threed_shadow1()); + } else if (gadget.is_selected) { + painter.fill_rect(adjusted_rect, palette().selection()); } painter.draw_rect(adjusted_rect, Color::Black); @@ -104,7 +109,7 @@ void LayerListWidget::paint_event(GUI::PaintEvent& event) Gfx::Rect text_rect { thumbnail_rect.right() + 10, adjusted_rect.y(), adjusted_rect.width(), adjusted_rect.height() }; text_rect.intersect(adjusted_rect); - painter.draw_text(text_rect, layer.name(), Gfx::TextAlignment::CenterLeft); + painter.draw_text(text_rect, layer.name(), Gfx::TextAlignment::CenterLeft, gadget.is_selected ? palette().selection_text() : palette().button_text()); }; for (auto& gadget : m_gadgets) { @@ -132,11 +137,16 @@ void LayerListWidget::mousedown_event(GUI::MouseEvent& event) if (event.button() != GUI::MouseButton::Left) return; auto gadget_index = gadget_at(event.position()); - if (!gadget_index.has_value()) + if (!gadget_index.has_value()) { + if (on_layer_select) + on_layer_select(nullptr); return; + } m_moving_gadget_index = gadget_index; m_moving_event_origin = event.position(); auto& gadget = m_gadgets[m_moving_gadget_index.value()]; + if (on_layer_select) + on_layer_select(&m_image->layer(gadget_index.value())); gadget.is_moving = true; gadget.movement_delta = {}; update(); @@ -180,7 +190,7 @@ void LayerListWidget::image_did_add_layer(size_t layer_index) m_gadgets[m_moving_gadget_index.value()].is_moving = false; m_moving_gadget_index = {}; } - Gadget gadget { layer_index, {}, {}, false, {} }; + Gadget gadget { layer_index, {}, {}, false, false, {} }; m_gadgets.insert(layer_index, move(gadget)); relayout_gadgets(); } @@ -217,6 +227,28 @@ size_t LayerListWidget::hole_index_during_move() const return center_y_of_moving_gadget / vertical_step; } +void LayerListWidget::select_bottom_layer() +{ + if (!m_image || !m_image->layer_count()) + return; + set_selected_layer(&m_image->layer(0)); +} + +void LayerListWidget::select_top_layer() +{ + if (!m_image || !m_image->layer_count()) + return; + set_selected_layer(&m_image->layer(m_image->layer_count() - 1)); +} + +void LayerListWidget::move_selection(int delta) +{ + if (!m_image || !m_image->layer_count()) + return; + int new_layer_index = min(max(0, (int)m_image->layer_count() + delta), (int)m_image->layer_count() - 1); + set_selected_layer(&m_image->layer(new_layer_index)); +} + void LayerListWidget::relayout_gadgets() { int y = 0; @@ -239,4 +271,23 @@ void LayerListWidget::relayout_gadgets() update(); } +void LayerListWidget::set_selected_layer(Layer* layer) +{ + if (!m_image) + return; + if (!layer) { + for (auto& gadget : m_gadgets) + gadget.is_selected = false; + } else { + auto layer_index = m_image->index_of(*layer); + for (auto& gadget : m_gadgets) { + if (gadget.layer_index == layer_index) + gadget.is_selected = true; + else + gadget.is_selected = false; + } + } + update(); +} + } diff --git a/Applications/PixelPaint/LayerListWidget.h b/Applications/PixelPaint/LayerListWidget.h index 22cff6d635..4698f56339 100644 --- a/Applications/PixelPaint/LayerListWidget.h +++ b/Applications/PixelPaint/LayerListWidget.h @@ -41,6 +41,13 @@ public: void set_image(Image*); + void set_selected_layer(Layer*); + Function<void(Layer*)> on_layer_select; + + void select_bottom_layer(); + void select_top_layer(); + void move_selection(int delta); + private: explicit LayerListWidget(); @@ -65,6 +72,7 @@ private: Gfx::Rect rect; Gfx::Rect temporary_rect_during_move; bool is_moving { false }; + bool is_selected { false }; Gfx::Point movement_delta; }; diff --git a/Applications/PixelPaint/LayerModel.cpp b/Applications/PixelPaint/LayerModel.cpp deleted file mode 100644 index 37420e78de..0000000000 --- a/Applications/PixelPaint/LayerModel.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> - * 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 PixelPaint { - -NonnullRefPtr<LayerModel> 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/PixelPaint/LayerModel.h b/Applications/PixelPaint/LayerModel.h deleted file mode 100644 index 76ac1cac0a..0000000000 --- a/Applications/PixelPaint/LayerModel.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> - * 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 <LibGUI/Model.h> - -namespace PixelPaint { - -class Image; - -class LayerModel final : public GUI::Model { -public: - enum Column { - Name, - Size, - Location, - __Count - }; - - static NonnullRefPtr<LayerModel> 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(); } - - void update_without_invalidating_indexes() { did_update(0); } - -private: - explicit LayerModel(Image&); - - Image& m_image; -}; - -} diff --git a/Applications/PixelPaint/main.cpp b/Applications/PixelPaint/main.cpp index 6a5dc1249a..bdc59b0cdc 100644 --- a/Applications/PixelPaint/main.cpp +++ b/Applications/PixelPaint/main.cpp @@ -40,7 +40,6 @@ #include <LibGUI/Menu.h> #include <LibGUI/MenuBar.h> #include <LibGUI/MessageBox.h> -#include <LibGUI/Model.h> #include <LibGUI/TableView.h> #include <LibGUI/Window.h> #include <LibGfx/Bitmap.h> @@ -90,8 +89,6 @@ int main(int argc, char** argv) right_panel.set_preferred_size(230, 0); right_panel.set_layout<GUI::VerticalBoxLayout>(); - auto& layer_table_view = right_panel.add<GUI::TableView>(); - auto& layer_list_widget = right_panel.add<PixelPaint::LayerListWidget>(); window->show(); @@ -145,22 +142,22 @@ int main(int argc, char** argv) layer_menu.add_separator(); layer_menu.add_action(GUI::Action::create( "Select previous layer", { 0, Key_PageUp }, [&](auto&) { - layer_table_view.move_selection(1); + layer_list_widget.move_selection(1); }, window)); layer_menu.add_action(GUI::Action::create( "Select next layer", { 0, Key_PageDown }, [&](auto&) { - layer_table_view.move_selection(-1); + layer_list_widget.move_selection(-1); }, window)); layer_menu.add_action(GUI::Action::create( "Select top layer", { 0, Key_Home }, [&](auto&) { - layer_table_view.selection().set(layer_table_view.model()->index(image_editor.image()->layer_count() - 1)); + layer_list_widget.select_top_layer(); }, window)); layer_menu.add_action(GUI::Action::create( "Select bottom layer", { 0, Key_End }, [&](auto&) { - layer_table_view.selection().set(layer_table_view.model()->index(0)); + layer_list_widget.select_bottom_layer(); }, window)); layer_menu.add_separator(); @@ -170,8 +167,6 @@ int main(int argc, char** argv) if (!active_layer) return; image_editor.image()->move_layer_up(*active_layer); - layer_table_view.move_selection(1); - image_editor.layers_did_change(); }, window)); layer_menu.add_action(GUI::Action::create( @@ -180,8 +175,6 @@ int main(int argc, char** argv) if (!active_layer) return; image_editor.image()->move_layer_down(*active_layer); - layer_table_view.move_selection(-1); - image_editor.layers_did_change(); }, window)); layer_menu.add_separator(); @@ -191,8 +184,6 @@ int main(int argc, char** argv) if (!active_layer) return; image_editor.image()->remove_layer(*active_layer); - image_editor.set_active_layer(nullptr); - image_editor.layers_did_change(); }, window)); @@ -203,11 +194,8 @@ int main(int argc, char** argv) app.set_menubar(move(menubar)); - image_editor.on_active_layer_change = [&](auto& index) { - if (index.is_valid()) - layer_table_view.selection().set(index); - else - layer_table_view.selection().clear(); + image_editor.on_active_layer_change = [&](auto* layer) { + layer_list_widget.set_selected_layer(layer); }; auto image = PixelPaint::Image::create_with_size({ 640, 480 }); @@ -226,13 +214,8 @@ int main(int argc, char** argv) image->add_layer(*fg_layer2); fg_layer2->bitmap().fill(Color::Blue); - 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<PixelPaint::Layer*>(&image->layer(index.row()))); - else - image_editor.set_active_layer(nullptr); + layer_list_widget.on_layer_select = [&](auto* layer) { + image_editor.set_active_layer(layer); }; layer_list_widget.set_image(image); |