mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 18:22:45 +00:00 
			
		
		
		
	PixelPaint: Tool properties panel
Each tool can have its own set of properties that can be modified through a panel on the right side. The tools I've added properties for are: Pen: Thickness Brush: Size Hardness Spray: Thickness Density Bucket: Threshold
This commit is contained in:
		
							parent
							
								
									544f2f3c96
								
							
						
					
					
						commit
						afd52e2576
					
				
					 13 changed files with 324 additions and 12 deletions
				
			
		|  | @ -28,9 +28,13 @@ | |||
| #include "ImageEditor.h" | ||||
| #include "Layer.h" | ||||
| #include <LibGUI/Action.h> | ||||
| #include <LibGUI/BoxLayout.h> | ||||
| #include <LibGUI/Label.h> | ||||
| #include <LibGUI/Painter.h> | ||||
| #include <LibGUI/Slider.h> | ||||
| #include <LibGfx/Color.h> | ||||
| #include <LibGfx/Rect.h> | ||||
| #include <utility> | ||||
| 
 | ||||
| namespace PixelPaint { | ||||
| 
 | ||||
|  | @ -70,7 +74,7 @@ void BrushTool::draw_point(Gfx::Bitmap& bitmap, const Gfx::Color& color, const G | |||
|             if (distance >= m_size) | ||||
|                 continue; | ||||
| 
 | ||||
|             auto falloff = (1.0 - (distance / (float)m_size)) * 0.2; | ||||
|             auto falloff = (1.0 - (distance / (float)m_size)) * (1.0f / (100 - m_hardness)); | ||||
|             auto pixel_color = color; | ||||
|             pixel_color.set_alpha(falloff * 255); | ||||
|             bitmap.set_pixel(x, y, bitmap.get_pixel(x, y).blend(pixel_color)); | ||||
|  | @ -111,4 +115,52 @@ void BrushTool::draw_line(Gfx::Bitmap& bitmap, const Gfx::Color& color, const Gf | |||
|     } | ||||
| } | ||||
| 
 | ||||
| GUI::Widget* BrushTool::get_properties_widget() | ||||
| { | ||||
|     if (!m_properties_widget) { | ||||
|         m_properties_widget = GUI::Widget::construct(); | ||||
|         m_properties_widget->set_layout<GUI::VerticalBoxLayout>(); | ||||
| 
 | ||||
|         auto& size_container = m_properties_widget->add<GUI::Widget>(); | ||||
|         size_container.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); | ||||
|         size_container.set_preferred_size(0, 20); | ||||
|         size_container.set_layout<GUI::HorizontalBoxLayout>(); | ||||
| 
 | ||||
|         auto& size_label = size_container.add<GUI::Label>("Size:"); | ||||
|         size_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); | ||||
|         size_label.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fixed); | ||||
|         size_label.set_preferred_size(80, 20); | ||||
| 
 | ||||
|         auto& size_slider = size_container.add<GUI::HorizontalSlider>(); | ||||
|         size_slider.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); | ||||
|         size_slider.set_preferred_size(0, 20); | ||||
|         size_slider.set_range(1, 100); | ||||
|         size_slider.set_value(m_size); | ||||
|         size_slider.on_value_changed = [this](int value) { | ||||
|             m_size = value; | ||||
|         }; | ||||
| 
 | ||||
|         auto& hardness_container = m_properties_widget->add<GUI::Widget>(); | ||||
|         hardness_container.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); | ||||
|         hardness_container.set_preferred_size(0, 20); | ||||
|         hardness_container.set_layout<GUI::HorizontalBoxLayout>(); | ||||
| 
 | ||||
|         auto& hardness_label = hardness_container.add<GUI::Label>("Hardness:"); | ||||
|         hardness_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); | ||||
|         hardness_label.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fixed); | ||||
|         hardness_label.set_preferred_size(80, 20); | ||||
| 
 | ||||
