mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 17:32:44 +00:00 
			
		
		
		
	PixelPaint: Let the move tool optionally select the active layer
Previously, the move tool would always select the topmost layer before performing a move operation. This commit adds an option for the move tool to always select the active layer, even if it is behind another.
This commit is contained in:
		
							parent
							
								
									16eca649f1
								
							
						
					
					
						commit
						77e15ff4da
					
				
					 3 changed files with 66 additions and 5 deletions
				
			
		|  | @ -372,10 +372,9 @@ void ImageEditor::mousedown_event(GUI::MouseEvent& event) | ||||||
|     if (!m_active_tool) |     if (!m_active_tool) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     if (is<MoveTool>(*m_active_tool)) { |     if (auto* tool = dynamic_cast<MoveTool*>(m_active_tool); tool && tool->layer_selection_mode() == MoveTool::LayerSelectionMode::ForegroundLayer) { | ||||||
|         if (auto* other_layer = layer_at_editor_position(event.position())) { |         if (auto* foreground_layer = layer_at_editor_position(event.position())) | ||||||
|             set_active_layer(other_layer); |             set_active_layer(foreground_layer); | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     auto layer_event = m_active_layer ? event_adjusted_for_layer(event, *m_active_layer) : event; |     auto layer_event = m_active_layer ? event_adjusted_for_layer(event, *m_active_layer) : event; | ||||||
|  |  | ||||||
|  | @ -11,6 +11,8 @@ | ||||||
| #include "../Layer.h" | #include "../Layer.h" | ||||||
| #include <AK/String.h> | #include <AK/String.h> | ||||||
| #include <LibGUI/Action.h> | #include <LibGUI/Action.h> | ||||||
|  | #include <LibGUI/BoxLayout.h> | ||||||
|  | #include <LibGUI/Label.h> | ||||||
| #include <LibGUI/Menu.h> | #include <LibGUI/Menu.h> | ||||||
| #include <LibGUI/MessageBox.h> | #include <LibGUI/MessageBox.h> | ||||||
| #include <LibGUI/Painter.h> | #include <LibGUI/Painter.h> | ||||||
|  | @ -138,6 +140,9 @@ bool MoveTool::on_keydown(GUI::KeyEvent& event) | ||||||
|     if (event.key() == Key_Shift) |     if (event.key() == Key_Shift) | ||||||
|         m_keep_aspect_ratio = true; |         m_keep_aspect_ratio = true; | ||||||
| 
 | 
 | ||||||
|  |     if (event.key() == Key_Alt) | ||||||
|  |         toggle_selection_mode(); | ||||||
|  | 
 | ||||||
|     if (m_scaling) |     if (m_scaling) | ||||||
|         return true; |         return true; | ||||||
| 
 | 
 | ||||||
|  | @ -176,6 +181,9 @@ void MoveTool::on_keyup(GUI::KeyEvent& event) | ||||||
| { | { | ||||||
|     if (event.key() == Key_Shift) |     if (event.key() == Key_Shift) | ||||||
|         m_keep_aspect_ratio = false; |         m_keep_aspect_ratio = false; | ||||||
|  | 
 | ||||||
|  |     if (event.key() == Key_Alt) | ||||||
|  |         toggle_selection_mode(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MoveTool::on_second_paint(Layer const* layer, GUI::PaintEvent& event) | void MoveTool::on_second_paint(Layer const* layer, GUI::PaintEvent& event) | ||||||
|  | @ -243,4 +251,44 @@ Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> MoveTool::cursor() | ||||||
|     return Gfx::StandardCursor::Move; |     return Gfx::StandardCursor::Move; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | GUI::Widget* MoveTool::get_properties_widget() | ||||||
|  | { | ||||||
|  |     if (!m_properties_widget) { | ||||||
|  |         m_properties_widget = GUI::Widget::construct(); | ||||||
|  |         m_properties_widget->set_layout<GUI::VerticalBoxLayout>(); | ||||||
|  | 
 | ||||||
|  |         auto& selection_mode_container = m_properties_widget->add<GUI::Widget>(); | ||||||
|  |         selection_mode_container.set_layout<GUI::HorizontalBoxLayout>(); | ||||||
|  |         selection_mode_container.set_fixed_height(46); | ||||||
|  |         auto& selection_mode_label = selection_mode_container.add<GUI::Label>("Selection Mode:"); | ||||||
|  |         selection_mode_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); | ||||||
|  |         selection_mode_label.set_fixed_size(80, 40); | ||||||
|  | 
 | ||||||
|  |         auto& mode_radio_container = selection_mode_container.add<GUI::Widget>(); | ||||||
|  |         mode_radio_container.set_layout<GUI::VerticalBoxLayout>(); | ||||||
|  |         m_selection_mode_foreground = mode_radio_container.add<GUI::RadioButton>("Foreground"); | ||||||
|  | 
 | ||||||
|  |         m_selection_mode_active = mode_radio_container.add<GUI::RadioButton>("Active Layer"); | ||||||
|  | 
 | ||||||
|  |         m_selection_mode_foreground->on_checked = [&](bool) { | ||||||
|  |             m_layer_selection_mode = LayerSelectionMode::ForegroundLayer; | ||||||
|  |         }; | ||||||
|  |         m_selection_mode_active->on_checked = [&](bool) { | ||||||
|  |             m_layer_selection_mode = LayerSelectionMode::ActiveLayer; | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         m_selection_mode_foreground->set_checked(true); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return m_properties_widget.ptr(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MoveTool::toggle_selection_mode() | ||||||
|  | { | ||||||
|  |     if (m_selection_mode_foreground->is_checked()) | ||||||
|  |         m_selection_mode_active->set_checked(true); | ||||||
|  |     else | ||||||
|  |         m_selection_mode_foreground->set_checked(true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> |  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> | ||||||
|  * Copyright (c) 2022, the SerenityOS developers. |  * Copyright (c) 2022-2023, the SerenityOS developers. | ||||||
|  * |  * | ||||||
|  * SPDX-License-Identifier: BSD-2-Clause |  * SPDX-License-Identifier: BSD-2-Clause | ||||||
|  */ |  */ | ||||||
|  | @ -9,6 +9,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "../Layer.h" | #include "../Layer.h" | ||||||
| #include "Tool.h" | #include "Tool.h" | ||||||
|  | #include <LibGUI/RadioButton.h> | ||||||
| 
 | 
 | ||||||
| namespace PixelPaint { | namespace PixelPaint { | ||||||
| 
 | 
 | ||||||
|  | @ -23,19 +24,29 @@ public: | ||||||
|     MoveTool() = default; |     MoveTool() = default; | ||||||
|     virtual ~MoveTool() override = default; |     virtual ~MoveTool() override = default; | ||||||
| 
 | 
 | ||||||
|  |     enum class LayerSelectionMode { | ||||||
|  |         ForegroundLayer, | ||||||
|  |         ActiveLayer, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|     virtual void on_mousedown(Layer*, MouseEvent&) override; |     virtual void on_mousedown(Layer*, MouseEvent&) override; | ||||||
|     virtual void on_mousemove(Layer*, MouseEvent&) override; |     virtual void on_mousemove(Layer*, MouseEvent&) override; | ||||||
|     virtual void on_mouseup(Layer*, MouseEvent&) override; |     virtual void on_mouseup(Layer*, MouseEvent&) override; | ||||||
|     virtual bool on_keydown(GUI::KeyEvent&) override; |     virtual bool on_keydown(GUI::KeyEvent&) override; | ||||||
|     virtual void on_keyup(GUI::KeyEvent&) override; |     virtual void on_keyup(GUI::KeyEvent&) override; | ||||||
|     virtual void on_second_paint(Layer const*, GUI::PaintEvent&) override; |     virtual void on_second_paint(Layer const*, GUI::PaintEvent&) override; | ||||||
|  |     virtual GUI::Widget* get_properties_widget() override; | ||||||
|     virtual Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> cursor() override; |     virtual Variant<Gfx::StandardCursor, NonnullRefPtr<Gfx::Bitmap>> cursor() override; | ||||||
|  |     virtual bool is_overriding_alt() override { return true; } | ||||||
|  |     LayerSelectionMode layer_selection_mode() const { return m_layer_selection_mode; } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     virtual StringView tool_name() const override { return "Move Tool"sv; } |     virtual StringView tool_name() const override { return "Move Tool"sv; } | ||||||
|     ErrorOr<void> update_cached_preview_bitmap(Layer const* layer); |     ErrorOr<void> update_cached_preview_bitmap(Layer const* layer); | ||||||
|     Optional<ResizeAnchorLocation const> resize_anchor_location_from_cursor_position(Layer const*, MouseEvent&); |     Optional<ResizeAnchorLocation const> resize_anchor_location_from_cursor_position(Layer const*, MouseEvent&); | ||||||
|  |     void toggle_selection_mode(); | ||||||
| 
 | 
 | ||||||
|  |     LayerSelectionMode m_layer_selection_mode { LayerSelectionMode::ForegroundLayer }; | ||||||
|     RefPtr<Layer> m_layer_being_moved; |     RefPtr<Layer> m_layer_being_moved; | ||||||
|     Gfx::IntPoint m_event_origin; |     Gfx::IntPoint m_event_origin; | ||||||
|     Gfx::IntPoint m_layer_origin; |     Gfx::IntPoint m_layer_origin; | ||||||
|  | @ -43,6 +54,9 @@ private: | ||||||
|     bool m_scaling { false }; |     bool m_scaling { false }; | ||||||
|     Optional<ResizeAnchorLocation const> m_resize_anchor_location {}; |     Optional<ResizeAnchorLocation const> m_resize_anchor_location {}; | ||||||
|     bool m_keep_aspect_ratio { false }; |     bool m_keep_aspect_ratio { false }; | ||||||
|  |     RefPtr<GUI::Widget> m_properties_widget; | ||||||
|  |     RefPtr<GUI::RadioButton> m_selection_mode_foreground; | ||||||
|  |     RefPtr<GUI::RadioButton> m_selection_mode_active; | ||||||
| 
 | 
 | ||||||
|     RefPtr<Gfx::Bitmap> m_cached_preview_bitmap { nullptr }; |     RefPtr<Gfx::Bitmap> m_cached_preview_bitmap { nullptr }; | ||||||
| }; | }; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tim Ledbetter
						Tim Ledbetter