|         auto& hardness_slider = hardness_container.add<GUI::HorizontalSlider>(); | ||||
|         hardness_slider.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); | ||||
|         hardness_slider.set_preferred_size(0, 20); | ||||
|         hardness_slider.set_range(1, 99); | ||||
|         hardness_slider.set_value(m_hardness); | ||||
|         hardness_slider.on_value_changed = [this](int value) { | ||||
|             m_hardness = value; | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     return m_properties_widget.ptr(); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -37,9 +37,12 @@ public: | |||
| 
 | ||||
|     virtual void on_mousedown(Layer&, GUI::MouseEvent& layer_event, GUI::MouseEvent& image_event) override; | ||||
|     virtual void on_mousemove(Layer&, GUI::MouseEvent& layer_event, GUI::MouseEvent& image_event) override; | ||||
|     virtual GUI::Widget* get_properties_widget() override; | ||||
| 
 | ||||
| private: | ||||
|     int m_size { 10 }; | ||||
|     RefPtr<GUI::Widget> m_properties_widget; | ||||
|     int m_size { 20 }; | ||||
|     int m_hardness { 80 }; | ||||
|     Gfx::IntPoint m_last_position; | ||||
| 
 | ||||
|     virtual const char* class_name() const override { return "BrushTool"; } | ||||
|  |  | |||
|  | @ -28,7 +28,10 @@ | |||
| #include "ImageEditor.h" | ||||
| #include "Layer.h" | ||||
| #include <AK/Queue.h> | ||||
| #include <LibGUI/BoxLayout.h> | ||||
| #include <LibGUI/Label.h> | ||||
| #include <LibGUI/Painter.h> | ||||
| #include <LibGUI/Slider.h> | ||||
| #include <LibGfx/Bitmap.h> | ||||
| #include <LibGfx/Rect.h> | ||||
| 
 | ||||
|  | @ -42,7 +45,15 @@ BucketTool::~BucketTool() | |||
| { | ||||
| } | ||||
| 
 | ||||
| static void flood_fill(Gfx::Bitmap& bitmap, const Gfx::IntPoint& start_position, Color target_color, Color fill_color) | ||||
| static float color_distance_squared(const Gfx::Color& lhs, const Gfx::Color& rhs) | ||||
| { | ||||
|     int a = rhs.red() - lhs.red(); | ||||
|     int b = rhs.green() - lhs.green(); | ||||
|     int c = rhs.blue() - lhs.blue(); | ||||
|     return (a * a + b * b + c * c) / (255.0f * 255.0f); | ||||
| } | ||||
| 
 | ||||
| static void flood_fill(Gfx::Bitmap& bitmap, const Gfx::IntPoint& start_position, Color target_color, Color fill_color, int threshold) | ||||
| { | ||||
|     ASSERT(bitmap.bpp() == 32); | ||||
| 
 | ||||
|  | @ -52,12 +63,15 @@ static void flood_fill(Gfx::Bitmap& bitmap, const Gfx::IntPoint& start_position, | |||
|     if (!bitmap.rect().contains(start_position)) | ||||
|         return; | ||||
| 
 | ||||
|     float threshold_normalized_squared = (threshold / 100.0f) * (threshold / 100.0f); | ||||
| 
 | ||||
|     Queue<Gfx::IntPoint> queue; | ||||
|     queue.enqueue(start_position); | ||||
|     while (!queue.is_empty()) { | ||||
|         auto position = queue.dequeue(); | ||||
| 
 | ||||
|         if (bitmap.get_pixel<Gfx::StorageFormat::RGBA32>(position.x(), position.y()) != target_color) | ||||
|         auto pixel_color = bitmap.get_pixel<Gfx::StorageFormat::RGBA32>(position.x(), position.y()); | ||||
|         if (color_distance_squared(pixel_color, target_color) > threshold_normalized_squared) | ||||
|             continue; | ||||
| 
 | ||||
|         bitmap.set_pixel<Gfx::StorageFormat::RGBA32>(position.x(), position.y(), fill_color); | ||||
|  | @ -84,9 +98,38 @@ void BucketTool::on_mousedown(Layer& layer, GUI::MouseEvent& event, GUI::MouseEv | |||
|     GUI::Painter painter(layer.bitmap()); | ||||
|     auto target_color = layer.bitmap().get_pixel(event.x(), event.y()); | ||||
| 
 | ||||
|     flood_fill(layer.bitmap(), event.position(), target_color, m_editor->color_for(event)); | ||||
|     flood_fill(layer.bitmap(), event.position(), target_color, m_editor->color_for(event), m_threshold); | ||||
| 
 | ||||
|     layer.did_modify_bitmap(*m_editor->image()); | ||||
| } | ||||
| 
 | ||||
| GUI::Widget* BucketTool::get_properties_widget() | ||||
| { | ||||
|     if (!m_properties_widget) { | ||||
|         m_properties_widget = GUI::Widget::construct(); | ||||
|         m_properties_widget->set_layout<GUI::VerticalBoxLayout>(); | ||||
| 
 | ||||
|         auto& threshold_container = m_properties_widget->add<GUI::Widget>(); | ||||
|         threshold_container.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); | ||||
|         threshold_container.set_preferred_size(0, 20); | ||||
|         threshold_container.set_layout<GUI::HorizontalBoxLayout>(); | ||||
| 
 | ||||
|         auto& threshold_label = threshold_container.add<GUI::Label>("Threshold:"); | ||||
|         threshold_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); | ||||
|         threshold_label.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fixed); | ||||
|         threshold_label.set_preferred_size(80, 20); | ||||
| 
 | ||||
|         auto& threshold_slider = threshold_container.add<GUI::HorizontalSlider>(); | ||||
|         threshold_slider.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); | ||||
|         threshold_slider.set_preferred_size(0, 20); | ||||
|         threshold_slider.set_range(0, 100); | ||||
|         threshold_slider.set_value(m_threshold); | ||||
|         threshold_slider.on_value_changed = [this](int value) { | ||||
|             m_threshold = value; | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     return m_properties_widget.ptr(); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -36,9 +36,13 @@ public: | |||
|     virtual ~BucketTool() override; | ||||
| 
 | ||||
|     virtual void on_mousedown(Layer&, GUI::MouseEvent& layer_event, GUI::MouseEvent& image_event) override; | ||||
|     virtual GUI::Widget* get_properties_widget() override; | ||||
| 
 | ||||
| private: | ||||
|     virtual const char* class_name() const override { return "BucketTool"; } | ||||
| 
 | ||||
|     RefPtr<GUI::Widget> m_properties_widget; | ||||
|     int m_threshold { 0 }; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ set(SOURCES | |||
|     RectangleTool.cpp | ||||
|     SprayTool.cpp | ||||
|     ToolboxWidget.cpp | ||||
|     ToolPropertiesWidget.cpp | ||||
|     Tool.cpp | ||||
| ) | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,8 +28,11 @@ | |||
| #include "ImageEditor.h" | ||||
| #include "Layer.h" | ||||
| #include <LibGUI/Action.h> | ||||
| #include <LibGUI/BoxLayout.h> | ||||
| #include <LibGUI/Label.h> | ||||
| #include <LibGUI/Menu.h> | ||||
| #include <LibGUI/Painter.h> | ||||
| #include <LibGUI/Slider.h> | ||||
| 
 | ||||
| namespace PixelPaint { | ||||
| 
 | ||||
|  | @ -94,4 +97,33 @@ void PenTool::on_tool_button_contextmenu(GUI::ContextMenuEvent& event) | |||
|     m_context_menu->popup(event.screen_position()); | ||||
| } | ||||
| 
 | ||||
| GUI::Widget* PenTool::get_properties_widget() | ||||
| { | ||||
|     if (!m_properties_widget) { | ||||
|         m_properties_widget = GUI::Widget::construct(); | ||||
|         m_properties_widget->set_layout<GUI::VerticalBoxLayout>(); | ||||
| 
 | ||||
|         auto& thickness_container = m_properties_widget->add<GUI::Widget>(); | ||||
|         thickness_container.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); | ||||
|         thickness_container.set_preferred_size(0, 20); | ||||
|         thickness_container.set_layout<GUI::HorizontalBoxLayout>(); | ||||
| 
 | ||||
|         auto& thickness_label = thickness_container.add<GUI::Label>("Thickness:"); | ||||
|         thickness_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); | ||||
|         thickness_label.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fixed); | ||||
|         thickness_label.set_preferred_size(80, 20); | ||||
| 
 | ||||
|         auto& thickness_slider = thickness_container.add<GUI::HorizontalSlider>(); | ||||
|         thickness_slider.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); | ||||
|         thickness_slider.set_preferred_size(0, 20); | ||||
|         thickness_slider.set_range(1, 20); | ||||
|         thickness_slider.set_value(m_thickness); | ||||
|         thickness_slider.on_value_changed = [this](int value) { | ||||
|             m_thickness = value; | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     return m_properties_widget.ptr(); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -41,12 +41,14 @@ public: | |||
|     virtual void on_mousemove(Layer&, GUI::MouseEvent& layer_event, GUI::MouseEvent& image_event) override; | ||||
|     virtual void on_mouseup(Layer&, GUI::MouseEvent& layer_event, GUI::MouseEvent& image_event) override; | ||||
|     virtual void on_tool_button_contextmenu(GUI::ContextMenuEvent&) override; | ||||
|     virtual GUI::Widget* get_properties_widget() override; | ||||
| 
 | ||||
| private: | ||||
|     virtual const char* class_name() const override { return "PenTool"; } | ||||
| 
 | ||||
|     Gfx::IntPoint m_last_drawing_event_position { -1, -1 }; | ||||
|     RefPtr<GUI::Menu> m_context_menu; | ||||
|     RefPtr<GUI::Widget> m_properties_widget; | ||||
|     int m_thickness { 1 }; | ||||
|     GUI::ActionGroup m_thickness_actions; | ||||
| }; | ||||
|  |  | |||
|  | @ -29,8 +29,11 @@ | |||
| #include "Layer.h" | ||||
| #include <AK/Queue.h> | ||||
| #include <LibGUI/Action.h> | ||||
| #include <LibGUI/BoxLayout.h> | ||||
| #include <LibGUI/Label.h> | ||||
| #include <LibGUI/Menu.h> | ||||
| #include <LibGUI/Painter.h> | ||||
| #include <LibGUI/Slider.h> | ||||
| #include <LibGfx/Bitmap.h> | ||||
| #include <math.h> | ||||
| #include <stdio.h> | ||||
|  | @ -65,9 +68,9 @@ void SprayTool::paint_it() | |||
|     GUI::Painter painter(bitmap); | ||||
|     ASSERT(bitmap.bpp() == 32); | ||||
|     m_editor->update(); | ||||
|     const double minimal_radius = 10; | ||||
|     const double minimal_radius = 2; | ||||
|     const double base_radius = minimal_radius * m_thickness; | ||||
|     for (int i = 0; i < 100 + (nrand() * 800); i++) { | ||||
|     for (int i = 0; i < M_PI * base_radius * base_radius * (m_density / 100.0f); i++) { | ||||
|         double radius = base_radius * nrand(); | ||||
|         double angle = 2 * M_PI * nrand(); | ||||
|         const int xpos = m_last_pos.x() + radius * cos(angle); | ||||
|  | @ -125,4 +128,52 @@ void SprayTool::on_tool_button_contextmenu(GUI::ContextMenuEvent& event) | |||
|     m_context_menu->popup(event.screen_position()); | ||||
| } | ||||
| 
 | ||||
| GUI::Widget* SprayTool::get_properties_widget() | ||||
| { | ||||
|     if (!m_properties_widget) { | ||||
|         m_properties_widget = GUI::Widget::construct(); | ||||
|         m_properties_widget->set_layout<GUI::VerticalBoxLayout>(); | ||||
| 
 | ||||
|         auto& thickness_container = m_properties_widget->add<GUI::Widget>(); | ||||
|         thickness_container.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); | ||||
|         thickness_container.set_preferred_size(0, 20); | ||||
|         thickness_container.set_layout<GUI::HorizontalBoxLayout>(); | ||||
| 
 | ||||
|         auto& thickness_label = thickness_container.add<GUI::Label>("Thickness:"); | ||||
|         thickness_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); | ||||
|         thickness_label.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fixed); | ||||
|         thickness_label.set_preferred_size(80, 20); | ||||
| 
 | ||||
|         auto& thickness_slider = thickness_container.add<GUI::HorizontalSlider>(); | ||||
|         thickness_slider.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); | ||||
|         thickness_slider.set_preferred_size(0, 20); | ||||
|         thickness_slider.set_range(1, 20); | ||||
|         thickness_slider.set_value(m_thickness); | ||||
|         thickness_slider.on_value_changed = [this](int value) { | ||||
|             m_thickness = value; | ||||
|         }; | ||||
| 
 | ||||
|         auto& density_container = m_properties_widget->add<GUI::Widget>(); | ||||
|         density_container.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); | ||||
|         density_container.set_preferred_size(0, 20); | ||||
|         density_container.set_layout<GUI::HorizontalBoxLayout>(); | ||||
| 
 | ||||
|         auto& density_label = density_container.add<GUI::Label>("Density:"); | ||||
|         density_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); | ||||
|         density_label.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fixed); | ||||
|         density_label.set_preferred_size(80, 20); | ||||
| 
 | ||||
|         auto& density_slider = density_container.add<GUI::HorizontalSlider>(); | ||||
|         density_slider.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); | ||||
|         density_slider.set_preferred_size(0, 30); | ||||
|         density_slider.set_range(1, 100); | ||||
|         density_slider.set_value(m_density); | ||||
|         density_slider.on_value_changed = [this](int value) { | ||||
|             m_density = value; | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     return m_properties_widget.ptr(); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -42,16 +42,20 @@ public: | |||
|     virtual void on_mouseup(Layer&, GUI::MouseEvent& layer_event, GUI::MouseEvent& image_event) override; | ||||
|     virtual void on_mousemove(Layer&, GUI::MouseEvent& layer_event, GUI::MouseEvent& image_event) override; | ||||
|     virtual void on_tool_button_contextmenu(GUI::ContextMenuEvent&) override; | ||||
|     virtual GUI::Widget* get_properties_widget() override; | ||||
| 
 | ||||
| private: | ||||
|     virtual const char* class_name() const override { return "SprayTool"; } | ||||
|     void paint_it(); | ||||
| 
 | ||||
|     RefPtr<GUI::Widget> m_properties_widget; | ||||
|     RefPtr<Core::Timer> m_timer; | ||||
|     Gfx::IntPoint m_last_pos; | ||||
|     Color m_color; | ||||
|     RefPtr<GUI::Menu> m_context_menu; | ||||
|     GUI::ActionGroup m_thickness_actions; | ||||
|     int m_thickness { 1 }; | ||||
|     int m_thickness { 10 }; | ||||
|     int m_density { 40 }; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -48,6 +48,7 @@ public: | |||
|     virtual void on_second_paint(const Layer&, GUI::PaintEvent&) { } | ||||
|     virtual void on_keydown(GUI::KeyEvent&) { } | ||||
|     virtual void on_keyup(GUI::KeyEvent&) { } | ||||
|     virtual GUI::Widget* get_properties_widget() { return nullptr; } | ||||
| 
 | ||||
|     virtual bool is_move_tool() const { return false; } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										61
									
								
								Applications/PixelPaint/ToolPropertiesWidget.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								Applications/PixelPaint/ToolPropertiesWidget.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2020, Ben Jilks <benjyjilks@gmail.com> | ||||
|  * 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 "ToolPropertiesWidget.h" | ||||
| #include "Tool.h" | ||||
| #include <LibGUI/BoxLayout.h> | ||||
| #include <LibGUI/GroupBox.h> | ||||
| 
 | ||||
| namespace PixelPaint { | ||||
| 
 | ||||
| ToolPropertiesWidget::ToolPropertiesWidget() | ||||
| { | ||||
|     set_layout<GUI::VerticalBoxLayout>(); | ||||
| 
 | ||||
|     m_group_box = add<GUI::GroupBox>("Tool properties"); | ||||
|     auto& layout = m_group_box->set_layout<GUI::VerticalBoxLayout>(); | ||||
|     layout.set_margins({ 10, 20, 10, 10 }); | ||||
| } | ||||
| 
 | ||||
| void ToolPropertiesWidget::set_active_tool(Tool* tool) | ||||
| { | ||||
|     if (tool == m_active_tool) | ||||
|         return; | ||||
| 
 | ||||
|     if (m_active_tool_widget != nullptr) | ||||
|         m_group_box->remove_child(*m_active_tool_widget); | ||||
| 
 | ||||
|     m_active_tool = tool; | ||||
|     m_active_tool_widget = tool->get_properties_widget(); | ||||
|     if (m_active_tool_widget != nullptr) | ||||
|         m_group_box->add_child(*m_active_tool_widget); | ||||
| } | ||||
| 
 | ||||
| ToolPropertiesWidget::~ToolPropertiesWidget() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										54
									
								
								Applications/PixelPaint/ToolPropertiesWidget.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								Applications/PixelPaint/ToolPropertiesWidget.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2020, Ben Jilks <benjyjilks@gmail.com> | ||||
|  * 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 <AK/RefPtr.h> | ||||
| #include <LibGUI/Forward.h> | ||||
| #include <LibGUI/Widget.h> | ||||
| 
 | ||||
| namespace PixelPaint { | ||||
| 
 | ||||
| class Tool; | ||||
| 
 | ||||
| class ToolPropertiesWidget final : public GUI::Widget { | ||||
|     C_OBJECT(ToolPropertiesWidget); | ||||
| 
 | ||||
| public: | ||||
|     virtual ~ToolPropertiesWidget() override; | ||||
| 
 | ||||
|     void set_active_tool(Tool*); | ||||
| 
 | ||||
| private: | ||||
|     ToolPropertiesWidget(); | ||||
| 
 | ||||
|     RefPtr<GUI::GroupBox> m_group_box; | ||||
| 
 | ||||
|     Tool* m_active_tool { nullptr }; | ||||
|     GUI::Widget* m_active_tool_widget { nullptr }; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  | @ -33,6 +33,7 @@ | |||
| #include "LayerPropertiesWidget.h" | ||||
| #include "PaletteWidget.h" | ||||
| #include "Tool.h" | ||||
| #include "ToolPropertiesWidget.h" | ||||
| #include "ToolboxWidget.h" | ||||
| #include <LibGUI/AboutDialog.h> | ||||
| #include <LibGUI/Action.h> | ||||
|  | @ -84,10 +85,6 @@ int main(int argc, char** argv) | |||
|     auto& image_editor = vertical_container.add<PixelPaint::ImageEditor>(); | ||||
|     image_editor.set_focus(true); | ||||
| 
 | ||||
|     toolbox.on_tool_selection = [&](auto* tool) { | ||||
|         image_editor.set_active_tool(tool); | ||||
|     }; | ||||
| 
 | ||||
|     vertical_container.add<PixelPaint::PaletteWidget>(image_editor); | ||||
| 
 | ||||
|     auto& right_panel = horizontal_container.add<GUI::Widget>(); | ||||
|  | @ -100,6 +97,13 @@ int main(int argc, char** argv) | |||
| 
 | ||||
|     auto& layer_properties_widget = right_panel.add<PixelPaint::LayerPropertiesWidget>(); | ||||
| 
 | ||||
|     auto& tool_properties_widget = right_panel.add<PixelPaint::ToolPropertiesWidget>(); | ||||
| 
 | ||||
|     toolbox.on_tool_selection = [&](auto* tool) { | ||||
|         image_editor.set_active_tool(tool); | ||||
|         tool_properties_widget.set_active_tool(tool); | ||||
|     }; | ||||
| 
 | ||||
|     window->show(); | ||||
| 
 | ||||
|     auto menubar = GUI::MenuBar::construct(); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 BenJilks
						BenJilks