| 
									
										
										
										
											2015-02-12 23:16:25 +08:00
										 |  |  | // Aseprite
 | 
					
						
							| 
									
										
										
										
											2025-02-27 02:55:12 +08:00
										 |  |  | // Copyright (C) 2018-2025  Igara Studio S.A.
 | 
					
						
							| 
									
										
										
										
											2018-01-30 01:09:51 +08:00
										 |  |  | // Copyright (C) 2001-2018  David Capello
 | 
					
						
							| 
									
										
										
										
											2015-02-12 23:16:25 +08:00
										 |  |  | //
 | 
					
						
							| 
									
										
										
										
											2016-08-27 04:02:58 +08:00
										 |  |  | // This program is distributed under the terms of
 | 
					
						
							|  |  |  | // the End-User License Agreement for Aseprite.
 | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #ifdef HAVE_CONFIG_H
 | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  |   #include "config.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-10 06:59:05 +08:00
										 |  |  | #include "app/ui/context_bar.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/app.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-16 04:12:11 +08:00
										 |  |  | #include "app/app_brushes.h"
 | 
					
						
							| 
									
										
										
										
											2015-11-27 22:36:27 +08:00
										 |  |  | #include "app/app_menus.h"
 | 
					
						
							| 
									
										
										
										
											2015-11-25 23:29:19 +08:00
										 |  |  | #include "app/color_utils.h"
 | 
					
						
							| 
									
										
										
										
											2015-04-27 11:08:04 +08:00
										 |  |  | #include "app/commands/commands.h"
 | 
					
						
							| 
									
										
										
										
											2017-12-01 03:23:31 +08:00
										 |  |  | #include "app/commands/quick_command.h"
 | 
					
						
							| 
									
										
										
										
											2018-07-07 22:54:44 +08:00
										 |  |  | #include "app/doc.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  | #include "app/doc_event.h"
 | 
					
						
							| 
									
										
										
										
											2023-11-30 22:02:52 +08:00
										 |  |  | #include "app/extensions.h"
 | 
					
						
							| 
									
										
										
										
											2019-11-12 02:40:01 +08:00
										 |  |  | #include "app/i18n/strings.h"
 | 
					
						
							| 
									
										
										
										
											2015-11-26 02:17:34 +08:00
										 |  |  | #include "app/ini_file.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  | #include "app/match_words.h"
 | 
					
						
							| 
									
										
										
										
											2015-04-27 11:08:04 +08:00
										 |  |  | #include "app/pref/preferences.h"
 | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  | #include "app/shade.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  | #include "app/site.h"
 | 
					
						
							| 
									
										
										
										
											2016-04-26 02:20:53 +08:00
										 |  |  | #include "app/tools/active_tool.h"
 | 
					
						
							| 
									
										
										
										
											2014-01-26 03:26:49 +08:00
										 |  |  | #include "app/tools/controller.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/tools/ink.h"
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  | #include "app/tools/ink_type.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/tools/point_shape.h"
 | 
					
						
							|  |  |  | #include "app/tools/tool.h"
 | 
					
						
							| 
									
										
										
										
											2014-01-26 03:26:49 +08:00
										 |  |  | #include "app/tools/tool_box.h"
 | 
					
						
							| 
									
										
										
										
											2016-04-05 05:46:48 +08:00
										 |  |  | #include "app/tools/tool_loop_modifiers.h"
 | 
					
						
							| 
									
										
										
										
											2024-01-11 02:27:17 +08:00
										 |  |  | #include "app/ui/alpha_entry.h"
 | 
					
						
							| 
									
										
										
										
											2015-04-28 23:38:15 +08:00
										 |  |  | #include "app/ui/brush_popup.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/ui/button_set.h"
 | 
					
						
							| 
									
										
										
										
											2013-11-30 04:59:28 +08:00
										 |  |  | #include "app/ui/color_button.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-28 23:57:00 +08:00
										 |  |  | #include "app/ui/color_shades.h"
 | 
					
						
							| 
									
										
										
										
											2017-05-24 07:41:30 +08:00
										 |  |  | #include "app/ui/dithering_selector.h"
 | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  | #include "app/ui/dynamics_popup.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  | #include "app/ui/editor/editor.h"
 | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  | #include "app/ui/expr_entry.h"
 | 
					
						
							| 
									
										
										
										
											2024-06-12 09:31:13 +08:00
										 |  |  | #include "app/ui/font_entry.h"
 | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  | #include "app/ui/icon_button.h"
 | 
					
						
							| 
									
										
										
										
											2017-06-23 20:02:59 +08:00
										 |  |  | #include "app/ui/keyboard_shortcuts.h"
 | 
					
						
							| 
									
										
										
										
											2024-07-20 03:47:13 +08:00
										 |  |  | #include "app/ui/layer_frame_comboboxes.h"
 | 
					
						
							| 
									
										
										
										
											2022-02-22 03:21:07 +08:00
										 |  |  | #include "app/ui/sampling_selector.h"
 | 
					
						
							| 
									
										
										
										
											2018-10-27 03:08:31 +08:00
										 |  |  | #include "app/ui/selection_mode_field.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/ui/skin/skin_theme.h"
 | 
					
						
							|  |  |  | #include "app/ui_context.h"
 | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  | #include "base/pi.h"
 | 
					
						
							| 
									
										
										
										
											2014-10-25 23:10:52 +08:00
										 |  |  | #include "base/scoped_value.h"
 | 
					
						
							| 
									
										
										
										
											2014-10-21 09:21:31 +08:00
										 |  |  | #include "doc/brush.h"
 | 
					
						
							|  |  |  | #include "doc/image.h"
 | 
					
						
							|  |  |  | #include "doc/palette.h"
 | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  | #include "doc/remap.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  | #include "doc/selected_objects.h"
 | 
					
						
							|  |  |  | #include "doc/slice.h"
 | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  | #include "fmt/format.h"
 | 
					
						
							| 
									
										
										
										
											2016-09-14 02:02:00 +08:00
										 |  |  | #include "obs/connection.h"
 | 
					
						
							| 
									
										
										
										
											2022-02-22 02:30:09 +08:00
										 |  |  | #include "os/sampling.h"
 | 
					
						
							| 
									
										
										
										
											2018-08-09 23:58:43 +08:00
										 |  |  | #include "os/surface.h"
 | 
					
						
							|  |  |  | #include "os/system.h"
 | 
					
						
							| 
									
										
										
										
											2018-10-27 03:08:31 +08:00
										 |  |  | #include "render/dithering.h"
 | 
					
						
							| 
									
										
										
										
											2019-04-04 06:32:24 +08:00
										 |  |  | #include "render/error_diffusion.h"
 | 
					
						
							|  |  |  | #include "render/ordered_dither.h"
 | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | #include "ui/button.h"
 | 
					
						
							|  |  |  | #include "ui/combobox.h"
 | 
					
						
							| 
									
										
										
										
											2021-03-20 05:57:56 +08:00
										 |  |  | #include "ui/fit_bounds.h"
 | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | #include "ui/int_entry.h"
 | 
					
						
							|  |  |  | #include "ui/label.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  | #include "ui/listbox.h"
 | 
					
						
							| 
									
										
										
										
											2013-12-30 04:11:56 +08:00
										 |  |  | #include "ui/listitem.h"
 | 
					
						
							| 
									
										
										
										
											2015-07-03 00:16:06 +08:00
										 |  |  | #include "ui/menu.h"
 | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  | #include "ui/message.h"
 | 
					
						
							|  |  |  | #include "ui/paint_event.h"
 | 
					
						
							| 
									
										
										
										
											2013-03-31 07:46:04 +08:00
										 |  |  | #include "ui/popup_window.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-04 08:50:05 +08:00
										 |  |  | #include "ui/size_hint_event.h"
 | 
					
						
							| 
									
										
										
										
											2015-11-25 23:29:19 +08:00
										 |  |  | #include "ui/system.h"
 | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | #include "ui/theme.h"
 | 
					
						
							| 
									
										
										
										
											2013-03-31 08:31:34 +08:00
										 |  |  | #include "ui/tooltips.h"
 | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  | #include <algorithm>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | namespace app { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace app::skin; | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | using namespace gfx; | 
					
						
							|  |  |  | using namespace ui; | 
					
						
							|  |  |  | using namespace tools; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  | static bool g_updatingFromCode = false; | 
					
						
							| 
									
										
										
										
											2014-10-25 23:10:52 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-15 20:50:00 +08:00
										 |  |  | class ContextBar::ZoomButtons : public ButtonSet { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |   ZoomButtons() : ButtonSet(3) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     addItem("100%"); | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     addItem(Strings::context_bar_center()); | 
					
						
							|  |  |  |     addItem(Strings::context_bar_fit_screen()); | 
					
						
							| 
									
										
										
										
											2016-09-15 20:50:00 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |   void onItemChange(Item* item) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ButtonSet::onItemChange(item); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Command* cmd = nullptr; | 
					
						
							|  |  |  |     Params params; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (selectedItem()) { | 
					
						
							|  |  |  |       case 0: { | 
					
						
							| 
									
										
										
										
											2017-12-02 02:10:21 +08:00
										 |  |  |         cmd = Commands::instance()->byId(CommandId::Zoom()); | 
					
						
							| 
									
										
										
										
											2016-09-15 20:50:00 +08:00
										 |  |  |         params.set("action", "set"); | 
					
						
							|  |  |  |         params.set("percentage", "100"); | 
					
						
							|  |  |  |         params.set("focus", "center"); | 
					
						
							|  |  |  |         UIContext::instance()->executeCommand(cmd, params); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       case 1: { | 
					
						
							| 
									
										
										
										
											2017-12-02 02:10:21 +08:00
										 |  |  |         cmd = Commands::instance()->byId(CommandId::ScrollCenter()); | 
					
						
							| 
									
										
										
										
											2016-09-15 20:50:00 +08:00
										 |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       case 2: { | 
					
						
							| 
									
										
										
										
											2017-12-02 02:10:21 +08:00
										 |  |  |         cmd = Commands::instance()->byId(CommandId::FitScreen()); | 
					
						
							| 
									
										
										
										
											2016-09-15 20:50:00 +08:00
										 |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (cmd) | 
					
						
							|  |  |  |       UIContext::instance()->executeCommand(cmd, params); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     deselectItems(); | 
					
						
							|  |  |  |     manager()->freeFocus(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-23 21:06:13 +08:00
										 |  |  | class ContextBar::BrushBackField : public ButtonSet { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |   BrushBackField() : ButtonSet(1) { addItem(Strings::context_bar_back()); } | 
					
						
							| 
									
										
										
										
											2017-11-23 21:06:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |   void onItemChange(Item* item) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ButtonSet::onItemChange(item); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-30 22:57:18 +08:00
										 |  |  |     Command* discardBrush = Commands::instance()->byId(CommandId::DiscardBrush()); | 
					
						
							| 
									
										
										
										
											2017-11-23 21:06:13 +08:00
										 |  |  |     UIContext::instance()->executeCommand(discardBrush); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-18 00:24:44 +08:00
										 |  |  | class ContextBar::BrushTypeField : public ButtonSet { | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  |   BrushTypeField(ContextBar* owner) | 
					
						
							|  |  |  |     : ButtonSet(1) | 
					
						
							| 
									
										
										
										
											2015-04-30 02:00:05 +08:00
										 |  |  |     , m_owner(owner) | 
					
						
							| 
									
										
										
										
											2015-12-18 00:24:44 +08:00
										 |  |  |     , m_brushes(App::instance()->brushes()) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-08-05 06:38:52 +08:00
										 |  |  |     SkinPartPtr part(new SkinPart); | 
					
						
							| 
									
										
										
										
											2018-01-30 01:09:51 +08:00
										 |  |  |     part->setBitmap(0, BrushPopup::createSurfaceForBrush(BrushRef(nullptr))); | 
					
						
							| 
									
										
										
										
											2024-05-07 04:00:27 +08:00
										 |  |  |     auto* theme = SkinTheme::get(this); | 
					
						
							|  |  |  |     addItem(part, theme->styles.brushType()); | 
					
						
							| 
									
										
										
										
											2021-05-16 01:33:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     m_popupWindow.Open.connect([this] { | 
					
						
							|  |  |  |       gfx::Region rgn(m_popupWindow.boundsOnScreen()); | 
					
						
							|  |  |  |       rgn |= gfx::Region(this->boundsOnScreen()); | 
					
						
							|  |  |  |       m_popupWindow.setHotRegion(rgn); | 
					
						
							|  |  |  |     }); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ~BrushTypeField() { closePopup(); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  |   void updateBrush(tools::Tool* tool = nullptr) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2018-01-30 01:09:51 +08:00
										 |  |  |     BrushRef brush = m_owner->activeBrush(tool); | 
					
						
							| 
									
										
										
										
											2015-08-05 06:38:52 +08:00
										 |  |  |     SkinPartPtr part(new SkinPart); | 
					
						
							| 
									
										
										
										
											2018-01-30 01:09:51 +08:00
										 |  |  |     part->setBitmap(0, BrushPopup::createSurfaceForBrush(brush)); | 
					
						
							| 
									
										
										
										
											2015-04-28 23:38:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-30 01:09:51 +08:00
										 |  |  |     const bool mono = (brush->type() != kImageBrushType); | 
					
						
							| 
									
										
										
										
											2022-12-17 04:59:08 +08:00
										 |  |  |     getItem(0)->setIcon(part); | 
					
						
							|  |  |  |     auto style = mono ? SkinTheme::instance()->styles.brushTypeMono() : | 
					
						
							|  |  |  |                         SkinTheme::instance()->styles.brushType(); | 
					
						
							|  |  |  |     getItem(0)->setStyle(style); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 00:38:12 +08:00
										 |  |  |   void switchPopup() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (!m_popupWindow.isVisible()) | 
					
						
							|  |  |  |       openPopup(); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       closePopup(); | 
					
						
							| 
									
										
										
										
											2017-12-01 03:23:31 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-16 04:12:11 +08:00
										 |  |  |   void showPopupAndHighlightSlot(int slot) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2017-12-01 03:23:31 +08:00
										 |  |  |     // TODO use slot?
 | 
					
						
							| 
									
										
										
										
											2015-12-16 04:12:11 +08:00
										 |  |  |     openPopup(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | protected: | 
					
						
							| 
									
										
										
										
											2015-08-29 02:41:02 +08:00
										 |  |  |   void onItemChange(Item* item) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ButtonSet::onItemChange(item); | 
					
						
							| 
									
										
										
										
											2020-05-02 00:38:12 +08:00
										 |  |  |     switchPopup(); | 
					
						
							| 
									
										
										
										
											2013-03-31 07:46:04 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-04 08:50:05 +08:00
										 |  |  |   void onSizeHint(SizeHintEvent& ev) override | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2022-02-19 06:01:46 +08:00
										 |  |  |     auto theme = SkinTheme::get(this); | 
					
						
							| 
									
										
										
										
											2018-11-15 22:08:45 +08:00
										 |  |  |     ev.setSizeHint(Size(theme->dimensions.brushTypeWidth(), theme->dimensions.contextBarHeight())); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  |   void onInitTheme(InitThemeEvent& ev) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ButtonSet::onInitTheme(ev); | 
					
						
							|  |  |  |     m_popupWindow.initTheme(); | 
					
						
							| 
									
										
										
										
											2024-10-19 04:51:44 +08:00
										 |  |  |     updateBrush(); | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2015-04-30 02:00:05 +08:00
										 |  |  |   // Returns a little rectangle that can be used by the popup as the
 | 
					
						
							|  |  |  |   // first brush position.
 | 
					
						
							| 
									
										
										
										
											2021-03-20 05:57:56 +08:00
										 |  |  |   gfx::Point popupPosCandidate() const | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
											
												Refactor several "getNoun()" getters to "noun()"
This is a work-in-progress to create a consistent API and finally
separate the whole Aseprite base/gfx/ui libs into a reusable C++ library.
Classes:
app::IFileItem, app::AppMenuItem, app::skin::SkinPart,
gfx::Rect, gfx::Border, she::FileDialog,
ui::IButtonIcon, ui::Graphics, ui::Overlay, ui::Widget,
ui::ScrollableViewDelegate, and UI events
											
										 
											2015-12-05 01:39:04 +08:00
										 |  |  |     Rect rc = bounds(); | 
					
						
							| 
									
										
										
										
											2014-11-26 09:33:45 +08:00
										 |  |  |     rc.y += rc.h - 2 * guiscale(); | 
					
						
							| 
									
										
										
										
											2021-03-20 05:57:56 +08:00
										 |  |  |     return rc.origin(); | 
					
						
							| 
									
										
										
										
											2015-04-30 02:00:05 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-04-28 23:38:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-30 02:00:05 +08:00
										 |  |  |   void openPopup() | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  |     doc::BrushRef brush = m_owner->activeBrush(); | 
					
						
							| 
									
										
										
										
											2015-04-28 23:38:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-20 05:57:56 +08:00
										 |  |  |     m_popupWindow.regenerate(display(), popupPosCandidate()); | 
					
						
							| 
									
										
										
										
											2015-04-28 23:53:02 +08:00
										 |  |  |     m_popupWindow.setBrush(brush.get()); | 
					
						
							|  |  |  |     m_popupWindow.openWindow(); | 
					
						
							| 
									
										
										
										
											2013-03-31 07:46:04 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void closePopup() | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-04-28 23:53:02 +08:00
										 |  |  |     m_popupWindow.closeWindow(NULL); | 
					
						
							| 
									
										
										
										
											2015-07-03 00:16:06 +08:00
										 |  |  |     deselectItems(); | 
					
						
							| 
									
										
										
										
											2013-03-31 07:46:04 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  |   ContextBar* m_owner; | 
					
						
							| 
									
										
										
										
											2015-12-16 04:12:11 +08:00
										 |  |  |   AppBrushes& m_brushes; | 
					
						
							| 
									
										
										
										
											2015-04-28 23:53:02 +08:00
										 |  |  |   BrushPopup m_popupWindow; | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-04 00:41:50 +08:00
										 |  |  | class ContextBar::BrushSizeField : public IntEntry { | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2014-12-08 07:50:26 +08:00
										 |  |  |   BrushSizeField() : IntEntry(Brush::kMinBrushSize, Brush::kMaxBrushSize) { setSuffix("px"); } | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2014-08-15 10:07:47 +08:00
										 |  |  |   void onValueChange() override | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     if (g_updatingFromCode) | 
					
						
							| 
									
										
										
										
											2014-10-25 23:10:52 +08:00
										 |  |  |       return; | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     IntEntry::onValueChange(); | 
					
						
							| 
									
										
										
										
											2023-04-15 00:43:36 +08:00
										 |  |  |     base::ScopedValue lockFlag(g_updatingFromCode, true); | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Tool* tool = App::instance()->activeTool(); | 
					
						
							|  |  |  |     Preferences::instance().tool(tool).brush.size(getValue()); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  | class ContextBar::BrushAngleField : public IntEntry { | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | public: | 
					
						
							|  |  |  |   BrushAngleField(BrushTypeField* brushType) : IntEntry(-180, 180), m_brushType(brushType) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2013-11-24 05:01:42 +08:00
										 |  |  |     setSuffix("\xc2\xb0"); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							| 
									
										
										
										
											2014-08-15 10:07:47 +08:00
										 |  |  |   void onValueChange() override | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     if (g_updatingFromCode) | 
					
						
							| 
									
										
										
										
											2014-10-25 23:10:52 +08:00
										 |  |  |       return; | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     IntEntry::onValueChange(); | 
					
						
							| 
									
										
										
										
											2023-04-15 00:43:36 +08:00
										 |  |  |     base::ScopedValue lockFlag(g_updatingFromCode, true); | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Tool* tool = App::instance()->activeTool(); | 
					
						
							|  |  |  |     Preferences::instance().tool(tool).brush.angle(getValue()); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  |     m_brushType->updateBrush(); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |   BrushTypeField* m_brushType; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  | class ContextBar::BrushPatternField : public ComboBox { | 
					
						
							| 
									
										
										
										
											2015-04-27 11:08:04 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2019-04-23 01:51:11 +08:00
										 |  |  |   BrushPatternField() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // We use "m_lock" variable to avoid setting the pattern
 | 
					
						
							|  |  |  |     // brush when we call ComboBox::addItem() (because the first
 | 
					
						
							|  |  |  |     // addItem() generates an onChange() event).
 | 
					
						
							|  |  |  |     m_lock = true; | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     addItem(Strings::context_bar_pattern_aligned_to_src()); | 
					
						
							|  |  |  |     addItem(Strings::context_bar_pattern_aligned_to_dest()); | 
					
						
							|  |  |  |     addItem(Strings::context_bar_paint_brush()); | 
					
						
							| 
									
										
										
										
											2019-04-23 01:51:11 +08:00
										 |  |  |     m_lock = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setSelectedItemIndex((int)Preferences::instance().brush.pattern()); | 
					
						
							| 
									
										
										
										
											2015-04-27 11:08:04 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void setBrushPattern(BrushPattern type) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     int index = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (type) { | 
					
						
							| 
									
										
										
										
											2015-04-27 22:45:00 +08:00
										 |  |  |       case BrushPattern::ALIGNED_TO_SRC: index = 0; break; | 
					
						
							| 
									
										
										
										
											2015-04-27 11:08:04 +08:00
										 |  |  |       case BrushPattern::ALIGNED_TO_DST: index = 1; break; | 
					
						
							|  |  |  |       case BrushPattern::PAINT_BRUSH:    index = 2; break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_lock = true; | 
					
						
							|  |  |  |     setSelectedItemIndex(index); | 
					
						
							|  |  |  |     m_lock = false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |   void onChange() override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ComboBox::onChange(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_lock) | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-27 22:45:00 +08:00
										 |  |  |     BrushPattern type = BrushPattern::ALIGNED_TO_SRC; | 
					
						
							| 
									
										
										
										
											2015-04-27 11:08:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     switch (getSelectedItemIndex()) { | 
					
						
							| 
									
										
										
										
											2015-04-27 22:45:00 +08:00
										 |  |  |       case 0: type = BrushPattern::ALIGNED_TO_SRC; break; | 
					
						
							| 
									
										
										
										
											2015-04-27 11:08:04 +08:00
										 |  |  |       case 1: type = BrushPattern::ALIGNED_TO_DST; break; | 
					
						
							|  |  |  |       case 2: type = BrushPattern::PAINT_BRUSH; break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     Preferences::instance().brush.pattern(type); | 
					
						
							| 
									
										
										
										
											2015-04-27 11:08:04 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool m_lock; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  | class ContextBar::ToleranceField : public IntEntry { | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2013-03-31 08:14:52 +08:00
										 |  |  |   ToleranceField() : IntEntry(0, 255) {} | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							| 
									
										
										
										
											2014-08-15 10:07:47 +08:00
										 |  |  |   void onValueChange() override | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     if (g_updatingFromCode) | 
					
						
							| 
									
										
										
										
											2014-10-25 23:10:52 +08:00
										 |  |  |       return; | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     IntEntry::onValueChange(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Tool* tool = App::instance()->activeTool(); | 
					
						
							|  |  |  |     Preferences::instance().tool(tool).tolerance(getValue()); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  | class ContextBar::ContiguousField : public CheckBox { | 
					
						
							| 
									
										
										
										
											2014-08-07 11:07:24 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |   ContiguousField() : CheckBox(Strings::context_bar_contiguous()) { initTheme(); } | 
					
						
							| 
									
										
										
										
											2014-08-07 11:07:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-18 00:22:46 +08:00
										 |  |  | protected: | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  |   void onInitTheme(InitThemeEvent& ev) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     CheckBox::onInitTheme(ev); | 
					
						
							| 
									
										
										
										
											2022-02-19 06:01:46 +08:00
										 |  |  |     setStyle(SkinTheme::get(this)->styles.miniCheckBox()); | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-12 22:00:16 +08:00
										 |  |  |   void onClick() override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     CheckBox::onClick(); | 
					
						
							| 
									
										
										
										
											2015-06-18 00:22:46 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Tool* tool = App::instance()->activeTool(); | 
					
						
							|  |  |  |     Preferences::instance().tool(tool).contiguous(isSelected()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     releaseFocus(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-04 02:31:27 +08:00
										 |  |  | class ContextBar::PaintBucketSettingsField : public ButtonSet { | 
					
						
							| 
									
										
										
										
											2015-06-18 00:22:46 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2016-05-04 02:31:27 +08:00
										 |  |  |   PaintBucketSettingsField() : ButtonSet(1) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2024-05-07 04:00:27 +08:00
										 |  |  |     auto* theme = SkinTheme::get(this); | 
					
						
							|  |  |  |     addItem(theme->parts.timelineGear(), theme->styles.contextBarButton()); | 
					
						
							| 
									
										
										
										
											2014-08-07 11:07:24 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							| 
									
										
										
										
											2016-05-04 02:31:27 +08:00
										 |  |  |   void onItemChange(Item* item) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ButtonSet::onItemChange(item); | 
					
						
							|  |  |  |     const gfx::Rect bounds = this->bounds(); | 
					
						
							| 
									
										
										
										
											2014-08-07 11:07:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     Tool* tool = App::instance()->activeTool(); | 
					
						
							| 
									
										
										
										
											2016-05-04 02:31:27 +08:00
										 |  |  |     auto& toolPref = Preferences::instance().tool(tool); | 
					
						
							| 
									
										
										
										
											2014-08-07 11:07:24 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-04 02:31:27 +08:00
										 |  |  |     Menu menu; | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     MenuItem stopAtGrid(Strings::context_bar_stop_at_grid()), | 
					
						
							|  |  |  |       activeLayer(Strings::context_bar_refer_active_layer()), | 
					
						
							|  |  |  |       allLayers(Strings::context_bar_refer_visible_layer()); | 
					
						
							| 
									
										
										
										
											2016-05-04 02:31:27 +08:00
										 |  |  |     menu.addChild(&stopAtGrid); | 
					
						
							|  |  |  |     menu.addChild(new MenuSeparator()); | 
					
						
							|  |  |  |     menu.addChild(&activeLayer); | 
					
						
							|  |  |  |     menu.addChild(&allLayers); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-29 09:07:32 +08:00
										 |  |  |     menu.addChild(new MenuSeparator); | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     menu.addChild(new Label(Strings::context_bar_pixel_connectivity())); | 
					
						
							| 
									
										
										
										
											2019-03-29 09:07:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     HBox box; | 
					
						
							|  |  |  |     ButtonSet buttonset(2); | 
					
						
							| 
									
										
										
										
											2023-12-23 02:03:07 +08:00
										 |  |  |     buttonset.addItem(Strings::context_bar_pixel_connectivity_4()); | 
					
						
							|  |  |  |     buttonset.addItem(Strings::context_bar_pixel_connectivity_8()); | 
					
						
							| 
									
										
										
										
											2019-03-29 09:07:32 +08:00
										 |  |  |     box.addChild(&buttonset); | 
					
						
							|  |  |  |     menu.addChild(&box); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-04 02:31:27 +08:00
										 |  |  |     stopAtGrid.setSelected(toolPref.floodfill.stopAtGrid() == app::gen::StopAtGrid::IF_VISIBLE); | 
					
						
							|  |  |  |     activeLayer.setSelected(toolPref.floodfill.referTo() == app::gen::FillReferTo::ACTIVE_LAYER); | 
					
						
							|  |  |  |     allLayers.setSelected(toolPref.floodfill.referTo() == app::gen::FillReferTo::ALL_LAYERS); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-29 09:07:32 +08:00
										 |  |  |     int index = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (toolPref.floodfill.pixelConnectivity()) { | 
					
						
							|  |  |  |       case app::gen::PixelConnectivity::FOUR_CONNECTED:  index = 0; break; | 
					
						
							|  |  |  |       case app::gen::PixelConnectivity::EIGHT_CONNECTED: index = 1; break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     buttonset.setSelectedItem(index); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-04 02:31:27 +08:00
										 |  |  |     stopAtGrid.Click.connect([&] { | 
					
						
							|  |  |  |       toolPref.floodfill.stopAtGrid(toolPref.floodfill.stopAtGrid() == | 
					
						
							|  |  |  |                                         app::gen::StopAtGrid::IF_VISIBLE ? | 
					
						
							|  |  |  |                                       app::gen::StopAtGrid::NEVER : | 
					
						
							|  |  |  |                                       app::gen::StopAtGrid::IF_VISIBLE); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     activeLayer.Click.connect( | 
					
						
							|  |  |  |       [&] { toolPref.floodfill.referTo(app::gen::FillReferTo::ACTIVE_LAYER); }); | 
					
						
							|  |  |  |     allLayers.Click.connect([&] { toolPref.floodfill.referTo(app::gen::FillReferTo::ALL_LAYERS); }); | 
					
						
							| 
									
										
										
										
											2024-12-17 01:52:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-29 09:07:32 +08:00
										 |  |  |     buttonset.ItemChange.connect([&buttonset, &toolPref](ButtonSet::Item* item) { | 
					
						
							|  |  |  |       switch (buttonset.selectedItem()) { | 
					
						
							|  |  |  |         case 0: | 
					
						
							|  |  |  |           toolPref.floodfill.pixelConnectivity(app::gen::PixelConnectivity::FOUR_CONNECTED); | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         case 1: | 
					
						
							|  |  |  |           toolPref.floodfill.pixelConnectivity(app::gen::PixelConnectivity::EIGHT_CONNECTED); | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-27 22:04:07 +08:00
										 |  |  |     menu.initTheme(); | 
					
						
							| 
									
										
										
										
											2021-03-20 05:57:56 +08:00
										 |  |  |     menu.showPopup(gfx::Point(bounds.x, bounds.y2()), display()); | 
					
						
							| 
									
										
										
										
											2016-05-04 02:31:27 +08:00
										 |  |  |     deselectItems(); | 
					
						
							| 
									
										
										
										
											2014-08-07 11:07:24 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  | class ContextBar::InkTypeField : public ButtonSet { | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2015-07-03 00:16:06 +08:00
										 |  |  |   InkTypeField(ContextBar* owner) : ButtonSet(1), m_owner(owner) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2024-05-07 04:00:27 +08:00
										 |  |  |     auto* theme = SkinTheme::get(this); | 
					
						
							|  |  |  |     addItem(theme->parts.inkSimple(), theme->styles.inkType()); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-02 07:20:58 +08:00
										 |  |  |   void setInkType(InkType inkType) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-11-27 12:35:31 +08:00
										 |  |  |     Preferences& pref = Preferences::instance(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (pref.shared.shareInk()) { | 
					
						
							| 
									
										
										
										
											2016-04-23 00:19:06 +08:00
										 |  |  |       for (Tool* tool : *App::instance()->toolBox()) | 
					
						
							| 
									
										
										
										
											2015-11-27 12:35:31 +08:00
										 |  |  |         pref.tool(tool).ink(inkType); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       Tool* tool = App::instance()->activeTool(); | 
					
						
							|  |  |  |       pref.tool(tool).ink(inkType); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-26 02:20:53 +08:00
										 |  |  |     m_owner->updateForActiveTool(); | 
					
						
							| 
									
										
										
										
											2015-11-27 12:35:31 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void setInkTypeIcon(InkType inkType) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2022-02-19 06:01:46 +08:00
										 |  |  |     auto theme = SkinTheme::get(this); | 
					
						
							| 
									
										
										
										
											2015-08-14 00:26:52 +08:00
										 |  |  |     SkinPartPtr part = theme->parts.inkSimple(); | 
					
						
							| 
									
										
										
										
											2014-03-09 08:00:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     switch (inkType) { | 
					
						
							| 
									
										
										
										
											2015-08-14 00:26:52 +08:00
										 |  |  |       case InkType::SIMPLE:            part = theme->parts.inkSimple(); break; | 
					
						
							|  |  |  |       case InkType::ALPHA_COMPOSITING: part = theme->parts.inkAlphaCompositing(); break; | 
					
						
							| 
									
										
										
										
											2015-08-05 06:38:52 +08:00
										 |  |  |       case InkType::COPY_COLOR:        part = theme->parts.inkCopyColor(); break; | 
					
						
							|  |  |  |       case InkType::LOCK_ALPHA:        part = theme->parts.inkLockAlpha(); break; | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  |       case InkType::SHADING:           part = theme->parts.inkShading(); break; | 
					
						
							| 
									
										
										
										
											2014-03-09 08:00:14 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 06:38:52 +08:00
										 |  |  |     getItem(0)->setIcon(part); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							| 
									
										
										
										
											2015-08-29 02:41:02 +08:00
										 |  |  |   void onItemChange(Item* item) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ButtonSet::onItemChange(item); | 
					
						
							| 
									
										
										
										
											2013-04-02 07:20:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												Refactor several "getNoun()" getters to "noun()"
This is a work-in-progress to create a consistent API and finally
separate the whole Aseprite base/gfx/ui libs into a reusable C++ library.
Classes:
app::IFileItem, app::AppMenuItem, app::skin::SkinPart,
gfx::Rect, gfx::Border, she::FileDialog,
ui::IButtonIcon, ui::Graphics, ui::Overlay, ui::Widget,
ui::ScrollableViewDelegate, and UI events
											
										 
											2015-12-05 01:39:04 +08:00
										 |  |  |     gfx::Rect bounds = this->bounds(); | 
					
						
							| 
									
										
										
										
											2014-04-22 09:23:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-20 05:57:56 +08:00
										 |  |  |     AppMenus::instance()->getInkPopupMenu()->showPopup(gfx::Point(bounds.x, bounds.y2()), | 
					
						
							|  |  |  |                                                        display()); | 
					
						
							| 
									
										
										
										
											2015-07-03 00:16:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     deselectItems(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ContextBar* m_owner; | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  | class ContextBar::InkShadesField : public HBox { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2019-12-17 08:17:12 +08:00
										 |  |  |   InkShadesField(ColorBar* colorBar) | 
					
						
							| 
									
										
										
										
											2022-02-19 06:01:46 +08:00
										 |  |  |     : m_button(SkinTheme::get(this)->parts.iconArrowDown()) | 
					
						
							| 
									
										
										
										
											2018-03-29 02:56:40 +08:00
										 |  |  |     , m_shade(Shade(), ColorShades::DragAndDropEntries) | 
					
						
							| 
									
										
										
										
											2015-11-26 02:17:34 +08:00
										 |  |  |     , m_loaded(false) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |     addChild(&m_button); | 
					
						
							|  |  |  |     addChild(&m_shade); | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     m_shade.setText(Strings::context_bar_select_palette_color()); | 
					
						
							| 
									
										
										
										
											2019-12-17 08:17:12 +08:00
										 |  |  |     m_shade.setMinColors(2); | 
					
						
							|  |  |  |     m_conn = colorBar->ChangeSelection.connect([this] { onChangeColorBarSelection(); }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |     m_button.setFocusStop(false); | 
					
						
							| 
									
										
										
										
											2020-07-04 08:51:46 +08:00
										 |  |  |     m_button.Click.connect([this] { onShowMenu(); }); | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     initTheme(); | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-26 02:17:34 +08:00
										 |  |  |   ~InkShadesField() { saveShades(); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |   void reverseShadeColors() { m_shade.reverseShadeColors(); } | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |   doc::Remap* createShadeRemap(bool left) { return m_shade.createShadeRemap(left); } | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 04:27:04 +08:00
										 |  |  |   Shade getShade() const { return m_shade.getShade(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void setShade(const Shade& shade) { m_shade.setShade(shade); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-02 03:24:29 +08:00
										 |  |  |   void updateShadeFromColorBarPicks() | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2019-12-17 08:17:12 +08:00
										 |  |  |     auto colorBar = ColorBar::instance(); | 
					
						
							|  |  |  |     if (!colorBar) | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     doc::PalettePicks picks; | 
					
						
							|  |  |  |     colorBar->getPaletteView()->getSelectedEntries(picks); | 
					
						
							|  |  |  |     if (picks.picks() >= 2) | 
					
						
							|  |  |  |       onChangeColorBarSelection(); | 
					
						
							| 
									
										
										
										
											2016-07-02 03:24:29 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  |   void onInitTheme(InitThemeEvent& ev) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     HBox::onInitTheme(ev); | 
					
						
							| 
									
										
										
										
											2022-02-19 06:01:46 +08:00
										 |  |  |     auto theme = SkinTheme::get(this); | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  |     noBorderNoChildSpacing(); | 
					
						
							|  |  |  |     m_shade.setStyle(theme->styles.topShadeView()); | 
					
						
							|  |  |  |     m_button.setBgColor(theme->colors.workspace()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |   void onShowMenu() | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-11-26 02:17:34 +08:00
										 |  |  |     loadShades(); | 
					
						
							| 
									
										
										
											
												Refactor several "getNoun()" getters to "noun()"
This is a work-in-progress to create a consistent API and finally
separate the whole Aseprite base/gfx/ui libs into a reusable C++ library.
Classes:
app::IFileItem, app::AppMenuItem, app::skin::SkinPart,
gfx::Rect, gfx::Border, she::FileDialog,
ui::IButtonIcon, ui::Graphics, ui::Overlay, ui::Widget,
ui::ScrollableViewDelegate, and UI events
											
										 
											2015-12-05 01:39:04 +08:00
										 |  |  |     gfx::Rect bounds = m_button.bounds(); | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |     Menu menu; | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     MenuItem reverse(Strings::context_bar_reverse_shade()), save(Strings::context_bar_save_shade()); | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |     menu.addChild(&reverse); | 
					
						
							|  |  |  |     menu.addChild(&save); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool hasShade = (m_shade.size() >= 2); | 
					
						
							|  |  |  |     reverse.setEnabled(hasShade); | 
					
						
							|  |  |  |     save.setEnabled(hasShade); | 
					
						
							| 
									
										
										
										
											2020-07-04 08:51:46 +08:00
										 |  |  |     reverse.Click.connect([this] { reverseShadeColors(); }); | 
					
						
							|  |  |  |     save.Click.connect([this] { onSaveShade(); }); | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!m_shades.empty()) { | 
					
						
							| 
									
										
										
										
											2022-02-19 06:01:46 +08:00
										 |  |  |       auto theme = SkinTheme::get(this); | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       menu.addChild(new MenuSeparator); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       int i = 0; | 
					
						
							|  |  |  |       for (const Shade& shade : m_shades) { | 
					
						
							| 
									
										
										
										
											2018-03-29 02:56:40 +08:00
										 |  |  |         auto shadeWidget = new ColorShades(shade, ColorShades::ClickWholeShade); | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |         shadeWidget->setExpansive(true); | 
					
						
							| 
									
										
										
										
											2020-03-28 03:14:00 +08:00
										 |  |  |         shadeWidget->Click.connect([&](ColorShades::ClickEvent&) { m_shade.setShade(shade); }); | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  |         auto close = new IconButton(theme->parts.iconClose()); | 
					
						
							|  |  |  |         close->InitTheme.connect( | 
					
						
							| 
									
										
										
										
											2022-02-19 06:01:46 +08:00
										 |  |  |           [close] { close->setBgColor(SkinTheme::get(close)->colors.menuitemNormalFace()); }); | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  |         close->initTheme(); | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |         close->Click.connect([this, i, close] { | 
					
						
							| 
									
										
										
										
											2020-07-04 08:51:46 +08:00
										 |  |  |           m_shades.erase(m_shades.begin() + i); | 
					
						
							|  |  |  |           close->closeWindow(); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         auto item = new HBox(); | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  |         item->InitTheme.connect([item] { item->noBorderNoChildSpacing(); }); | 
					
						
							|  |  |  |         item->initTheme(); | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |         item->addChild(shadeWidget); | 
					
						
							|  |  |  |         item->addChild(close); | 
					
						
							|  |  |  |         menu.addChild(item); | 
					
						
							|  |  |  |         ++i; | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-20 05:57:56 +08:00
										 |  |  |     menu.showPopup(gfx::Point(bounds.x, bounds.y2()), display()); | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |     m_button.invalidate(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void onSaveShade() | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-11-26 02:17:34 +08:00
										 |  |  |     loadShades(); | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |     m_shades.push_back(m_shade.getShade()); | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-26 02:17:34 +08:00
										 |  |  |   void loadShades() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (m_loaded) | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_loaded = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-23 06:14:36 +08:00
										 |  |  |     std::string buf; | 
					
						
							| 
									
										
										
										
											2015-11-26 02:17:34 +08:00
										 |  |  |     int n = get_config_int("shades", "count", 0); | 
					
						
							| 
									
										
										
										
											2022-06-10 05:28:06 +08:00
										 |  |  |     n = std::clamp(n, 0, 256); | 
					
						
							| 
									
										
										
										
											2015-11-26 02:17:34 +08:00
										 |  |  |     for (int i = 0; i < n; ++i) { | 
					
						
							| 
									
										
										
										
											2023-09-23 06:14:36 +08:00
										 |  |  |       buf = fmt::format("shade{}", i); | 
					
						
							|  |  |  |       Shade shade = shade_from_string(get_config_string("shades", buf.c_str(), "")); | 
					
						
							| 
									
										
										
										
											2015-11-26 02:17:34 +08:00
										 |  |  |       if (shade.size() >= 2) | 
					
						
							|  |  |  |         m_shades.push_back(shade); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void saveShades() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (!m_loaded) | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-23 06:14:36 +08:00
										 |  |  |     std::string buf; | 
					
						
							| 
									
										
										
										
											2015-11-26 02:17:34 +08:00
										 |  |  |     int n = int(m_shades.size()); | 
					
						
							|  |  |  |     set_config_int("shades", "count", n); | 
					
						
							|  |  |  |     for (int i = 0; i < n; ++i) { | 
					
						
							| 
									
										
										
										
											2023-09-23 06:14:36 +08:00
										 |  |  |       buf = fmt::format("shade{}", i); | 
					
						
							|  |  |  |       set_config_string("shades", buf.c_str(), shade_to_string(m_shades[i]).c_str()); | 
					
						
							| 
									
										
										
										
											2015-11-26 02:17:34 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:17:12 +08:00
										 |  |  |   void onChangeColorBarSelection() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (!m_shade.isVisible()) | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     doc::PalettePicks picks; | 
					
						
							|  |  |  |     ColorBar::instance()->getPaletteView()->getSelectedEntries(picks); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Shade newShade = m_shade.getShade(); | 
					
						
							|  |  |  |     newShade.resize(picks.picks()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int i = 0, j = 0; | 
					
						
							|  |  |  |     for (bool pick : picks) { | 
					
						
							|  |  |  |       if (pick) | 
					
						
							|  |  |  |         newShade[j++] = app::Color::fromIndex(i); | 
					
						
							|  |  |  |       ++i; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_shade.setShade(newShade); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     layout(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |   IconButton m_button; | 
					
						
							| 
									
										
										
										
											2018-03-28 23:57:00 +08:00
										 |  |  |   ColorShades m_shade; | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |   std::vector<Shade> m_shades; | 
					
						
							| 
									
										
										
										
											2015-11-26 02:17:34 +08:00
										 |  |  |   bool m_loaded; | 
					
						
							| 
									
										
										
										
											2019-12-17 08:17:12 +08:00
										 |  |  |   obs::scoped_connection m_conn; | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-11 02:27:17 +08:00
										 |  |  | class ContextBar::InkOpacityField : public AlphaEntry { | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2024-01-11 02:27:17 +08:00
										 |  |  |   InkOpacityField() : AlphaEntry(AlphaSlider::Type::OPACITY) {} | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							| 
									
										
										
										
											2014-08-15 10:07:47 +08:00
										 |  |  |   void onValueChange() override | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     if (g_updatingFromCode) | 
					
						
							| 
									
										
										
										
											2014-10-25 23:10:52 +08:00
										 |  |  |       return; | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-11 02:27:17 +08:00
										 |  |  |     AlphaEntry::onValueChange(); | 
					
						
							| 
									
										
										
										
											2023-04-15 00:43:36 +08:00
										 |  |  |     base::ScopedValue lockFlag(g_updatingFromCode, true); | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     int newValue = getValue(); | 
					
						
							| 
									
										
										
										
											2015-07-23 21:07:07 +08:00
										 |  |  |     Preferences& pref = Preferences::instance(); | 
					
						
							|  |  |  |     if (pref.shared.shareInk()) { | 
					
						
							| 
									
										
										
										
											2016-04-23 00:19:06 +08:00
										 |  |  |       for (Tool* tool : *App::instance()->toolBox()) | 
					
						
							| 
									
										
										
										
											2015-07-23 21:07:07 +08:00
										 |  |  |         pref.tool(tool).opacity(newValue); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       Tool* tool = App::instance()->activeTool(); | 
					
						
							|  |  |  |       pref.tool(tool).opacity(newValue); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  | class ContextBar::SprayWidthField : public IntEntry { | 
					
						
							| 
									
										
										
										
											2013-03-31 08:31:34 +08:00
										 |  |  | public: | 
					
						
							|  |  |  |   SprayWidthField() : IntEntry(1, 32) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							| 
									
										
										
										
											2014-08-15 10:07:47 +08:00
										 |  |  |   void onValueChange() override | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2013-03-31 08:31:34 +08:00
										 |  |  |     IntEntry::onValueChange(); | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     if (g_updatingFromCode) | 
					
						
							| 
									
										
										
										
											2014-10-25 23:10:52 +08:00
										 |  |  |       return; | 
					
						
							| 
									
										
										
										
											2013-03-31 08:31:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     Tool* tool = App::instance()->activeTool(); | 
					
						
							|  |  |  |     Preferences::instance().tool(tool).spray.width(getValue()); | 
					
						
							| 
									
										
										
										
											2013-03-31 08:31:34 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  | class ContextBar::SpraySpeedField : public IntEntry { | 
					
						
							| 
									
										
										
										
											2013-03-31 08:31:34 +08:00
										 |  |  | public: | 
					
						
							|  |  |  |   SpraySpeedField() : IntEntry(1, 100) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							| 
									
										
										
										
											2014-08-15 10:07:47 +08:00
										 |  |  |   void onValueChange() override | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     if (g_updatingFromCode) | 
					
						
							| 
									
										
										
										
											2014-10-25 23:10:52 +08:00
										 |  |  |       return; | 
					
						
							| 
									
										
										
										
											2013-03-31 08:31:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     IntEntry::onValueChange(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Tool* tool = App::instance()->activeTool(); | 
					
						
							|  |  |  |     Preferences::instance().tool(tool).spray.speed(getValue()); | 
					
						
							| 
									
										
										
										
											2013-03-31 08:31:34 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-24 09:42:14 +08:00
										 |  |  | class ContextBar::TransparentColorField : public HBox { | 
					
						
							| 
									
										
										
										
											2013-11-30 04:59:28 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2018-12-14 01:08:56 +08:00
										 |  |  |   TransparentColorField(ContextBar* owner, TooltipManager* tooltipManager) | 
					
						
							| 
									
										
										
										
											2015-07-24 09:42:14 +08:00
										 |  |  |     : m_icon(1) | 
					
						
							| 
									
										
										
										
											2017-06-23 05:39:28 +08:00
										 |  |  |     , m_maskColor(app::Color::fromMask(), IMAGE_RGB, ColorButtonOptions()) | 
					
						
							| 
									
										
										
										
											2015-07-24 09:42:14 +08:00
										 |  |  |     , m_owner(owner) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2022-02-19 06:01:46 +08:00
										 |  |  |     auto theme = SkinTheme::get(this); | 
					
						
							| 
									
										
										
										
											2015-08-05 06:38:52 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-24 09:42:14 +08:00
										 |  |  |     addChild(&m_icon); | 
					
						
							|  |  |  |     addChild(&m_maskColor); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 06:38:52 +08:00
										 |  |  |     m_icon.addItem(theme->parts.selectionOpaque()); | 
					
						
							| 
									
										
										
										
											2015-12-04 08:50:05 +08:00
										 |  |  |     gfx::Size sz = m_icon.getItem(0)->sizeHint(); | 
					
						
							| 
									
										
										
										
											2015-07-24 09:42:14 +08:00
										 |  |  |     sz.w += 2 * guiscale(); | 
					
						
							|  |  |  |     m_icon.getItem(0)->setMinSize(sz); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-04 08:51:46 +08:00
										 |  |  |     m_icon.ItemChange.connect([this] { onPopup(); }); | 
					
						
							|  |  |  |     m_maskColor.Change.connect([this] { onChangeColor(); }); | 
					
						
							| 
									
										
										
										
											2015-07-27 22:43:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Preferences::instance().selection.opaque.AfterChange.connect([this] { onOpaqueChange(); }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-28 22:14:12 +08:00
										 |  |  |     onOpaqueChange(); | 
					
						
							| 
									
										
										
										
											2018-12-14 01:08:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     tooltipManager->addTooltipFor(m_icon.at(0), | 
					
						
							|  |  |  |                                   Strings::context_bar_transparent_color_options(), | 
					
						
							|  |  |  |                                   BOTTOM); | 
					
						
							|  |  |  |     tooltipManager->addTooltipFor(&m_maskColor, Strings::context_bar_transparent_color(), BOTTOM); | 
					
						
							| 
									
										
										
										
											2013-11-30 04:59:28 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-24 09:42:14 +08:00
										 |  |  | private: | 
					
						
							|  |  |  |   void onPopup() | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
											
												Refactor several "getNoun()" getters to "noun()"
This is a work-in-progress to create a consistent API and finally
separate the whole Aseprite base/gfx/ui libs into a reusable C++ library.
Classes:
app::IFileItem, app::AppMenuItem, app::skin::SkinPart,
gfx::Rect, gfx::Border, she::FileDialog,
ui::IButtonIcon, ui::Graphics, ui::Overlay, ui::Widget,
ui::ScrollableViewDelegate, and UI events
											
										 
											2015-12-05 01:39:04 +08:00
										 |  |  |     gfx::Rect bounds = this->bounds(); | 
					
						
							| 
									
										
										
										
											2015-07-24 09:42:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Menu menu; | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     MenuItem opaque(Strings::context_bar_opaque()), masked(Strings::context_bar_transparent()), | 
					
						
							|  |  |  |       automatic(Strings::context_bar_auto_adjust_layer()); | 
					
						
							| 
									
										
										
										
											2015-07-24 09:42:14 +08:00
										 |  |  |     menu.addChild(&opaque); | 
					
						
							|  |  |  |     menu.addChild(&masked); | 
					
						
							| 
									
										
										
										
											2015-12-02 03:37:46 +08:00
										 |  |  |     menu.addChild(new MenuSeparator); | 
					
						
							|  |  |  |     menu.addChild(&automatic); | 
					
						
							| 
									
										
										
										
											2015-07-24 09:42:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (Preferences::instance().selection.opaque()) | 
					
						
							|  |  |  |       opaque.setSelected(true); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       masked.setSelected(true); | 
					
						
							| 
									
										
										
										
											2015-12-02 03:37:46 +08:00
										 |  |  |     automatic.setSelected(Preferences::instance().selection.autoOpaque()); | 
					
						
							| 
									
										
										
										
											2015-07-24 09:42:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-04 08:51:46 +08:00
										 |  |  |     opaque.Click.connect([this] { setOpaque(true); }); | 
					
						
							|  |  |  |     masked.Click.connect([this] { setOpaque(false); }); | 
					
						
							|  |  |  |     automatic.Click.connect([this] { onAutomatic(); }); | 
					
						
							| 
									
										
										
										
											2015-07-24 09:42:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-20 05:57:56 +08:00
										 |  |  |     menu.showPopup(gfx::Point(bounds.x, bounds.y2()), display()); | 
					
						
							| 
									
										
										
										
											2013-11-30 04:59:28 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-07-24 09:42:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   void onChangeColor() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     Preferences::instance().selection.transparentColor(m_maskColor.getColor()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-27 22:43:48 +08:00
										 |  |  |   void setOpaque(bool opaque) { Preferences::instance().selection.opaque(opaque); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // When the preference is changed from outside the context bar
 | 
					
						
							|  |  |  |   void onOpaqueChange() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     bool opaque = Preferences::instance().selection.opaque(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-19 06:01:46 +08:00
										 |  |  |     auto theme = SkinTheme::get(this); | 
					
						
							| 
									
										
										
										
											2015-08-05 06:38:52 +08:00
										 |  |  |     SkinPartPtr part = (opaque ? theme->parts.selectionOpaque() : theme->parts.selectionMasked()); | 
					
						
							|  |  |  |     m_icon.getItem(0)->setIcon(part); | 
					
						
							| 
									
										
										
										
											2015-07-24 09:42:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     m_maskColor.setVisible(!opaque); | 
					
						
							|  |  |  |     if (!opaque) { | 
					
						
							|  |  |  |       Preferences::instance().selection.transparentColor(m_maskColor.getColor()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_owner) | 
					
						
							|  |  |  |       m_owner->layout(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-02 03:37:46 +08:00
										 |  |  |   void onAutomatic() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     Preferences::instance().selection.autoOpaque(!Preferences::instance().selection.autoOpaque()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-24 09:42:14 +08:00
										 |  |  |   ButtonSet m_icon; | 
					
						
							|  |  |  |   ColorButton m_maskColor; | 
					
						
							|  |  |  |   ContextBar* m_owner; | 
					
						
							| 
									
										
										
										
											2013-11-30 04:59:28 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  | class ContextBar::PivotField : public ButtonSet { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |   PivotField() : ButtonSet(1) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2024-05-07 04:00:27 +08:00
										 |  |  |     auto* theme = SkinTheme::get(this); | 
					
						
							|  |  |  |     addItem(SkinTheme::get(this)->parts.pivotCenter(), theme->styles.pivotField()); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 03:24:36 +08:00
										 |  |  |     m_pivotConn = Preferences::instance().selection.pivotPosition.AfterChange.connect( | 
					
						
							| 
									
										
										
										
											2020-07-04 08:51:46 +08:00
										 |  |  |       [this] { onPivotChange(); }); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     onPivotChange(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2015-08-29 02:41:02 +08:00
										 |  |  |   void onItemChange(Item* item) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ButtonSet::onItemChange(item); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-07 04:00:27 +08:00
										 |  |  |     auto* theme = SkinTheme::get(this); | 
					
						
							| 
									
										
										
											
												Refactor several "getNoun()" getters to "noun()"
This is a work-in-progress to create a consistent API and finally
separate the whole Aseprite base/gfx/ui libs into a reusable C++ library.
Classes:
app::IFileItem, app::AppMenuItem, app::skin::SkinPart,
gfx::Rect, gfx::Border, she::FileDialog,
ui::IButtonIcon, ui::Graphics, ui::Overlay, ui::Widget,
ui::ScrollableViewDelegate, and UI events
											
										 
											2015-12-05 01:39:04 +08:00
										 |  |  |     gfx::Rect bounds = this->bounds(); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Menu menu; | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     CheckBox visible(Strings::context_bar_default_display_pivot()); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  |     HBox box; | 
					
						
							|  |  |  |     ButtonSet buttonset(3); | 
					
						
							| 
									
										
										
										
											2024-05-07 04:00:27 +08:00
										 |  |  |     buttonset.addItem(theme->parts.pivotNorthwest(), theme->styles.pivotDir()); | 
					
						
							|  |  |  |     buttonset.addItem(theme->parts.pivotNorth(), theme->styles.pivotDir()); | 
					
						
							|  |  |  |     buttonset.addItem(theme->parts.pivotNortheast(), theme->styles.pivotDir()); | 
					
						
							|  |  |  |     buttonset.addItem(theme->parts.pivotWest(), theme->styles.pivotDir()); | 
					
						
							|  |  |  |     buttonset.addItem(theme->parts.pivotCenter(), theme->styles.pivotDir()); | 
					
						
							|  |  |  |     buttonset.addItem(theme->parts.pivotEast(), theme->styles.pivotDir()); | 
					
						
							|  |  |  |     buttonset.addItem(theme->parts.pivotSouthwest(), theme->styles.pivotDir()); | 
					
						
							|  |  |  |     buttonset.addItem(theme->parts.pivotSouth(), theme->styles.pivotDir()); | 
					
						
							|  |  |  |     buttonset.addItem(theme->parts.pivotSoutheast(), theme->styles.pivotDir()); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  |     box.addChild(&buttonset); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-14 21:09:15 +08:00
										 |  |  |     menu.addChild(&visible); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  |     menu.addChild(new MenuSeparator); | 
					
						
							|  |  |  |     menu.addChild(&box); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-14 21:09:15 +08:00
										 |  |  |     bool isVisible = Preferences::instance().selection.pivotVisibility(); | 
					
						
							|  |  |  |     app::gen::PivotPosition pos = Preferences::instance().selection.pivotPosition(); | 
					
						
							|  |  |  |     visible.setSelected(isVisible); | 
					
						
							|  |  |  |     buttonset.setSelectedItem(int(pos)); | 
					
						
							| 
									
										
										
										
											2022-12-17 04:59:08 +08:00
										 |  |  |     buttonset.initTheme(); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-14 21:09:15 +08:00
										 |  |  |     visible.Click.connect( | 
					
						
							|  |  |  |       [&visible]() { Preferences::instance().selection.pivotVisibility(visible.isSelected()); }); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-29 02:41:02 +08:00
										 |  |  |     buttonset.ItemChange.connect([&buttonset](ButtonSet::Item* item) { | 
					
						
							| 
									
										
										
										
											2015-08-14 21:09:15 +08:00
										 |  |  |       Preferences::instance().selection.pivotPosition( | 
					
						
							|  |  |  |         app::gen::PivotPosition(buttonset.selectedItem())); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-20 05:57:56 +08:00
										 |  |  |     menu.showPopup(gfx::Point(bounds.x, bounds.y2()), display()); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void onPivotChange() | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2022-02-19 06:01:46 +08:00
										 |  |  |     auto theme = SkinTheme::get(this); | 
					
						
							| 
									
										
										
										
											2015-08-05 06:38:52 +08:00
										 |  |  |     SkinPartPtr part; | 
					
						
							| 
									
										
										
										
											2015-08-14 21:09:15 +08:00
										 |  |  |     switch (Preferences::instance().selection.pivotPosition()) { | 
					
						
							|  |  |  |       case app::gen::PivotPosition::NORTHWEST: part = theme->parts.pivotNorthwest(); break; | 
					
						
							|  |  |  |       case app::gen::PivotPosition::NORTH:     part = theme->parts.pivotNorth(); break; | 
					
						
							|  |  |  |       case app::gen::PivotPosition::NORTHEAST: part = theme->parts.pivotNortheast(); break; | 
					
						
							|  |  |  |       case app::gen::PivotPosition::WEST:      part = theme->parts.pivotWest(); break; | 
					
						
							|  |  |  |       case app::gen::PivotPosition::CENTER:    part = theme->parts.pivotCenter(); break; | 
					
						
							|  |  |  |       case app::gen::PivotPosition::EAST:      part = theme->parts.pivotEast(); break; | 
					
						
							|  |  |  |       case app::gen::PivotPosition::SOUTHWEST: part = theme->parts.pivotSouthwest(); break; | 
					
						
							|  |  |  |       case app::gen::PivotPosition::SOUTH:     part = theme->parts.pivotSouth(); break; | 
					
						
							|  |  |  |       case app::gen::PivotPosition::SOUTHEAST: part = theme->parts.pivotSoutheast(); break; | 
					
						
							| 
									
										
										
										
											2015-08-05 06:38:52 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (part) | 
					
						
							|  |  |  |       getItem(0)->setIcon(part); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 03:24:36 +08:00
										 |  |  |   obs::scoped_connection m_pivotConn; | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ContextBar::RotAlgorithmField : public ComboBox { | 
					
						
							| 
									
										
										
										
											2013-12-30 04:11:56 +08:00
										 |  |  | public: | 
					
						
							|  |  |  |   RotAlgorithmField() | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2014-06-14 12:35:04 +08:00
										 |  |  |     // We use "m_lockChange" variable to avoid setting the rotation
 | 
					
						
							|  |  |  |     // algorithm when we call ComboBox::addItem() (because the first
 | 
					
						
							|  |  |  |     // addItem() generates an onChange() event).
 | 
					
						
							|  |  |  |     m_lockChange = true; | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     addItem(new Item(Strings::context_bar_fast_rotation(), tools::RotationAlgorithm::FAST)); | 
					
						
							|  |  |  |     addItem(new Item(Strings::context_bar_rotsprite(), tools::RotationAlgorithm::ROTSPRITE)); | 
					
						
							| 
									
										
										
										
											2014-06-14 12:35:04 +08:00
										 |  |  |     m_lockChange = false; | 
					
						
							| 
									
										
										
										
											2013-12-30 04:11:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     setSelectedItemIndex((int)Preferences::instance().selection.rotationAlgorithm()); | 
					
						
							| 
									
										
										
										
											2013-12-30 04:11:56 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							| 
									
										
										
										
											2014-08-15 10:07:47 +08:00
										 |  |  |   void onChange() override | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2014-06-14 12:35:04 +08:00
										 |  |  |     if (m_lockChange) | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     Preferences::instance().selection.rotationAlgorithm( | 
					
						
							|  |  |  |       static_cast<Item*>(getSelectedItem())->algo()); | 
					
						
							| 
									
										
										
										
											2013-12-30 04:11:56 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-15 10:07:47 +08:00
										 |  |  |   void onCloseListBox() override { releaseFocus(); } | 
					
						
							| 
									
										
										
										
											2014-03-09 07:31:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-30 04:11:56 +08:00
										 |  |  | private: | 
					
						
							|  |  |  |   class Item : public ListItem { | 
					
						
							|  |  |  |   public: | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     Item(const std::string& text, tools::RotationAlgorithm algo) : ListItem(text), m_algo(algo) {} | 
					
						
							| 
									
										
										
										
											2013-12-30 04:11:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     tools::RotationAlgorithm algo() const { return m_algo; } | 
					
						
							| 
									
										
										
										
											2013-12-30 04:11:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   private: | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     tools::RotationAlgorithm m_algo; | 
					
						
							| 
									
										
										
										
											2013-12-30 04:11:56 +08:00
										 |  |  |   }; | 
					
						
							| 
									
										
										
										
											2014-06-14 12:35:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   bool m_lockChange; | 
					
						
							| 
									
										
										
										
											2013-12-30 04:11:56 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  | class ContextBar::TransformationFields : public HBox { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |   class CustomEntry : public ExprEntry { | 
					
						
							|  |  |  |   public: | 
					
						
							|  |  |  |     CustomEntry() { setDecimals(1); } | 
					
						
							| 
									
										
										
										
											2024-12-17 01:52:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  |   private: | 
					
						
							|  |  |  |     bool onProcessMessage(Message* msg) override | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       switch (msg->type()) { | 
					
						
							|  |  |  |         case kKeyDownMessage: | 
					
						
							|  |  |  |           if (ExprEntry::onProcessMessage(msg)) | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |           else if (hasFocus() && manager()->processFocusMovementMessage(msg)) | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |           return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case kFocusLeaveMessage: { | 
					
						
							|  |  |  |           bool res = ExprEntry::onProcessMessage(msg); | 
					
						
							|  |  |  |           deselectText(); | 
					
						
							|  |  |  |           setCaretPos(0); | 
					
						
							|  |  |  |           return res; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return ExprEntry::onProcessMessage(msg); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     void onVisible(bool visible) override | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (!visible && hasFocus()) { | 
					
						
							|  |  |  |         releaseFocus(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       ExprEntry::onVisible(visible); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     void onFormatExprFocusLeave(std::string& buf) override { buf = formatDec(onGetTextDouble()); } | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   TransformationFields() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_angle.setSuffix("°"); | 
					
						
							|  |  |  |     m_skew.setSuffix("°"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-07 00:21:10 +08:00
										 |  |  |     addChild(new Label(Strings::context_bar_position_label())); | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  |     addChild(&m_x); | 
					
						
							|  |  |  |     addChild(&m_y); | 
					
						
							|  |  |  |     addChild(&m_w); | 
					
						
							|  |  |  |     addChild(&m_h); | 
					
						
							| 
									
										
										
										
											2025-08-07 00:21:10 +08:00
										 |  |  |     addChild(new Label(Strings::context_bar_rotation_label())); | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  |     addChild(&m_angle); | 
					
						
							|  |  |  |     addChild(&m_skew); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     InitTheme.connect([this] { | 
					
						
							|  |  |  |       gfx::Size sz(font()->textLength("8") * 4 + m_x.border().width(), | 
					
						
							|  |  |  |                    std::numeric_limits<int>::max()); | 
					
						
							|  |  |  |       setChildSpacing(0); | 
					
						
							|  |  |  |       m_x.setMaxSize(sz); | 
					
						
							|  |  |  |       m_y.setMaxSize(sz); | 
					
						
							|  |  |  |       m_w.setMaxSize(sz); | 
					
						
							|  |  |  |       m_h.setMaxSize(sz); | 
					
						
							|  |  |  |       m_angle.setMaxSize(sz); | 
					
						
							|  |  |  |       m_skew.setMaxSize(sz); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     initTheme(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_x.Change.connect([this] { | 
					
						
							|  |  |  |       auto rc = bounds(); | 
					
						
							|  |  |  |       rc.x = m_x.textDouble(); | 
					
						
							|  |  |  |       onChangePos(rc); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     m_y.Change.connect([this] { | 
					
						
							|  |  |  |       auto rc = bounds(); | 
					
						
							|  |  |  |       rc.y = m_y.textDouble(); | 
					
						
							|  |  |  |       onChangePos(rc); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     m_w.Change.connect([this] { | 
					
						
							|  |  |  |       auto rc = bounds(); | 
					
						
							|  |  |  |       rc.w = m_w.textDouble(); | 
					
						
							|  |  |  |       onChangeSize(rc); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     m_h.Change.connect([this] { | 
					
						
							|  |  |  |       auto rc = bounds(); | 
					
						
							|  |  |  |       rc.h = m_h.textDouble(); | 
					
						
							|  |  |  |       onChangeSize(rc); | 
					
						
							| 
									
										
										
										
											2024-12-17 01:52:19 +08:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  |     m_angle.Change.connect([this] { onChangeAngle(); }); | 
					
						
							|  |  |  |     m_skew.Change.connect([this] { onChangeSkew(); }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-07 00:21:10 +08:00
										 |  |  |   void setupTooltips(TooltipManager* tooltipManager) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     tooltipManager->addTooltipFor(&m_x, Strings::context_bar_position_x(), BOTTOM); | 
					
						
							|  |  |  |     tooltipManager->addTooltipFor(&m_y, Strings::context_bar_position_y(), BOTTOM); | 
					
						
							|  |  |  |     tooltipManager->addTooltipFor(&m_w, Strings::context_bar_size_width(), BOTTOM); | 
					
						
							|  |  |  |     tooltipManager->addTooltipFor(&m_h, Strings::context_bar_size_height(), BOTTOM); | 
					
						
							|  |  |  |     tooltipManager->addTooltipFor(&m_angle, Strings::context_bar_rotation_angle(), BOTTOM); | 
					
						
							|  |  |  |     tooltipManager->addTooltipFor(&m_skew, Strings::context_bar_rotation_skew(), BOTTOM); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  |   void update(const Transformation& t) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     auto rc = t.bounds(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_x.setText(formatDec(rc.x)); | 
					
						
							|  |  |  |     m_y.setText(formatDec(rc.y)); | 
					
						
							|  |  |  |     m_w.setText(formatDec(rc.w)); | 
					
						
							|  |  |  |     m_h.setText(formatDec(rc.h)); | 
					
						
							|  |  |  |     m_angle.setText(formatDec(180.0 * t.angle() / PI)); | 
					
						
							|  |  |  |     m_skew.setText(formatDec(180.0 * t.skew() / PI)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_t = t; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |   static std::string formatDec(const double x) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     std::string s = fmt::format("{:0.1f}", x); | 
					
						
							|  |  |  |     if (s.size() > 2 && s[s.size() - 1] == '0' && s[s.size() - 2] == '.') { | 
					
						
							|  |  |  |       s.erase(s.size() - 2, 2); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return s; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   gfx::RectF bounds() const { return m_t.bounds(); } | 
					
						
							|  |  |  |   void onChangePos(gfx::RectF newBounds) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // Adjust new pivot position depending on the new bounds origin
 | 
					
						
							|  |  |  |     gfx::RectF bounds = m_t.bounds(); | 
					
						
							|  |  |  |     gfx::PointF pivot = m_t.pivot(); | 
					
						
							|  |  |  |     if (!bounds.isEmpty()) { | 
					
						
							|  |  |  |       pivot.x = (pivot.x - bounds.x) / bounds.w; | 
					
						
							|  |  |  |       pivot.y = (pivot.y - bounds.y) / bounds.h; | 
					
						
							|  |  |  |       pivot.x = newBounds.x + pivot.x * newBounds.w; | 
					
						
							|  |  |  |       pivot.y = newBounds.y + pivot.y * newBounds.h; | 
					
						
							|  |  |  |       m_t.pivot(pivot); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     m_t.bounds(newBounds); | 
					
						
							|  |  |  |     updateEditor(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   void onChangeSize(gfx::RectF newBounds) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // Adjust bounds origin depending on the new size and the current pivot
 | 
					
						
							|  |  |  |     gfx::RectF bounds = m_t.bounds(); | 
					
						
							|  |  |  |     gfx::PointF pivot = m_t.pivot(); | 
					
						
							|  |  |  |     if (!bounds.isEmpty()) { | 
					
						
							|  |  |  |       pivot.x = (pivot.x - bounds.x) / bounds.w; | 
					
						
							|  |  |  |       pivot.y = (pivot.y - bounds.y) / bounds.h; | 
					
						
							|  |  |  |       newBounds.x -= (newBounds.w - bounds.w) * pivot.x; | 
					
						
							|  |  |  |       newBounds.y -= (newBounds.h - bounds.h) * pivot.y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       m_x.setText(formatDec(newBounds.x)); | 
					
						
							|  |  |  |       m_y.setText(formatDec(newBounds.y)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     m_t.bounds(newBounds); | 
					
						
							|  |  |  |     updateEditor(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   void onChangeAngle() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_t.angle(PI * m_angle.textDouble() / 180.0); | 
					
						
							|  |  |  |     updateEditor(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   void onChangeSkew() | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2020-09-24 06:43:35 +08:00
										 |  |  |     double newSkew = PI * m_skew.textDouble() / 180.0; | 
					
						
							| 
									
										
										
										
											2022-06-10 21:31:13 +08:00
										 |  |  |     newSkew = std::clamp(newSkew, -PI * 85.0 / 180.0, PI * 85.0 / 180.0); | 
					
						
							| 
									
										
										
										
											2020-09-24 06:43:35 +08:00
										 |  |  |     m_t.skew(newSkew); | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  |     updateEditor(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   void updateEditor() | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2022-10-20 23:31:22 +08:00
										 |  |  |     if (auto editor = Editor::activeEditor()) | 
					
						
							|  |  |  |       editor->updateTransformation(m_t); | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   CustomEntry m_x, m_y, m_w, m_h; | 
					
						
							|  |  |  |   CustomEntry m_angle; | 
					
						
							|  |  |  |   CustomEntry m_skew; | 
					
						
							|  |  |  |   Transformation m_t; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  | class ContextBar::DynamicsField : public ButtonSet, | 
					
						
							|  |  |  |                                   public DynamicsPopup::Delegate { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2023-11-30 22:02:52 +08:00
										 |  |  |   DynamicsField(ContextBar* ctxBar) : ButtonSet(1), m_ctxBar(ctxBar) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2024-05-07 04:00:27 +08:00
										 |  |  |     auto* theme = SkinTheme::get(this); | 
					
						
							|  |  |  |     addItem(theme->parts.dynamics(), theme->styles.dynamicsField()); | 
					
						
							| 
									
										
										
										
											2023-08-10 03:18:23 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-09 04:26:58 +08:00
										 |  |  |     loadDynamicsPref(); | 
					
						
							| 
									
										
										
										
											2023-12-01 08:24:48 +08:00
										 |  |  |     initTheme(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void updateIconFromActiveToolPref() { initTheme(); } | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 00:38:12 +08:00
										 |  |  |   void switchPopup() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (m_popup && m_popup->isVisible()) { | 
					
						
							|  |  |  |       m_popup->closeWindow(nullptr); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-09 04:26:58 +08:00
										 |  |  |     if (!m_popup.get()) | 
					
						
							|  |  |  |       m_popup.reset(new DynamicsPopup(this)); | 
					
						
							|  |  |  |     m_sameInAllTools = m_popup->sharedSettings(); | 
					
						
							| 
									
										
										
										
											2023-08-31 00:11:34 +08:00
										 |  |  |     m_popup->loadDynamicsPref(m_sameInAllTools); | 
					
						
							|  |  |  |     m_dynamics = m_popup->getDynamics(); | 
					
						
							| 
									
										
										
										
											2023-08-09 04:26:58 +08:00
										 |  |  |     m_popup->Close.connect([this](CloseEvent&) { | 
					
						
							|  |  |  |       deselectItems(); | 
					
						
							| 
									
										
										
										
											2023-08-31 00:11:34 +08:00
										 |  |  |       saveDynamicsPref(); | 
					
						
							| 
									
										
										
										
											2023-08-09 04:26:58 +08:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_popup->refreshVisibility(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  |     const gfx::Rect bounds = this->bounds(); | 
					
						
							| 
									
										
										
										
											2020-04-24 23:04:36 +08:00
										 |  |  |     m_popup->remapWindow(); | 
					
						
							| 
									
										
										
										
											2021-03-20 05:57:56 +08:00
										 |  |  |     fit_bounds(display(), | 
					
						
							|  |  |  |                m_popup.get(), | 
					
						
							|  |  |  |                gfx::Rect(gfx::Point(bounds.x, bounds.y2()), m_popup->sizeHint())); | 
					
						
							| 
									
										
										
										
											2021-03-22 22:56:02 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  |     m_popup->openWindow(); | 
					
						
							| 
									
										
										
										
											2021-03-22 22:56:02 +08:00
										 |  |  |     m_popup->setHotRegion(gfx::Region(m_popup->boundsOnScreen())); | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-21 01:50:52 +08:00
										 |  |  |   const tools::DynamicsOptions& getDynamics() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (m_popup && m_popup->isVisible()) { | 
					
						
							| 
									
										
										
										
											2020-06-05 03:15:57 +08:00
										 |  |  |       m_dynamics = m_popup->getDynamics(); | 
					
						
							| 
									
										
										
										
											2023-11-21 01:50:52 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       // Load dynamics just in case that the active tool has changed.
 | 
					
						
							| 
									
										
										
										
											2023-11-28 23:47:24 +08:00
										 |  |  |       //
 | 
					
						
							|  |  |  |       // TODO cache the loaded dynamics per tool until the preferences
 | 
					
						
							|  |  |  |       //      changes (listen pref changes)
 | 
					
						
							| 
									
										
										
										
											2023-11-21 01:50:52 +08:00
										 |  |  |       loadDynamicsPref(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-06-05 03:15:57 +08:00
										 |  |  |     return m_dynamics; | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-11 23:07:28 +08:00
										 |  |  |   void setOptionsGridVisibility(bool state) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (m_popup) | 
					
						
							|  |  |  |       m_popup->setOptionsGridVisibility(state); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-31 00:11:34 +08:00
										 |  |  |   void saveDynamicsPref() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_sameInAllTools = m_popup->sharedSettings(); | 
					
						
							|  |  |  |     Preferences::instance().shared.shareDynamics(m_sameInAllTools); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-01 08:24:48 +08:00
										 |  |  |     auto& dynaPref = Preferences::instance().tool(getTool()).dynamics; | 
					
						
							| 
									
										
										
										
											2023-08-31 00:11:34 +08:00
										 |  |  |     m_dynamics = m_popup->getDynamics(); | 
					
						
							| 
									
										
										
										
											2023-08-09 04:26:58 +08:00
										 |  |  |     dynaPref.stabilizer(m_dynamics.stabilizer); | 
					
						
							|  |  |  |     dynaPref.stabilizerFactor(m_dynamics.stabilizerFactor); | 
					
						
							|  |  |  |     dynaPref.size(m_dynamics.size); | 
					
						
							|  |  |  |     dynaPref.angle(m_dynamics.angle); | 
					
						
							|  |  |  |     dynaPref.gradient(m_dynamics.gradient); | 
					
						
							|  |  |  |     dynaPref.minSize.setValue(m_dynamics.minSize); | 
					
						
							|  |  |  |     dynaPref.minAngle.setValue(m_dynamics.minAngle); | 
					
						
							|  |  |  |     dynaPref.minPressureThreshold(m_dynamics.minPressureThreshold); | 
					
						
							|  |  |  |     dynaPref.minVelocityThreshold(m_dynamics.minVelocityThreshold); | 
					
						
							|  |  |  |     dynaPref.maxPressureThreshold(m_dynamics.maxPressureThreshold); | 
					
						
							|  |  |  |     dynaPref.maxVelocityThreshold(m_dynamics.maxVelocityThreshold); | 
					
						
							|  |  |  |     dynaPref.colorFromTo(m_dynamics.colorFromTo); | 
					
						
							| 
									
										
										
										
											2023-08-31 00:11:34 +08:00
										 |  |  |     dynaPref.matrixName(m_popup->ditheringMatrixName()); | 
					
						
							| 
									
										
										
										
											2023-12-01 08:24:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     initTheme(); | 
					
						
							| 
									
										
										
										
											2023-08-09 04:26:58 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void loadDynamicsPref() | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2023-08-31 00:11:34 +08:00
										 |  |  |     m_sameInAllTools = Preferences::instance().shared.shareDynamics(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-01 08:24:48 +08:00
										 |  |  |     auto& dynaPref = Preferences::instance().tool(getTool()).dynamics; | 
					
						
							| 
									
										
										
										
											2023-08-09 04:26:58 +08:00
										 |  |  |     m_dynamics.stabilizer = dynaPref.stabilizer(); | 
					
						
							|  |  |  |     m_dynamics.stabilizerFactor = dynaPref.stabilizerFactor(); | 
					
						
							|  |  |  |     m_dynamics.size = dynaPref.size(); | 
					
						
							|  |  |  |     m_dynamics.angle = dynaPref.angle(); | 
					
						
							|  |  |  |     m_dynamics.gradient = dynaPref.gradient(); | 
					
						
							|  |  |  |     m_dynamics.minSize = dynaPref.minSize(); | 
					
						
							|  |  |  |     m_dynamics.minAngle = dynaPref.minAngle(); | 
					
						
							|  |  |  |     m_dynamics.minPressureThreshold = dynaPref.minPressureThreshold(); | 
					
						
							|  |  |  |     m_dynamics.minVelocityThreshold = dynaPref.minVelocityThreshold(); | 
					
						
							|  |  |  |     m_dynamics.maxPressureThreshold = dynaPref.maxPressureThreshold(); | 
					
						
							|  |  |  |     m_dynamics.maxVelocityThreshold = dynaPref.maxVelocityThreshold(); | 
					
						
							|  |  |  |     m_dynamics.colorFromTo = dynaPref.colorFromTo(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 22:02:52 +08:00
										 |  |  |     // Get the dithering matrix by name from the extensions.
 | 
					
						
							|  |  |  |     bool found = false; | 
					
						
							|  |  |  |     auto ditheringMatrices = App::instance()->extensions().ditheringMatrices(); | 
					
						
							| 
									
										
										
										
											2024-08-22 06:49:55 +08:00
										 |  |  |     for (const auto* it : ditheringMatrices) { | 
					
						
							|  |  |  |       if (it->name() == dynaPref.matrixName()) { | 
					
						
							|  |  |  |         m_dynamics.ditheringMatrix = it->matrix(); | 
					
						
							| 
									
										
										
										
											2023-11-30 22:02:52 +08:00
										 |  |  |         found = true; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (!found) | 
					
						
							|  |  |  |       m_dynamics.ditheringMatrix = render::DitheringMatrix(); | 
					
						
							| 
									
										
										
										
											2023-08-09 04:26:58 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  | private: | 
					
						
							|  |  |  |   // DynamicsPopup::Delegate impl
 | 
					
						
							|  |  |  |   doc::BrushRef getActiveBrush() override { return m_ctxBar->activeBrush(); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-02 22:59:34 +08:00
										 |  |  |   void setMaxSize(int size) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     Tool* tool = App::instance()->activeTool(); | 
					
						
							|  |  |  |     Preferences::instance().tool(tool).brush.size(size); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void setMaxAngle(int angle) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     Tool* tool = App::instance()->activeTool(); | 
					
						
							|  |  |  |     Preferences::instance().tool(tool).brush.angle(angle); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-01 08:24:48 +08:00
										 |  |  |   void onDynamicsChange(const tools::DynamicsOptions& dynamicsOptions) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     updateIcon(dynamicsOptions.size != tools::DynamicSensor::Static || | 
					
						
							|  |  |  |                dynamicsOptions.angle != tools::DynamicSensor::Static || | 
					
						
							|  |  |  |                dynamicsOptions.gradient != tools::DynamicSensor::Static); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-05 03:15:57 +08:00
										 |  |  |   // ButtonSet overrides
 | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  |   void onItemChange(Item* item) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ButtonSet::onItemChange(item); | 
					
						
							| 
									
										
										
										
											2020-05-02 00:38:12 +08:00
										 |  |  |     switchPopup(); | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-05 03:15:57 +08:00
										 |  |  |   // Widget overrides
 | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  |   void onInitTheme(InitThemeEvent& ev) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ButtonSet::onInitTheme(ev); | 
					
						
							| 
									
										
										
										
											2023-12-01 08:24:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     auto& dynaPref = Preferences::instance().tool(getTool()).dynamics; | 
					
						
							|  |  |  |     updateIcon(dynaPref.size() != tools::DynamicSensor::Static || | 
					
						
							|  |  |  |                dynaPref.angle() != tools::DynamicSensor::Static || | 
					
						
							|  |  |  |                dynaPref.gradient() != tools::DynamicSensor::Static); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  |     if (m_popup) | 
					
						
							|  |  |  |       m_popup->initTheme(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-01 08:24:48 +08:00
										 |  |  |   tools::Tool* getTool() const | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (m_sameInAllTools) | 
					
						
							|  |  |  |       return nullptr; // For shared dynamic options we use tool=nullptr
 | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       return App::instance()->activeTool(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void updateIcon(const bool dynamicsOn) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     auto theme = SkinTheme::get(this); | 
					
						
							|  |  |  |     getItem(0)->setIcon(dynamicsOn ? theme->parts.dynamicsOn() : theme->parts.dynamics()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  |   std::unique_ptr<DynamicsPopup> m_popup; | 
					
						
							|  |  |  |   ContextBar* m_ctxBar; | 
					
						
							| 
									
										
										
										
											2020-06-05 03:15:57 +08:00
										 |  |  |   mutable tools::DynamicsOptions m_dynamics; | 
					
						
							| 
									
										
										
										
											2023-08-09 04:26:58 +08:00
										 |  |  |   bool m_sameInAllTools = false; | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  | class ContextBar::FreehandAlgorithmField : public CheckBox { | 
					
						
							| 
									
										
										
										
											2014-07-17 20:54:04 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |   FreehandAlgorithmField() : CheckBox(Strings::context_bar_pixel_perfect()) { initTheme(); } | 
					
						
							| 
									
										
										
										
											2014-07-17 20:54:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |   void setFreehandAlgorithm(tools::FreehandAlgorithm algo) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2014-07-17 20:54:04 +08:00
										 |  |  |     switch (algo) { | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |       case tools::FreehandAlgorithm::DEFAULT:       setSelected(false); break; | 
					
						
							|  |  |  |       case tools::FreehandAlgorithm::PIXEL_PERFECT: setSelected(true); break; | 
					
						
							|  |  |  |       case tools::FreehandAlgorithm::DOTS: | 
					
						
							| 
									
										
										
										
											2014-07-17 20:54:04 +08:00
										 |  |  |         // Not available
 | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  |   void onInitTheme(InitThemeEvent& ev) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     CheckBox::onInitTheme(ev); | 
					
						
							| 
									
										
										
										
											2022-02-19 06:01:46 +08:00
										 |  |  |     setStyle(SkinTheme::get(this)->styles.miniCheckBox()); | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-12 22:00:16 +08:00
										 |  |  |   void onClick() override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     CheckBox::onClick(); | 
					
						
							| 
									
										
										
										
											2014-07-17 20:54:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     Tool* tool = App::instance()->activeTool(); | 
					
						
							|  |  |  |     Preferences::instance().tool(tool).freehandAlgorithm( | 
					
						
							|  |  |  |       isSelected() ? tools::FreehandAlgorithm::PIXEL_PERFECT : tools::FreehandAlgorithm::DEFAULT); | 
					
						
							| 
									
										
										
										
											2014-07-17 20:54:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     releaseFocus(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-27 03:08:31 +08:00
										 |  |  | class ContextBar::SelectionModeField : public app::SelectionModeField { | 
					
						
							| 
									
										
										
										
											2014-01-26 04:58:29 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2018-10-27 03:08:31 +08:00
										 |  |  |   SelectionModeField() {} | 
					
						
							| 
									
										
										
										
											2024-12-17 01:52:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-26 04:58:29 +08:00
										 |  |  | protected: | 
					
						
							| 
									
										
										
										
											2018-10-27 03:08:31 +08:00
										 |  |  |   void onSelectionModeChange(gen::SelectionMode mode) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     Preferences::instance().selection.mode(mode); | 
					
						
							| 
									
										
										
										
											2014-01-26 04:58:29 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 07:54:25 +08:00
										 |  |  | class ContextBar::GradientTypeField : public ButtonSet { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |   GradientTypeField() : ButtonSet(2) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2024-05-07 04:00:27 +08:00
										 |  |  |     auto* theme = SkinTheme::get(this); | 
					
						
							| 
									
										
										
										
											2019-03-20 07:54:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-07 04:00:27 +08:00
										 |  |  |     addItem(theme->parts.linearGradient(), theme->styles.contextBarButton()); | 
					
						
							|  |  |  |     addItem(theme->parts.radialGradient(), theme->styles.contextBarButton()); | 
					
						
							| 
									
										
										
										
											2019-03-20 07:54:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     setSelectedItem(0); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void setupTooltips(TooltipManager* tooltipManager) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     tooltipManager->addTooltipFor(at(0), Strings::context_bar_linear_gradient(), BOTTOM); | 
					
						
							|  |  |  |     tooltipManager->addTooltipFor(at(1), Strings::context_bar_radial_gradient(), BOTTOM); | 
					
						
							| 
									
										
										
										
											2019-03-20 07:54:25 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   render::GradientType gradientType() const { return (render::GradientType)selectedItem(); } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  | class ContextBar::DropPixelsField : public ButtonSet { | 
					
						
							| 
									
										
										
										
											2014-05-26 11:20:16 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2014-09-08 13:27:41 +08:00
										 |  |  |   DropPixelsField() : ButtonSet(2) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2024-05-07 04:00:27 +08:00
										 |  |  |     auto* theme = SkinTheme::get(this); | 
					
						
							| 
									
										
										
										
											2014-09-08 13:27:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-07 04:00:27 +08:00
										 |  |  |     addItem(theme->parts.dropPixelsOk(), theme->styles.contextBarButton()); | 
					
						
							|  |  |  |     addItem(theme->parts.dropPixelsCancel(), theme->styles.contextBarButton()); | 
					
						
							| 
									
										
										
										
											2014-09-08 13:27:41 +08:00
										 |  |  |     setOfferCapture(false); | 
					
						
							| 
									
										
										
										
											2014-05-26 11:20:16 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void setupTooltips(TooltipManager* tooltipManager) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2017-06-23 20:02:59 +08:00
										 |  |  |     // TODO Enter and Esc should be configurable keys
 | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     tooltipManager->addTooltipFor(at(0), Strings::context_bar_drop_pixel(), BOTTOM); | 
					
						
							|  |  |  |     tooltipManager->addTooltipFor(at(1), Strings::context_bar_cancel_drag(), BOTTOM); | 
					
						
							| 
									
										
										
										
											2014-05-26 11:20:16 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-14 02:02:00 +08:00
										 |  |  |   obs::signal<void(ContextBarObserver::DropAction)> DropPixels; | 
					
						
							| 
									
										
										
										
											2014-05-26 11:20:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							| 
									
										
										
										
											2015-08-29 02:41:02 +08:00
										 |  |  |   void onItemChange(Item* item) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ButtonSet::onItemChange(item); | 
					
						
							| 
									
										
										
										
											2014-05-26 11:20:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-08 13:27:41 +08:00
										 |  |  |     switch (selectedItem()) { | 
					
						
							| 
									
										
										
										
											2014-05-26 11:20:16 +08:00
										 |  |  |       case 0: DropPixels(ContextBarObserver::DropPixels); break; | 
					
						
							|  |  |  |       case 1: DropPixels(ContextBarObserver::CancelDrag); break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  | class ContextBar::EyedropperField : public HBox { | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2015-07-03 05:13:47 +08:00
										 |  |  |   EyedropperField() | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2024-06-21 07:14:29 +08:00
										 |  |  |     m_channel.addItem( | 
					
						
							|  |  |  |       Strings::context_bar_eyedropper_combined(Strings::context_bar_eyedropper_color(), | 
					
						
							| 
									
										
										
										
											2023-12-23 02:03:07 +08:00
										 |  |  |                                                Strings::context_bar_eyedropper_alpha())); | 
					
						
							|  |  |  |     m_channel.addItem(Strings::context_bar_eyedropper_color()); | 
					
						
							|  |  |  |     m_channel.addItem(Strings::context_bar_eyedropper_alpha()); | 
					
						
							| 
									
										
										
										
											2024-06-21 07:14:29 +08:00
										 |  |  |     m_channel.addItem( | 
					
						
							|  |  |  |       Strings::context_bar_eyedropper_combined(Strings::context_bar_eyedropper_rgb(), | 
					
						
							| 
									
										
										
										
											2023-12-23 02:03:07 +08:00
										 |  |  |                                                Strings::context_bar_eyedropper_alpha())); | 
					
						
							|  |  |  |     m_channel.addItem(Strings::context_bar_eyedropper_rgb()); | 
					
						
							| 
									
										
										
										
											2024-06-21 07:14:29 +08:00
										 |  |  |     m_channel.addItem( | 
					
						
							|  |  |  |       Strings::context_bar_eyedropper_combined(Strings::context_bar_eyedropper_hsv(), | 
					
						
							| 
									
										
										
										
											2023-12-23 02:03:07 +08:00
										 |  |  |                                                Strings::context_bar_eyedropper_alpha())); | 
					
						
							|  |  |  |     m_channel.addItem(Strings::context_bar_eyedropper_hsv()); | 
					
						
							| 
									
										
										
										
											2024-06-21 07:14:29 +08:00
										 |  |  |     m_channel.addItem( | 
					
						
							|  |  |  |       Strings::context_bar_eyedropper_combined(Strings::context_bar_eyedropper_hsl(), | 
					
						
							| 
									
										
										
										
											2023-12-23 02:03:07 +08:00
										 |  |  |                                                Strings::context_bar_eyedropper_alpha())); | 
					
						
							|  |  |  |     m_channel.addItem(Strings::context_bar_eyedropper_hsl()); | 
					
						
							| 
									
										
										
										
											2024-06-21 07:14:29 +08:00
										 |  |  |     m_channel.addItem( | 
					
						
							|  |  |  |       Strings::context_bar_eyedropper_combined(Strings::context_bar_eyedropper_gray(), | 
					
						
							| 
									
										
										
										
											2023-12-23 02:03:07 +08:00
										 |  |  |                                                Strings::context_bar_eyedropper_alpha())); | 
					
						
							|  |  |  |     m_channel.addItem(Strings::context_bar_eyedropper_gray()); | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     m_channel.addItem(Strings::context_bar_best_fit_index()); | 
					
						
							| 
									
										
										
										
											2015-07-03 05:13:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     m_sample.addItem(Strings::context_bar_all_layers()); | 
					
						
							|  |  |  |     m_sample.addItem(Strings::context_bar_current_layer()); | 
					
						
							|  |  |  |     m_sample.addItem(Strings::context_bar_first_ref_layer()); | 
					
						
							| 
									
										
										
										
											2015-07-03 05:13:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     addChild(new Label(Strings::context_bar_pick())); | 
					
						
							| 
									
										
										
										
											2015-07-03 05:13:47 +08:00
										 |  |  |     addChild(&m_channel); | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     addChild(new Label(Strings::context_bar_sample())); | 
					
						
							| 
									
										
										
										
											2015-07-03 05:13:47 +08:00
										 |  |  |     addChild(&m_sample); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-04 08:51:46 +08:00
										 |  |  |     m_channel.Change.connect([this] { onChannelChange(); }); | 
					
						
							|  |  |  |     m_sample.Change.connect([this] { onSampleChange(); }); | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-03 05:13:47 +08:00
										 |  |  |   void updateFromPreferences(app::Preferences::Eyedropper& prefEyedropper) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_channel.setSelectedItemIndex((int)prefEyedropper.channel()); | 
					
						
							|  |  |  |     m_sample.setSelectedItemIndex((int)prefEyedropper.sample()); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-03 05:13:47 +08:00
										 |  |  | private: | 
					
						
							|  |  |  |   void onChannelChange() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     Preferences::instance().eyedropper.channel( | 
					
						
							|  |  |  |       (app::gen::EyedropperChannel)m_channel.getSelectedItemIndex()); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-03-09 07:31:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-03 05:13:47 +08:00
										 |  |  |   void onSampleChange() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     Preferences::instance().eyedropper.sample( | 
					
						
							|  |  |  |       (app::gen::EyedropperSample)m_sample.getSelectedItemIndex()); | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-07-03 05:13:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ComboBox m_channel; | 
					
						
							|  |  |  |   ComboBox m_sample; | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  | class ContextBar::AutoSelectLayerField : public CheckBox { | 
					
						
							| 
									
										
										
										
											2014-11-17 05:33:31 +08:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |   AutoSelectLayerField() : CheckBox(Strings::context_bar_auto_select_layer()) { initTheme(); } | 
					
						
							| 
									
										
										
										
											2014-11-17 05:33:31 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  |   void onInitTheme(InitThemeEvent& ev) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     CheckBox::onInitTheme(ev); | 
					
						
							| 
									
										
										
										
											2022-02-19 06:01:46 +08:00
										 |  |  |     setStyle(SkinTheme::get(this)->styles.miniCheckBox()); | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-12 22:00:16 +08:00
										 |  |  |   void onClick() override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     CheckBox::onClick(); | 
					
						
							| 
									
										
										
										
											2014-11-17 05:33:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-19 08:21:14 +08:00
										 |  |  |     auto atm = App::instance()->activeToolManager(); | 
					
						
							|  |  |  |     if (atm->quickTool() && atm->quickTool()->getInk(0)->isCelMovement()) { | 
					
						
							|  |  |  |       Preferences::instance().editor.autoSelectLayerQuick(isSelected()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       Preferences::instance().editor.autoSelectLayer(isSelected()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-11-17 05:33:31 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     releaseFocus(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-27 04:51:32 +08:00
										 |  |  | class ContextBar::SymmetryField : public ButtonSet { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2024-11-02 02:05:23 +08:00
										 |  |  |   SymmetryField() : ButtonSet(5) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2019-10-30 03:37:06 +08:00
										 |  |  |     setMultiMode(MultiMode::Set); | 
					
						
							| 
									
										
										
										
											2024-11-02 02:05:23 +08:00
										 |  |  |     auto theme = SkinTheme::get(this); | 
					
						
							| 
									
										
										
										
											2024-05-07 04:00:27 +08:00
										 |  |  |     addItem(theme->parts.horizontalSymmetry(), theme->styles.symmetryField()); | 
					
						
							|  |  |  |     addItem(theme->parts.verticalSymmetry(), theme->styles.symmetryField()); | 
					
						
							| 
									
										
										
										
											2024-11-02 02:05:23 +08:00
										 |  |  |     addItem(theme->parts.rightDiagonalSymmetry(), theme->styles.symmetryField()); | 
					
						
							|  |  |  |     addItem(theme->parts.leftDiagonalSymmetry(), theme->styles.symmetryField()); | 
					
						
							| 
									
										
										
										
											2024-05-07 04:00:27 +08:00
										 |  |  |     addItem("...", theme->styles.symmetryOptions()); | 
					
						
							| 
									
										
										
										
											2015-10-27 04:51:32 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void setupTooltips(TooltipManager* tooltipManager) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2019-11-12 02:40:01 +08:00
										 |  |  |     tooltipManager->addTooltipFor(at(0), Strings::symmetry_toggle_horizontal(), BOTTOM); | 
					
						
							|  |  |  |     tooltipManager->addTooltipFor(at(1), Strings::symmetry_toggle_vertical(), BOTTOM); | 
					
						
							| 
									
										
										
										
											2024-11-02 02:05:23 +08:00
										 |  |  |     tooltipManager->addTooltipFor(at(2), Strings::symmetry_toggle_right_diagonal(), BOTTOM); | 
					
						
							|  |  |  |     tooltipManager->addTooltipFor(at(3), Strings::symmetry_toggle_left_diagonal(), BOTTOM); | 
					
						
							|  |  |  |     tooltipManager->addTooltipFor(at(4), Strings::symmetry_show_options(), BOTTOM); | 
					
						
							| 
									
										
										
										
											2015-10-27 04:51:32 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void updateWithCurrentDocument() | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2018-07-07 22:54:44 +08:00
										 |  |  |     Doc* doc = UIContext::instance()->activeDocument(); | 
					
						
							| 
									
										
										
										
											2015-10-27 04:51:32 +08:00
										 |  |  |     if (!doc) | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     DocumentPreferences& docPref = Preferences::instance().document(doc); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-27 02:55:12 +08:00
										 |  |  |     at(0)->setSelected(int(docPref.symmetry.mode()) & int(app::gen::SymmetryMode::HORIZONTAL)); | 
					
						
							|  |  |  |     at(1)->setSelected(int(docPref.symmetry.mode()) & int(app::gen::SymmetryMode::VERTICAL)); | 
					
						
							|  |  |  |     at(2)->setSelected(int(docPref.symmetry.mode()) & int(app::gen::SymmetryMode::RIGHT_DIAG)); | 
					
						
							|  |  |  |     at(3)->setSelected(int(docPref.symmetry.mode()) & int(app::gen::SymmetryMode::LEFT_DIAG)); | 
					
						
							| 
									
										
										
										
											2015-10-27 04:51:32 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |   void onItemChange(Item* item) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ButtonSet::onItemChange(item); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-07 22:54:44 +08:00
										 |  |  |     Doc* doc = UIContext::instance()->activeDocument(); | 
					
						
							| 
									
										
										
										
											2015-10-27 04:51:32 +08:00
										 |  |  |     if (!doc) | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     DocumentPreferences& docPref = Preferences::instance().document(doc); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-28 02:27:37 +08:00
										 |  |  |     int mode = 0; | 
					
						
							|  |  |  |     if (at(0)->isSelected()) | 
					
						
							|  |  |  |       mode |= int(app::gen::SymmetryMode::HORIZONTAL); | 
					
						
							|  |  |  |     if (at(1)->isSelected()) | 
					
						
							|  |  |  |       mode |= int(app::gen::SymmetryMode::VERTICAL); | 
					
						
							| 
									
										
										
										
											2024-11-02 02:05:23 +08:00
										 |  |  |     if (at(2)->isSelected()) | 
					
						
							|  |  |  |       mode |= int(app::gen::SymmetryMode::RIGHT_DIAG); | 
					
						
							|  |  |  |     if (at(3)->isSelected()) | 
					
						
							|  |  |  |       mode |= int(app::gen::SymmetryMode::LEFT_DIAG); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-12 02:40:01 +08:00
										 |  |  |     if (app::gen::SymmetryMode(mode) != docPref.symmetry.mode()) { | 
					
						
							|  |  |  |       docPref.symmetry.mode(app::gen::SymmetryMode(mode)); | 
					
						
							|  |  |  |       // Redraw symmetry rules
 | 
					
						
							|  |  |  |       doc->notifyGeneralUpdate(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2024-11-02 02:05:23 +08:00
										 |  |  |     else if (at(4)->isSelected()) { | 
					
						
							|  |  |  |       auto* item = at(4); | 
					
						
							| 
									
										
										
										
											2019-11-12 02:40:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       gfx::Rect bounds = item->bounds(); | 
					
						
							|  |  |  |       item->setSelected(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       Menu menu; | 
					
						
							| 
									
										
										
										
											2024-09-16 20:32:07 +08:00
										 |  |  |       MenuItem resetToCenter(Strings::symmetry_reset_position()); | 
					
						
							| 
									
										
										
										
											2024-09-06 06:38:54 +08:00
										 |  |  |       MenuItem resetToViewCenter(Strings::symmetry_reset_position_to_view_center()); | 
					
						
							| 
									
										
										
										
											2019-11-12 02:40:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-06 06:38:54 +08:00
										 |  |  |       menu.addChild(&resetToCenter); | 
					
						
							|  |  |  |       menu.addChild(&resetToViewCenter); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       resetToCenter.Click.connect([doc, &docPref] { | 
					
						
							| 
									
										
										
										
											2019-11-12 02:40:01 +08:00
										 |  |  |         docPref.symmetry.xAxis(doc->sprite()->width() / 2.0); | 
					
						
							|  |  |  |         docPref.symmetry.yAxis(doc->sprite()->height() / 2.0); | 
					
						
							|  |  |  |         // Redraw symmetry rules
 | 
					
						
							|  |  |  |         doc->notifyGeneralUpdate(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-06 06:38:54 +08:00
										 |  |  |       resetToViewCenter.Click.connect([doc, &docPref] { | 
					
						
							|  |  |  |         auto* editor = Editor::activeEditor(); | 
					
						
							|  |  |  |         const gfx::Rect& bounds = editor->getViewportBounds(); | 
					
						
							|  |  |  |         double xViewPosition = bounds.x + bounds.w / 2.0; | 
					
						
							|  |  |  |         double yViewPosition = bounds.y + bounds.h / 2.0; | 
					
						
							|  |  |  |         docPref.symmetry.xAxis(xViewPosition); | 
					
						
							|  |  |  |         docPref.symmetry.yAxis(yViewPosition); | 
					
						
							|  |  |  |         // Redraw symmetry rules
 | 
					
						
							|  |  |  |         doc->notifyGeneralUpdate(); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-20 05:57:56 +08:00
										 |  |  |       menu.showPopup(gfx::Point(bounds.x, bounds.y2()), display()); | 
					
						
							| 
									
										
										
										
											2019-11-12 02:40:01 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-10-27 04:51:32 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  | class ContextBar::SliceFields : public HBox { | 
					
						
							|  |  |  |   class Item : public ListItem { | 
					
						
							|  |  |  |   public: | 
					
						
							|  |  |  |     Item(const doc::Slice* slice) : ListItem(slice->name()), m_slice(slice) {} | 
					
						
							|  |  |  |     const doc::Slice* slice() const { return m_slice; } | 
					
						
							| 
									
										
										
										
											2024-12-17 01:52:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |   private: | 
					
						
							|  |  |  |     const doc::Slice* m_slice; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   class Combo : public ComboBox { | 
					
						
							|  |  |  |     SliceFields* m_sliceFields; | 
					
						
							| 
									
										
										
										
											2024-12-17 01:52:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |   public: | 
					
						
							|  |  |  |     Combo(SliceFields* sliceFields) : m_sliceFields(sliceFields) {} | 
					
						
							| 
									
										
										
										
											2024-12-17 01:52:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |   protected: | 
					
						
							|  |  |  |     void onChange() override | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       ComboBox::onChange(); | 
					
						
							|  |  |  |       m_sliceFields->onSelectSliceFromComboBox(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     void onEntryChange() override | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       ComboBox::onEntryChange(); | 
					
						
							|  |  |  |       m_sliceFields->onComboBoxEntryChange(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     void onBeforeOpenListBox() override | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       ComboBox::onBeforeOpenListBox(); | 
					
						
							|  |  |  |       m_sliceFields->fillSlices(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     void onEnterOnEditableEntry() override | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       ComboBox::onEnterOnEditableEntry(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const Slice* slice = nullptr; | 
					
						
							|  |  |  |       if (auto item = dynamic_cast<Item*>(getSelectedItem())) { | 
					
						
							|  |  |  |         if (item->slice()->name() == getValue()) { | 
					
						
							|  |  |  |           slice = item->slice(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-10-20 23:31:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       auto editor = Editor::activeEditor(); | 
					
						
							|  |  |  |       if (!slice && editor) | 
					
						
							|  |  |  |         slice = editor->sprite()->slices().getByName(getValue()); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |       if (slice) | 
					
						
							|  |  |  |         m_sliceFields->scrollToSlice(slice); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       closeListBox(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |   SliceFields() | 
					
						
							|  |  |  |     : m_doc(nullptr) | 
					
						
							|  |  |  |     , m_sel(2) | 
					
						
							|  |  |  |     , m_combobox(this) | 
					
						
							| 
									
										
										
										
											2024-06-13 03:21:32 +08:00
										 |  |  |     , m_transform(Strings::context_bar_slice_transform()) | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |     , m_action(2) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2024-05-07 04:00:27 +08:00
										 |  |  |     auto* theme = SkinTheme::get(this); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     m_sel.addItem(Strings::context_bar_all()); | 
					
						
							|  |  |  |     m_sel.addItem(Strings::context_bar_none()); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |     m_sel.ItemChange.connect([this](ButtonSet::Item* item) { onSelAction(m_sel.selectedItem()); }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_combobox.setEditable(true); | 
					
						
							|  |  |  |     m_combobox.setExpansive(true); | 
					
						
							|  |  |  |     m_combobox.setMinSize(gfx::Size(256 * guiscale(), 0)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-13 03:21:32 +08:00
										 |  |  |     m_transform.Click.connect([this]() { | 
					
						
							|  |  |  |       if (auto* editor = Editor::activeEditor()) | 
					
						
							|  |  |  |         editor->slicesTransforms(m_transform.isSelected()); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-07 04:00:27 +08:00
										 |  |  |     m_action.addItem(theme->parts.iconUserData(), theme->styles.buttonsetItemIconMono()); | 
					
						
							|  |  |  |     m_action.addItem(theme->parts.iconClose(), theme->styles.buttonsetItemIconMono()); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |     m_action.ItemChange.connect( | 
					
						
							|  |  |  |       [this](ButtonSet::Item* item) { onAction(m_action.selectedItem()); }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     addChild(&m_sel); | 
					
						
							|  |  |  |     addChild(&m_combobox); | 
					
						
							| 
									
										
										
										
											2024-06-13 03:21:32 +08:00
										 |  |  |     addChild(&m_transform); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |     addChild(&m_action); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_combobox.setVisible(false); | 
					
						
							|  |  |  |     m_action.setVisible(false); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void setupTooltips(TooltipManager* tooltipManager) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     tooltipManager->addTooltipFor(m_sel.at(0), Strings::context_bar_select_slices(), BOTTOM); | 
					
						
							|  |  |  |     tooltipManager->addTooltipFor(m_sel.at(1), Strings::context_bar_deselect_slices(), BOTTOM); | 
					
						
							| 
									
										
										
										
											2024-06-13 03:21:32 +08:00
										 |  |  |     tooltipManager->addTooltipFor(&m_transform, Strings::context_bar_slice_transform_tip(), BOTTOM); | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |     tooltipManager->addTooltipFor(m_action.at(0), Strings::context_bar_slice_props(), BOTTOM); | 
					
						
							|  |  |  |     tooltipManager->addTooltipFor(m_action.at(1), Strings::context_bar_delete_slice(), BOTTOM); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void setDoc(Doc* doc) { m_doc = doc; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void addSlice(const doc::Slice* slice) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_changeFromEntry = true; | 
					
						
							|  |  |  |     m_combobox.setValue(slice->name()); | 
					
						
							|  |  |  |     updateLayout(); | 
					
						
							|  |  |  |     m_changeFromEntry = false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void removeSlice(const doc::Slice* slice) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_combobox.setValue(std::string()); | 
					
						
							|  |  |  |     updateLayout(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void updateSlice(const doc::Slice* slice) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_combobox.setValue(slice->name()); | 
					
						
							|  |  |  |     updateLayout(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void selectSlices(const doc::Sprite* sprite, const doc::SelectedObjects& slices) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (!slices.empty()) { | 
					
						
							|  |  |  |       auto selected = slices.frontAs<doc::Slice>(); | 
					
						
							| 
									
										
										
										
											2021-06-09 07:02:02 +08:00
										 |  |  |       if (m_combobox.getValue() != selected->name()) | 
					
						
							|  |  |  |         m_combobox.setValue(selected->name()); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2021-06-09 07:02:02 +08:00
										 |  |  |       if (!m_combobox.getValue().empty()) | 
					
						
							|  |  |  |         m_combobox.setValue(std::string()); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     updateLayout(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void closeComboBox() { m_combobox.closeListBox(); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							| 
									
										
										
										
											2024-06-13 03:21:32 +08:00
										 |  |  |   void onInitTheme(InitThemeEvent& ev) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     HBox::onInitTheme(ev); | 
					
						
							|  |  |  |     auto* theme = SkinTheme::get(this); | 
					
						
							|  |  |  |     m_transform.setStyle(theme->styles.miniCheckBox()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |   void onVisible(bool visible) override | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     HBox::onVisible(visible); | 
					
						
							|  |  |  |     m_combobox.closeListBox(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void fillSlices() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_combobox.deleteAllItems(); | 
					
						
							|  |  |  |     if (m_doc && m_doc->sprite()) { | 
					
						
							| 
									
										
										
										
											2024-07-20 03:47:13 +08:00
										 |  |  |       for (auto* slice : sort_slices_by_name(m_doc->sprite()->slices(), MatchWords(m_filter))) { | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |         Item* item = new Item(slice); | 
					
						
							|  |  |  |         m_combobox.addItem(item); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void scrollToSlice(const Slice* slice) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2022-10-20 23:31:22 +08:00
										 |  |  |     auto editor = Editor::activeEditor(); | 
					
						
							|  |  |  |     if (editor && slice) { | 
					
						
							|  |  |  |       if (const SliceKey* key = slice->getByFrame(editor->frame())) { | 
					
						
							|  |  |  |         editor->centerInSpritePoint(key->bounds().center()); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void updateLayout() | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2024-04-08 21:44:44 +08:00
										 |  |  |     const bool visible = (m_doc && m_doc->sprite() && !m_doc->sprite()->slices().empty()); | 
					
						
							| 
									
										
										
										
											2021-06-09 07:02:02 +08:00
										 |  |  |     const bool relayout = (visible != m_combobox.isVisible() || visible != m_action.isVisible()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |     m_combobox.setVisible(visible); | 
					
						
							| 
									
										
										
										
											2024-06-13 03:21:32 +08:00
										 |  |  |     m_transform.setVisible(visible); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |     m_action.setVisible(visible); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-06 02:49:34 +08:00
										 |  |  |     if (auto* editor = Editor::activeEditor()) | 
					
						
							|  |  |  |       m_transform.setSelected(editor->slicesTransforms()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-09 07:02:02 +08:00
										 |  |  |     if (relayout) | 
					
						
							|  |  |  |       parent()->layout(); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void onSelAction(const int item) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_sel.deselectItems(); | 
					
						
							|  |  |  |     switch (item) { | 
					
						
							|  |  |  |       case 0: | 
					
						
							| 
									
										
										
										
											2022-10-20 23:31:22 +08:00
										 |  |  |         if (auto editor = Editor::activeEditor()) | 
					
						
							|  |  |  |           editor->selectAllSlices(); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |         break; | 
					
						
							|  |  |  |       case 1: | 
					
						
							| 
									
										
										
										
											2022-10-20 23:31:22 +08:00
										 |  |  |         if (auto editor = Editor::activeEditor()) | 
					
						
							|  |  |  |           editor->clearSlicesSelection(); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void onSelectSliceFromComboBox() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (m_changeFromEntry) | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_filter.clear(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (auto item = dynamic_cast<Item*>(m_combobox.getSelectedItem())) { | 
					
						
							| 
									
										
										
										
											2022-10-20 23:31:22 +08:00
										 |  |  |       if (auto editor = Editor::activeEditor()) { | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |         const doc::Slice* slice = item->slice(); | 
					
						
							| 
									
										
										
										
											2022-10-20 23:31:22 +08:00
										 |  |  |         editor->clearSlicesSelection(); | 
					
						
							|  |  |  |         editor->selectSlice(slice); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void onComboBoxEntryChange() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_changeFromEntry = true; | 
					
						
							|  |  |  |     m_combobox.closeListBox(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_filter = m_combobox.getValue(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_combobox.openListBox(); | 
					
						
							|  |  |  |     m_changeFromEntry = false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void onAction(const int item) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_action.deselectItems(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Command* cmd = nullptr; | 
					
						
							|  |  |  |     Params params; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (item) { | 
					
						
							|  |  |  |       case 0: cmd = Commands::instance()->byId(CommandId::SliceProperties()); break; | 
					
						
							|  |  |  |       case 1: cmd = Commands::instance()->byId(CommandId::RemoveSlice()); break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (cmd) | 
					
						
							|  |  |  |       UIContext::instance()->executeCommand(cmd, params); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     updateLayout(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Doc* m_doc; | 
					
						
							|  |  |  |   ButtonSet m_sel; | 
					
						
							|  |  |  |   Combo m_combobox; | 
					
						
							| 
									
										
										
										
											2024-06-13 03:21:32 +08:00
										 |  |  |   CheckBox m_transform; | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |   ButtonSet m_action; | 
					
						
							|  |  |  |   bool m_changeFromEntry; | 
					
						
							|  |  |  |   std::string m_filter; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-12 09:31:13 +08:00
										 |  |  | class ContextBar::FontSelector : public FontEntry { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2025-07-17 22:55:09 +08:00
										 |  |  |   FontSelector(ContextBar* contextBar) : FontEntry(true) // With stroke and fill options
 | 
					
						
							| 
									
										
										
										
											2024-06-12 09:31:13 +08:00
										 |  |  |   { | 
					
						
							|  |  |  |     // Load the font from the preferences
 | 
					
						
							| 
									
										
										
										
											2024-10-23 01:32:33 +08:00
										 |  |  |     setInfo(FontInfo::getFromPreferences(), FontEntry::From::Init); | 
					
						
							| 
									
										
										
										
											2024-06-12 09:31:13 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-23 01:32:33 +08:00
										 |  |  |     FontChange.connect([contextBar](const FontInfo& fontInfo, From from) { | 
					
						
							|  |  |  |       contextBar->FontChange(fontInfo, from); | 
					
						
							| 
									
										
										
										
											2024-06-12 09:31:13 +08:00
										 |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ~FontSelector() { info().updatePreferences(); } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-17 08:17:12 +08:00
										 |  |  | ContextBar::ContextBar(TooltipManager* tooltipManager, ColorBar* colorBar) | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  |   auto& pref = Preferences::instance(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-26 04:58:29 +08:00
										 |  |  |   addChild(m_selectionOptionsBox = new HBox()); | 
					
						
							| 
									
										
										
										
											2014-05-26 11:20:16 +08:00
										 |  |  |   m_selectionOptionsBox->addChild(m_dropPixels = new DropPixelsField()); | 
					
						
							| 
									
										
										
										
											2014-01-26 04:58:29 +08:00
										 |  |  |   m_selectionOptionsBox->addChild(m_selectionMode = new SelectionModeField); | 
					
						
							| 
									
										
										
										
											2018-12-14 01:08:56 +08:00
										 |  |  |   m_selectionOptionsBox->addChild( | 
					
						
							|  |  |  |     m_transparentColor = new TransparentColorField(this, tooltipManager)); | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  |   m_selectionOptionsBox->addChild(m_transformation = new TransformationFields); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  |   m_selectionOptionsBox->addChild(m_pivot = new PivotField); | 
					
						
							| 
									
										
										
										
											2014-01-26 04:58:29 +08:00
										 |  |  |   m_selectionOptionsBox->addChild(m_rotAlgo = new RotAlgorithmField()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-15 20:50:00 +08:00
										 |  |  |   addChild(m_zoomButtons = new ZoomButtons); | 
					
						
							| 
									
										
										
										
											2022-02-22 03:21:07 +08:00
										 |  |  |   addChild(m_samplingSelector = new SamplingSelector); | 
					
						
							| 
									
										
										
										
											2016-09-15 20:50:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-23 21:06:13 +08:00
										 |  |  |   addChild(m_brushBack = new BrushBackField); | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  |   addChild(m_brushType = new BrushTypeField(this)); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  |   addChild(m_brushSize = new BrushSizeField()); | 
					
						
							|  |  |  |   addChild(m_brushAngle = new BrushAngleField(m_brushType)); | 
					
						
							| 
									
										
										
										
											2015-04-27 11:08:04 +08:00
										 |  |  |   addChild(m_brushPatternField = new BrushPatternField()); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-23 02:03:07 +08:00
										 |  |  |   addChild(m_toleranceLabel = new Label(Strings::general_tolerance())); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  |   addChild(m_tolerance = new ToleranceField()); | 
					
						
							| 
									
										
										
										
											2014-08-07 11:07:24 +08:00
										 |  |  |   addChild(m_contiguous = new ContiguousField()); | 
					
						
							| 
									
										
										
										
											2016-05-04 02:31:27 +08:00
										 |  |  |   addChild(m_paintBucketSettings = new PaintBucketSettingsField()); | 
					
						
							| 
									
										
										
										
											2019-03-20 07:54:25 +08:00
										 |  |  |   addChild(m_gradientType = new GradientTypeField()); | 
					
						
							| 
									
										
										
										
											2017-06-10 04:31:41 +08:00
										 |  |  |   addChild(m_ditheringSelector = new DitheringSelector(DitheringSelector::SelectMatrix)); | 
					
						
							| 
									
										
										
										
											2017-05-24 07:41:30 +08:00
										 |  |  |   m_ditheringSelector->setUseCustomWidget(false); // Disable custom widget because the context bar
 | 
					
						
							|  |  |  |                                                   // is too small
 | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-03 00:16:06 +08:00
										 |  |  |   addChild(m_inkType = new InkTypeField(this)); | 
					
						
							| 
									
										
										
										
											2023-12-23 02:03:07 +08:00
										 |  |  |   addChild(m_inkOpacityLabel = new Label(Strings::general_opacity())); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  |   addChild(m_inkOpacity = new InkOpacityField()); | 
					
						
							| 
									
										
										
										
											2019-12-17 08:17:12 +08:00
										 |  |  |   addChild(m_inkShades = new InkShadesField(colorBar)); | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-03 05:13:47 +08:00
										 |  |  |   addChild(m_eyedropperField = new EyedropperField()); | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-17 05:33:31 +08:00
										 |  |  |   addChild(m_autoSelectLayer = new AutoSelectLayerField()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-31 08:31:34 +08:00
										 |  |  |   addChild(m_sprayBox = new HBox()); | 
					
						
							| 
									
										
										
										
											2023-12-23 02:03:07 +08:00
										 |  |  |   m_sprayBox->addChild(m_sprayLabel = new Label(Strings::context_bar_spray())); | 
					
						
							| 
									
										
										
										
											2013-03-31 08:31:34 +08:00
										 |  |  |   m_sprayBox->addChild(m_sprayWidth = new SprayWidthField()); | 
					
						
							|  |  |  |   m_sprayBox->addChild(m_spraySpeed = new SpraySpeedField()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-08 00:11:44 +08:00
										 |  |  |   addChild(m_selectBoxHelp = new Label("")); | 
					
						
							| 
									
										
										
										
											2014-01-26 03:37:38 +08:00
										 |  |  |   addChild(m_freehandBox = new HBox()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 22:02:52 +08:00
										 |  |  |   m_freehandBox->addChild(m_dynamics = new DynamicsField(this)); | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  |   m_freehandBox->addChild(m_freehandAlgo = new FreehandAlgorithmField()); | 
					
						
							| 
									
										
										
										
											2014-01-26 19:40:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-27 04:51:32 +08:00
										 |  |  |   addChild(m_symmetry = new SymmetryField()); | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  |   m_symmetry->setVisible(pref.symmetryMode.enabled()); | 
					
						
							| 
									
										
										
										
											2015-10-27 04:51:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |   addChild(m_sliceFields = new SliceFields); | 
					
						
							| 
									
										
										
										
											2024-06-12 09:31:13 +08:00
										 |  |  |   addChild(m_fontSelector = new FontSelector(this)); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-23 21:16:37 +08:00
										 |  |  |   setupTooltips(tooltipManager); | 
					
						
							| 
									
										
										
										
											2013-03-31 08:31:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-14 02:02:00 +08:00
										 |  |  |   App::instance()->activeToolManager()->add_observer(this); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |   UIContext::instance()->add_observer(this); | 
					
						
							| 
									
										
										
										
											2016-04-26 02:20:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-09 03:24:36 +08:00
										 |  |  |   m_symmModeConn = pref.symmetryMode.enabled.AfterChange.connect( | 
					
						
							| 
									
										
										
										
											2020-07-04 08:51:46 +08:00
										 |  |  |     [this] { onSymmetryModeChange(); }); | 
					
						
							| 
									
										
										
										
											2022-06-09 03:24:36 +08:00
										 |  |  |   m_fgColorConn = pref.colorBar.fgColor.AfterChange.connect( | 
					
						
							| 
									
										
										
										
											2020-07-04 08:51:46 +08:00
										 |  |  |     [this] { onFgOrBgColorChange(doc::Brush::ImageColor::MainColor); }); | 
					
						
							| 
									
										
										
										
											2022-06-09 03:24:36 +08:00
										 |  |  |   m_bgColorConn = pref.colorBar.bgColor.AfterChange.connect( | 
					
						
							| 
									
										
										
										
											2020-07-04 08:51:46 +08:00
										 |  |  |     [this] { onFgOrBgColorChange(doc::Brush::ImageColor::BackgroundColor); }); | 
					
						
							| 
									
										
										
										
											2024-01-11 02:27:17 +08:00
										 |  |  |   m_alphaRangeConn = pref.range.opacity.AfterChange.connect([this] { onOpacityRangeChange(); }); | 
					
						
							| 
									
										
										
										
											2022-06-09 03:24:36 +08:00
										 |  |  |   m_keysConn = KeyboardShortcuts::instance()->UserChange.connect( | 
					
						
							| 
									
										
										
										
											2020-07-04 08:51:46 +08:00
										 |  |  |     [this, tooltipManager] { setupTooltips(tooltipManager); }); | 
					
						
							| 
									
										
										
										
											2022-06-09 03:24:36 +08:00
										 |  |  |   m_dropPixelsConn = m_dropPixels->DropPixels.connect(&ContextBar::onDropPixels, this); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |   setActiveBrush(createBrushFromPreferences()); | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   initTheme(); | 
					
						
							| 
									
										
										
										
											2017-12-01 03:23:31 +08:00
										 |  |  |   registerCommands(); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-26 02:20:53 +08:00
										 |  |  | ContextBar::~ContextBar() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |   UIContext::instance()->remove_observer(this); | 
					
						
							| 
									
										
										
										
											2016-09-14 02:02:00 +08:00
										 |  |  |   App::instance()->activeToolManager()->remove_observer(this); | 
					
						
							| 
									
										
										
										
											2016-04-26 02:20:53 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  | void ContextBar::onInitTheme(ui::InitThemeEvent& ev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Box::onInitTheme(ev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-19 06:01:46 +08:00
										 |  |  |   auto theme = SkinTheme::get(this); | 
					
						
							| 
									
										
										
										
											2017-08-15 21:39:06 +08:00
										 |  |  |   gfx::Border border = this->border(); | 
					
						
							|  |  |  |   border.bottom(2 * guiscale()); | 
					
						
							|  |  |  |   setBorder(border); | 
					
						
							|  |  |  |   setBgColor(theme->colors.workspace()); | 
					
						
							|  |  |  |   m_sprayLabel->setStyle(theme->styles.miniLabel()); | 
					
						
							|  |  |  |   m_toleranceLabel->setStyle(theme->styles.miniLabel()); | 
					
						
							|  |  |  |   m_inkOpacityLabel->setStyle(theme->styles.miniLabel()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-04 08:50:05 +08:00
										 |  |  | void ContextBar::onSizeHint(SizeHintEvent& ev) | 
					
						
							| 
									
										
										
										
											2014-02-03 08:07:12 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-02-19 06:01:46 +08:00
										 |  |  |   auto theme = SkinTheme::get(this); | 
					
						
							| 
									
										
										
										
											2018-11-15 22:08:45 +08:00
										 |  |  |   ev.setSizeHint(gfx::Size(0, theme->dimensions.contextBarHeight())); | 
					
						
							| 
									
										
										
										
											2014-02-03 08:07:12 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  | void ContextBar::onToolSetOpacity(const int& newOpacity) | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |   if (g_updatingFromCode) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  |   m_inkOpacity->setTextf("%d", newOpacity); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-19 03:15:25 +08:00
										 |  |  | void ContextBar::onToolSetFreehandAlgorithm() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Tool* tool = App::instance()->activeTool(); | 
					
						
							|  |  |  |   if (tool) { | 
					
						
							|  |  |  |     m_freehandAlgo->setFreehandAlgorithm(Preferences::instance().tool(tool).freehandAlgorithm()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-10 00:04:00 +08:00
										 |  |  | void ContextBar::onToolSetContiguous() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Tool* tool = App::instance()->activeTool(); | 
					
						
							|  |  |  |   if (tool) { | 
					
						
							|  |  |  |     m_contiguous->setSelected(Preferences::instance().tool(tool).contiguous()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  | void ContextBar::onActiveSiteChange(const Site& site) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   DocObserverWidget<ui::HBox>::onActiveSiteChange(site); | 
					
						
							| 
									
										
										
										
											2021-06-09 07:02:02 +08:00
										 |  |  |   if (m_sliceFields->isVisible()) | 
					
						
							|  |  |  |     updateSliceFields(site); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ContextBar::onDocChange(Doc* doc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   DocObserverWidget<ui::HBox>::onDocChange(doc); | 
					
						
							|  |  |  |   m_sliceFields->setDoc(doc); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ContextBar::onAddSlice(DocEvent& ev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (ev.slice()) | 
					
						
							|  |  |  |     m_sliceFields->addSlice(ev.slice()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ContextBar::onRemoveSlice(DocEvent& ev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (ev.slice()) | 
					
						
							|  |  |  |     m_sliceFields->removeSlice(ev.slice()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ContextBar::onSliceNameChange(DocEvent& ev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (ev.slice()) | 
					
						
							|  |  |  |     m_sliceFields->updateSlice(ev.slice()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-15 02:09:43 +08:00
										 |  |  | void ContextBar::onBrushSizeChange() | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  |   if (m_activeBrush->type() != kImageBrushType) | 
					
						
							|  |  |  |     discardActiveBrush(); | 
					
						
							| 
									
										
										
										
											2015-07-04 00:41:50 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-26 02:20:53 +08:00
										 |  |  |   updateForActiveTool(); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-15 02:09:43 +08:00
										 |  |  | void ContextBar::onBrushAngleChange() | 
					
						
							| 
									
										
										
										
											2013-05-23 10:58:32 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  |   if (m_activeBrush->type() != kImageBrushType) | 
					
						
							|  |  |  |     discardActiveBrush(); | 
					
						
							| 
									
										
										
										
											2013-05-23 10:58:32 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-26 02:20:53 +08:00
										 |  |  | void ContextBar::onActiveToolChange(tools::Tool* tool) | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  |   if (m_activeBrush->type() != kImageBrushType) | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     setActiveBrush(ContextBar::createBrushFromPreferences()); | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  |   else { | 
					
						
							| 
									
										
										
										
											2016-04-26 02:20:53 +08:00
										 |  |  |     updateForTool(tool); | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-27 04:51:32 +08:00
										 |  |  | void ContextBar::onSymmetryModeChange() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-04-26 02:20:53 +08:00
										 |  |  |   updateForActiveTool(); | 
					
						
							| 
									
										
										
										
											2015-10-27 04:51:32 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-26 05:48:59 +08:00
										 |  |  | void ContextBar::onFgOrBgColorChange(doc::Brush::ImageColor imageColor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!m_activeBrush) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (m_activeBrush->type() == kImageBrushType) { | 
					
						
							|  |  |  |     ASSERT(m_activeBrush->image()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto& pref = Preferences::instance(); | 
					
						
							|  |  |  |     m_activeBrush->setImageColor( | 
					
						
							|  |  |  |       imageColor, | 
					
						
							| 
									
										
										
										
											2017-06-30 01:24:28 +08:00
										 |  |  |       color_utils::color_for_target_mask( | 
					
						
							| 
									
										
										
										
											2016-02-26 05:48:59 +08:00
										 |  |  |         (imageColor == doc::Brush::ImageColor::MainColor ? pref.colorBar.fgColor() : | 
					
						
							|  |  |  |                                                            pref.colorBar.bgColor()), | 
					
						
							| 
									
										
										
										
											2017-06-30 01:24:28 +08:00
										 |  |  |         ColorTarget(ColorTarget::TransparentLayer, m_activeBrush->image()->pixelFormat(), -1))); | 
					
						
							| 
									
										
										
										
											2016-02-26 05:48:59 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-11 02:27:17 +08:00
										 |  |  | void ContextBar::onOpacityRangeChange() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   updateForActiveTool(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-26 11:20:16 +08:00
										 |  |  | void ContextBar::onDropPixels(ContextBarObserver::DropAction action) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-09-14 02:02:00 +08:00
										 |  |  |   notify_observers(&ContextBarObserver::onDropPixels, action); | 
					
						
							| 
									
										
										
										
											2014-05-26 11:20:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-09 07:02:02 +08:00
										 |  |  | void ContextBar::updateSliceFields(const Site& site) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (site.sprite()) | 
					
						
							|  |  |  |     m_sliceFields->selectSlices(site.sprite(), site.selectedSlices()); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     m_sliceFields->closeComboBox(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-26 02:20:53 +08:00
										 |  |  | void ContextBar::updateForActiveTool() | 
					
						
							| 
									
										
										
										
											2015-05-07 23:32:08 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |   updateForTool(App::instance()->activeTool()); | 
					
						
							| 
									
										
										
										
											2015-05-07 23:32:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ContextBar::updateForTool(tools::Tool* tool) | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-10-29 23:52:22 +08:00
										 |  |  |   // TODO Improve the design of the visibility of ContextBar
 | 
					
						
							|  |  |  |   // items. Actually this manual show/hide logic is a mess. There
 | 
					
						
							|  |  |  |   // should be a IContextBarUser interface, with a method to ask who
 | 
					
						
							|  |  |  |   // needs which items to be visible. E.g. different tools elements
 | 
					
						
							|  |  |  |   // (inks, controllers, etc.) and sprite editor states are the main
 | 
					
						
							|  |  |  |   // target to implement this new IContextBarUser and ask for
 | 
					
						
							|  |  |  |   // ContextBar elements.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-03 04:24:09 +08:00
										 |  |  |   const bool oldUpdatingFromCode = g_updatingFromCode; | 
					
						
							| 
									
										
										
										
											2023-04-15 00:43:36 +08:00
										 |  |  |   base::ScopedValue lockFlag(g_updatingFromCode, true); | 
					
						
							| 
									
										
										
										
											2014-10-25 23:10:52 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |   ToolPreferences* toolPref = nullptr; | 
					
						
							|  |  |  |   ToolPreferences::Brush* brushPref = nullptr; | 
					
						
							|  |  |  |   Preferences& preferences = Preferences::instance(); | 
					
						
							| 
									
										
										
										
											2015-05-08 00:11:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (tool) { | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     toolPref = &preferences.tool(tool); | 
					
						
							|  |  |  |     brushPref = &toolPref->brush; | 
					
						
							| 
									
										
										
										
											2015-05-08 00:11:44 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |   if (toolPref) { | 
					
						
							| 
									
										
										
										
											2020-07-04 08:51:46 +08:00
										 |  |  |     m_sizeConn = brushPref->size.AfterChange.connect([this] { onBrushSizeChange(); }); | 
					
						
							|  |  |  |     m_angleConn = brushPref->angle.AfterChange.connect([this] { onBrushAngleChange(); }); | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     m_opacityConn = toolPref->opacity.AfterChange.connect(&ContextBar::onToolSetOpacity, this); | 
					
						
							| 
									
										
										
										
											2020-07-04 08:51:46 +08:00
										 |  |  |     m_freehandAlgoConn = toolPref->freehandAlgorithm.AfterChange.connect( | 
					
						
							|  |  |  |       [this] { onToolSetFreehandAlgorithm(); }); | 
					
						
							|  |  |  |     m_contiguousConn = toolPref->contiguous.AfterChange.connect([this] { onToolSetContiguous(); }); | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-05-08 00:11:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (tool) | 
					
						
							|  |  |  |     m_brushType->updateBrush(tool); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |   if (brushPref) { | 
					
						
							| 
									
										
										
										
											2016-12-03 04:24:09 +08:00
										 |  |  |     if (!oldUpdatingFromCode) { | 
					
						
							|  |  |  |       m_brushSize->setTextf("%d", brushPref->size()); | 
					
						
							|  |  |  |       m_brushAngle->setTextf("%d", brushPref->angle()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-08 00:11:44 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-27 11:08:04 +08:00
										 |  |  |   m_brushPatternField->setBrushPattern(preferences.brush.pattern()); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-03 00:16:06 +08:00
										 |  |  |   // Tool ink
 | 
					
						
							|  |  |  |   bool isPaint = tool && (tool->getInk(0)->isPaint() || tool->getInk(1)->isPaint()); | 
					
						
							|  |  |  |   bool isEffect = tool && (tool->getInk(0)->isEffect() || tool->getInk(1)->isEffect()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // True if the current tool support opacity slider
 | 
					
						
							|  |  |  |   bool supportOpacity = (isPaint || isEffect); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // True if it makes sense to change the ink property for the current
 | 
					
						
							|  |  |  |   // tool.
 | 
					
						
							|  |  |  |   bool hasInk = tool && ((tool->getInk(0)->isPaint() && !tool->getInk(0)->isEffect()) || | 
					
						
							|  |  |  |                          (tool->getInk(1)->isPaint() && !tool->getInk(1)->isEffect())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool hasInkWithOpacity = false; | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  |   bool hasInkShades = false; | 
					
						
							| 
									
										
										
										
											2015-07-03 00:16:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |   if (toolPref) { | 
					
						
							|  |  |  |     m_tolerance->setTextf("%d", toolPref->tolerance()); | 
					
						
							|  |  |  |     m_contiguous->setSelected(toolPref->contiguous()); | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-27 12:35:31 +08:00
										 |  |  |     m_inkType->setInkTypeIcon(toolPref->ink()); | 
					
						
							| 
									
										
										
										
											2024-01-11 02:27:17 +08:00
										 |  |  |     m_inkOpacity->setValue(toolPref->opacity()); | 
					
						
							| 
									
										
										
										
											2013-03-31 08:12:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-14 00:26:52 +08:00
										 |  |  |     hasInkWithOpacity = ((isPaint && tools::inkHasOpacity(toolPref->ink())) || (isEffect)); | 
					
						
							| 
									
										
										
										
											2015-07-03 00:16:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-23 04:05:33 +08:00
										 |  |  |     hasInkShades = (isPaint && !isEffect && toolPref->ink() == InkType::SHADING); | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     m_freehandAlgo->setFreehandAlgorithm(toolPref->freehandAlgorithm()); | 
					
						
							| 
									
										
										
										
											2014-01-26 03:26:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     m_sprayWidth->setValue(toolPref->spray.width()); | 
					
						
							|  |  |  |     m_spraySpeed->setValue(toolPref->spray.speed()); | 
					
						
							| 
									
										
										
										
											2015-05-08 00:11:44 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 07:41:30 +08:00
										 |  |  |   const bool updateShade = (!m_inkShades->isVisible() && hasInkShades); | 
					
						
							| 
									
										
										
										
											2016-07-02 03:24:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-03 05:13:47 +08:00
										 |  |  |   m_eyedropperField->updateFromPreferences(preferences.eyedropper); | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |   m_autoSelectLayer->setSelected(preferences.editor.autoSelectLayer()); | 
					
						
							| 
									
										
										
										
											2013-03-31 08:31:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-27 11:08:04 +08:00
										 |  |  |   // True if we have an image as brush
 | 
					
						
							| 
									
										
										
										
											2017-05-24 07:41:30 +08:00
										 |  |  |   const bool hasImageBrush = (activeBrush()->type() == kImageBrushType); | 
					
						
							| 
									
										
										
										
											2015-04-27 11:08:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-04 00:41:50 +08:00
										 |  |  |   // True if the brush type supports angle.
 | 
					
						
							| 
									
										
										
										
											2017-05-24 07:41:30 +08:00
										 |  |  |   const bool hasBrushWithAngle = (activeBrush()->size() > 1) && | 
					
						
							| 
									
										
										
										
											2015-07-04 00:41:50 +08:00
										 |  |  |                                  (activeBrush()->type() == kSquareBrushType || | 
					
						
							|  |  |  |                                   activeBrush()->type() == kLineBrushType); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  |   // True if the current tool is eyedropper.
 | 
					
						
							| 
									
										
										
										
											2017-05-24 07:41:30 +08:00
										 |  |  |   const bool isEyedropper = tool && | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  |                             (tool->getInk(0)->isEyedropper() || tool->getInk(1)->isEyedropper()); | 
					
						
							| 
									
										
										
										
											2013-03-31 08:12:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-17 05:33:31 +08:00
										 |  |  |   // True if the current tool is move tool.
 | 
					
						
							| 
									
										
										
										
											2017-05-24 07:41:30 +08:00
										 |  |  |   const bool isMove = tool && | 
					
						
							| 
									
										
										
										
											2014-11-17 05:33:31 +08:00
										 |  |  |                       (tool->getInk(0)->isCelMovement() || tool->getInk(1)->isCelMovement()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |   // True if the current tool is slice tool.
 | 
					
						
							|  |  |  |   const bool isSlice = tool && (tool->getInk(0)->isSlice() || tool->getInk(1)->isSlice()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-12 09:31:13 +08:00
										 |  |  |   // True if the current tool is text tool.
 | 
					
						
							|  |  |  |   const bool isText = tool && (tool->getInk(0)->isText() || tool->getInk(1)->isText()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-18 00:22:46 +08:00
										 |  |  |   // True if the current tool is floodfill
 | 
					
						
							|  |  |  |   const bool isFloodfill = tool && (tool->getPointShape(0)->isFloodFill() || | 
					
						
							|  |  |  |                                     tool->getPointShape(1)->isFloodFill()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-31 08:12:09 +08:00
										 |  |  |   // True if the current tool needs tolerance options
 | 
					
						
							| 
									
										
										
										
											2015-05-08 00:11:44 +08:00
										 |  |  |   const bool hasTolerance = tool && (tool->getPointShape(0)->isFloodFill() || | 
					
						
							|  |  |  |                                      tool->getPointShape(1)->isFloodFill()); | 
					
						
							| 
									
										
										
										
											2013-03-31 08:12:09 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // True if the current tool needs spray options
 | 
					
						
							| 
									
										
										
										
											2015-05-08 00:11:44 +08:00
										 |  |  |   const bool hasSprayOptions = tool && (tool->getPointShape(0)->isSpray() || | 
					
						
							|  |  |  |                                         tool->getPointShape(1)->isSpray()); | 
					
						
							| 
									
										
										
										
											2013-03-31 08:12:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 07:41:30 +08:00
										 |  |  |   const bool hasSelectOptions = tool && | 
					
						
							| 
									
										
										
										
											2015-05-08 00:11:44 +08:00
										 |  |  |                                 (tool->getInk(0)->isSelection() || tool->getInk(1)->isSelection()); | 
					
						
							| 
									
										
										
										
											2013-11-30 04:59:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-29 10:56:44 +08:00
										 |  |  |   const bool isFreehand = tool && (tool->getController(0)->isFreehand() || | 
					
						
							|  |  |  |                                    tool->getController(1)->isFreehand()); | 
					
						
							| 
									
										
										
										
											2014-01-26 03:26:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 23:56:46 +08:00
										 |  |  |   const bool isFilled = tool && (tool->getFill(0) == tools::FillAlways || | 
					
						
							|  |  |  |                                  tool->getFill(1) == tools::FillAlways); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 07:41:30 +08:00
										 |  |  |   const bool showOpacity = (supportOpacity) && | 
					
						
							| 
									
										
										
										
											2015-07-23 21:43:16 +08:00
										 |  |  |                            ((isPaint && (hasInkWithOpacity || hasImageBrush)) || (isEffect)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 07:41:30 +08:00
										 |  |  |   const bool withDithering = tool && (tool->getInk(0)->withDitheringOptions() || | 
					
						
							|  |  |  |                                       tool->getInk(1)->withDitheringOptions()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-30 23:56:46 +08:00
										 |  |  |   // True if the tool & brush support dynamics
 | 
					
						
							|  |  |  |   const bool supportDynamics = (isFreehand && !isFilled && // TODO add support for dynamics to
 | 
					
						
							|  |  |  |                                                            // contour tool
 | 
					
						
							|  |  |  |                                 !hasImageBrush); // TODO add support for dynamics in custom brushes
 | 
					
						
							| 
									
										
										
										
											2020-04-23 07:17:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-31 08:12:09 +08:00
										 |  |  |   // Show/Hide fields
 | 
					
						
							| 
									
										
										
										
											2022-02-22 02:30:09 +08:00
										 |  |  |   m_zoomButtons->setVisible(needZoomButtons(tool)); | 
					
						
							| 
									
										
										
										
											2017-11-23 21:06:13 +08:00
										 |  |  |   m_brushBack->setVisible(supportOpacity && hasImageBrush && !withDithering); | 
					
						
							| 
									
										
										
										
											2023-09-26 03:56:30 +08:00
										 |  |  |   m_brushType->setVisible(supportOpacity && (!isFloodfill || (isFloodfill && !withDithering))); | 
					
						
							| 
									
										
										
										
											2015-07-03 00:16:06 +08:00
										 |  |  |   m_brushSize->setVisible(supportOpacity && !isFloodfill && !hasImageBrush); | 
					
						
							| 
									
										
										
										
											2015-07-04 00:41:50 +08:00
										 |  |  |   m_brushAngle->setVisible(supportOpacity && !isFloodfill && !hasImageBrush && hasBrushWithAngle); | 
					
						
							| 
									
										
										
										
											2017-06-30 01:46:12 +08:00
										 |  |  |   m_brushPatternField->setVisible(supportOpacity && hasImageBrush && !withDithering); | 
					
						
							| 
									
										
										
										
											2016-02-16 07:40:37 +08:00
										 |  |  |   m_inkType->setVisible(hasInk); | 
					
						
							| 
									
										
										
										
											2015-07-23 21:43:16 +08:00
										 |  |  |   m_inkOpacityLabel->setVisible(showOpacity); | 
					
						
							|  |  |  |   m_inkOpacity->setVisible(showOpacity); | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  |   m_inkShades->setVisible(hasInkShades); | 
					
						
							| 
									
										
										
										
											2015-07-03 05:13:47 +08:00
										 |  |  |   m_eyedropperField->setVisible(isEyedropper); | 
					
						
							| 
									
										
										
										
											2014-11-17 05:33:31 +08:00
										 |  |  |   m_autoSelectLayer->setVisible(isMove); | 
					
						
							| 
									
										
										
										
											2023-11-30 23:56:46 +08:00
										 |  |  |   m_dynamics->setVisible(supportDynamics); | 
					
						
							| 
									
										
										
										
											2021-06-11 23:07:28 +08:00
										 |  |  |   m_dynamics->setOptionsGridVisibility(isFreehand && !hasSelectOptions); | 
					
						
							| 
									
										
										
										
											2023-12-01 08:24:48 +08:00
										 |  |  |   if (supportDynamics) | 
					
						
							|  |  |  |     m_dynamics->updateIconFromActiveToolPref(); | 
					
						
							| 
									
										
										
										
											2021-06-12 01:29:58 +08:00
										 |  |  |   m_freehandBox->setVisible(isFreehand && (supportOpacity || hasSelectOptions)); | 
					
						
							| 
									
										
										
										
											2024-01-25 22:16:50 +08:00
										 |  |  |   m_freehandAlgo->setVisible(!hasSprayOptions); | 
					
						
							| 
									
										
										
										
											2013-03-31 08:12:09 +08:00
										 |  |  |   m_toleranceLabel->setVisible(hasTolerance); | 
					
						
							|  |  |  |   m_tolerance->setVisible(hasTolerance); | 
					
						
							| 
									
										
										
										
											2014-08-07 11:07:24 +08:00
										 |  |  |   m_contiguous->setVisible(hasTolerance); | 
					
						
							| 
									
										
										
										
											2016-05-04 02:31:27 +08:00
										 |  |  |   m_paintBucketSettings->setVisible(hasTolerance); | 
					
						
							| 
									
										
										
										
											2013-03-31 08:31:34 +08:00
										 |  |  |   m_sprayBox->setVisible(hasSprayOptions); | 
					
						
							| 
									
										
										
										
											2013-11-30 04:59:28 +08:00
										 |  |  |   m_selectionOptionsBox->setVisible(hasSelectOptions); | 
					
						
							| 
									
										
										
										
											2019-03-20 07:54:25 +08:00
										 |  |  |   m_gradientType->setVisible(withDithering); | 
					
						
							| 
									
										
										
										
											2017-05-24 07:41:30 +08:00
										 |  |  |   m_ditheringSelector->setVisible(withDithering); | 
					
						
							| 
									
										
										
										
											2014-05-26 11:20:16 +08:00
										 |  |  |   m_selectionMode->setVisible(true); | 
					
						
							| 
									
										
										
										
											2015-07-30 03:35:34 +08:00
										 |  |  |   m_pivot->setVisible(true); | 
					
						
							| 
									
										
										
										
											2014-05-26 11:20:16 +08:00
										 |  |  |   m_dropPixels->setVisible(false); | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  |   m_transformation->setVisible(false); | 
					
						
							| 
									
										
										
										
											2015-05-08 00:11:44 +08:00
										 |  |  |   m_selectBoxHelp->setVisible(false); | 
					
						
							| 
									
										
										
										
											2015-10-29 23:52:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   m_symmetry->setVisible(Preferences::instance().symmetryMode.enabled() && | 
					
						
							|  |  |  |                          (isPaint || isEffect || hasSelectOptions)); | 
					
						
							| 
									
										
										
										
											2015-10-27 04:51:32 +08:00
										 |  |  |   m_symmetry->updateWithCurrentDocument(); | 
					
						
							| 
									
										
										
										
											2013-03-31 08:12:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |   m_sliceFields->setVisible(isSlice); | 
					
						
							| 
									
										
										
										
											2021-06-09 07:02:02 +08:00
										 |  |  |   if (isSlice) | 
					
						
							|  |  |  |     updateSliceFields(UIContext::instance()->activeSite()); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-12 09:31:13 +08:00
										 |  |  |   m_fontSelector->setVisible(isText); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-02 03:24:29 +08:00
										 |  |  |   // Update ink shades with the current selected palette entries
 | 
					
						
							|  |  |  |   if (updateShade) | 
					
						
							|  |  |  |     m_inkShades->updateShadeFromColorBarPicks(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-22 02:30:09 +08:00
										 |  |  |   if (!updateSamplingVisibility(tool)) { | 
					
						
							|  |  |  |     // updateSamplingVisibility() returns false if it doesn't layout()
 | 
					
						
							|  |  |  |     // the ContextBar.
 | 
					
						
							|  |  |  |     layout(); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-03-31 00:43:00 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  | void ContextBar::updateForMovingPixels(const Transformation& t) | 
					
						
							| 
									
										
										
										
											2014-05-26 11:20:16 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-04-23 00:19:06 +08:00
										 |  |  |   tools::Tool* tool = App::instance()->toolBox()->getToolById( | 
					
						
							| 
									
										
										
										
											2014-05-26 11:20:16 +08:00
										 |  |  |     tools::WellKnownTools::RectangularMarquee); | 
					
						
							|  |  |  |   if (tool) | 
					
						
							| 
									
										
										
										
											2015-05-07 23:32:08 +08:00
										 |  |  |     updateForTool(tool); | 
					
						
							| 
									
										
										
										
											2014-05-26 11:20:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   m_dropPixels->deselectItems(); | 
					
						
							|  |  |  |   m_dropPixels->setVisible(true); | 
					
						
							|  |  |  |   m_selectionMode->setVisible(false); | 
					
						
							| 
									
										
										
										
											2020-09-19 06:29:43 +08:00
										 |  |  |   m_transformation->setVisible(true); | 
					
						
							|  |  |  |   m_transformation->update(t); | 
					
						
							| 
									
										
										
										
											2014-05-26 11:20:16 +08:00
										 |  |  |   layout(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-08 00:11:44 +08:00
										 |  |  | void ContextBar::updateForSelectingBox(const std::string& text) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
											
												Refactor several "getNoun()" getters to "noun()"
This is a work-in-progress to create a consistent API and finally
separate the whole Aseprite base/gfx/ui libs into a reusable C++ library.
Classes:
app::IFileItem, app::AppMenuItem, app::skin::SkinPart,
gfx::Rect, gfx::Border, she::FileDialog,
ui::IButtonIcon, ui::Graphics, ui::Overlay, ui::Widget,
ui::ScrollableViewDelegate, and UI events
											
										 
											2015-12-05 01:39:04 +08:00
										 |  |  |   if (m_selectBoxHelp->isVisible() && m_selectBoxHelp->text() == text) | 
					
						
							| 
									
										
										
										
											2015-05-08 00:11:44 +08:00
										 |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   updateForTool(nullptr); | 
					
						
							|  |  |  |   m_selectBoxHelp->setText(text); | 
					
						
							|  |  |  |   m_selectBoxHelp->setVisible(true); | 
					
						
							|  |  |  |   layout(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-05 05:46:48 +08:00
										 |  |  | void ContextBar::updateToolLoopModifiersIndicators(tools::ToolLoopModifiers modifiers) | 
					
						
							| 
									
										
										
										
											2014-08-25 06:19:38 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-04-05 05:46:48 +08:00
										 |  |  |   gen::SelectionMode mode = gen::SelectionMode::DEFAULT; | 
					
						
							|  |  |  |   if (int(modifiers) & int(tools::ToolLoopModifiers::kAddSelection)) | 
					
						
							|  |  |  |     mode = gen::SelectionMode::ADD; | 
					
						
							|  |  |  |   else if (int(modifiers) & int(tools::ToolLoopModifiers::kSubtractSelection)) | 
					
						
							|  |  |  |     mode = gen::SelectionMode::SUBTRACT; | 
					
						
							| 
									
										
										
										
											2018-10-27 01:04:08 +08:00
										 |  |  |   else if (int(modifiers) & int(tools::ToolLoopModifiers::kIntersectSelection)) | 
					
						
							|  |  |  |     mode = gen::SelectionMode::INTERSECT; | 
					
						
							| 
									
										
										
										
											2016-04-05 05:46:48 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-25 06:19:38 +08:00
										 |  |  |   m_selectionMode->setSelectionMode(mode); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-22 02:30:09 +08:00
										 |  |  | bool ContextBar::updateSamplingVisibility(tools::Tool* tool) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!tool) | 
					
						
							|  |  |  |     tool = App::instance()->activeTool(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-20 23:31:22 +08:00
										 |  |  |   auto editor = Editor::activeEditor(); | 
					
						
							| 
									
										
										
										
											2022-02-22 02:30:09 +08:00
										 |  |  |   const bool newVisibility = needZoomButtons(tool) && editor && | 
					
						
							| 
									
										
										
										
											2022-10-20 23:31:22 +08:00
										 |  |  |                              (editor->projection().scaleX() < 1.0 || | 
					
						
							|  |  |  |                               editor->projection().scaleY() < 1.0) && | 
					
						
							|  |  |  |                              editor->isUsingNewRenderEngine(); | 
					
						
							| 
									
										
										
										
											2022-02-22 02:30:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-22 03:21:07 +08:00
										 |  |  |   if (newVisibility == m_samplingSelector->hasFlags(HIDDEN)) { | 
					
						
							|  |  |  |     m_samplingSelector->setVisible(newVisibility); | 
					
						
							| 
									
										
										
										
											2022-02-22 02:30:09 +08:00
										 |  |  |     layout(); | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-17 05:33:31 +08:00
										 |  |  | void ContextBar::updateAutoSelectLayer(bool state) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   m_autoSelectLayer->setSelected(state); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-30 05:36:08 +08:00
										 |  |  | bool ContextBar::isAutoSelectLayer() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return m_autoSelectLayer->isSelected(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-12 23:19:12 +08:00
										 |  |  | void ContextBar::setActiveBrushBySlot(tools::Tool* tool, int slot) | 
					
						
							| 
									
										
										
										
											2015-04-30 02:00:05 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-09-12 23:19:12 +08:00
										 |  |  |   ASSERT(tool); | 
					
						
							|  |  |  |   if (!tool) | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-16 04:12:11 +08:00
										 |  |  |   AppBrushes& brushes = App::instance()->brushes(); | 
					
						
							| 
									
										
										
										
											2015-12-17 04:27:04 +08:00
										 |  |  |   BrushSlot brush = brushes.getBrushSlot(slot); | 
					
						
							|  |  |  |   if (!brush.isEmpty()) { | 
					
						
							|  |  |  |     brushes.lockBrushSlot(slot); | 
					
						
							| 
									
										
										
										
											2015-05-07 04:39:40 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 04:27:04 +08:00
										 |  |  |     Preferences& pref = Preferences::instance(); | 
					
						
							|  |  |  |     ToolPreferences& toolPref = pref.tool(tool); | 
					
						
							|  |  |  |     ToolPreferences::Brush& brushPref = toolPref.brush; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (brush.brush()) { | 
					
						
							|  |  |  |       if (brush.brush()->type() == doc::kImageBrushType) { | 
					
						
							| 
									
										
										
										
											2022-07-15 21:05:50 +08:00
										 |  |  |         // Reset the colors of the image when we select the brush from
 | 
					
						
							|  |  |  |         // the slot.
 | 
					
						
							|  |  |  |         if (brush.hasFlag(BrushSlot::Flags::ImageColor)) | 
					
						
							|  |  |  |           brush.brush()->resetImageColors(); | 
					
						
							| 
									
										
										
										
											2015-12-17 04:27:04 +08:00
										 |  |  |         setActiveBrush(brush.brush()); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							|  |  |  |         if (brush.hasFlag(BrushSlot::Flags::BrushType)) | 
					
						
							|  |  |  |           brushPref.type(static_cast<app::gen::BrushType>(brush.brush()->type())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (brush.hasFlag(BrushSlot::Flags::BrushSize)) | 
					
						
							|  |  |  |           brushPref.size(brush.brush()->size()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (brush.hasFlag(BrushSlot::Flags::BrushAngle)) | 
					
						
							|  |  |  |           brushPref.angle(brush.brush()->angle()); | 
					
						
							| 
									
										
										
										
											2015-12-18 02:21:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         setActiveBrush(ContextBar::createBrushFromPreferences()); | 
					
						
							| 
									
										
										
										
											2015-12-17 04:27:04 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (brush.hasFlag(BrushSlot::Flags::FgColor)) | 
					
						
							|  |  |  |       pref.colorBar.fgColor(brush.fgColor()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (brush.hasFlag(BrushSlot::Flags::BgColor)) | 
					
						
							|  |  |  |       pref.colorBar.bgColor(brush.bgColor()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 21:14:41 +08:00
										 |  |  |     // If the image/stamp brush doesn't have the "ImageColor" flag, it
 | 
					
						
							|  |  |  |     // means that we have to change the image color to the current
 | 
					
						
							|  |  |  |     // "foreground color".
 | 
					
						
							|  |  |  |     if (brush.brush() && brush.brush()->type() == doc::kImageBrushType && | 
					
						
							|  |  |  |         !brush.hasFlag(BrushSlot::Flags::ImageColor)) { | 
					
						
							|  |  |  |       auto pixelFormat = brush.brush()->image()->pixelFormat(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       brush.brush()->setImageColor(Brush::ImageColor::MainColor, | 
					
						
							| 
									
										
										
										
											2017-06-30 01:24:28 +08:00
										 |  |  |                                    color_utils::color_for_target_mask( | 
					
						
							|  |  |  |                                      pref.colorBar.fgColor(), | 
					
						
							|  |  |  |                                      ColorTarget(ColorTarget::TransparentLayer, pixelFormat, -1))); | 
					
						
							| 
									
										
										
										
											2024-12-17 01:52:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 21:14:41 +08:00
										 |  |  |       brush.brush()->setImageColor(Brush::ImageColor::BackgroundColor, | 
					
						
							| 
									
										
										
										
											2017-06-30 01:24:28 +08:00
										 |  |  |                                    color_utils::color_for_target_mask( | 
					
						
							|  |  |  |                                      pref.colorBar.bgColor(), | 
					
						
							|  |  |  |                                      ColorTarget(ColorTarget::TransparentLayer, pixelFormat, -1))); | 
					
						
							| 
									
										
										
										
											2016-09-20 21:14:41 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 04:27:04 +08:00
										 |  |  |     if (brush.hasFlag(BrushSlot::Flags::InkType)) | 
					
						
							|  |  |  |       setInkType(brush.inkType()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (brush.hasFlag(BrushSlot::Flags::InkOpacity)) | 
					
						
							|  |  |  |       toolPref.opacity(brush.inkOpacity()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (brush.hasFlag(BrushSlot::Flags::Shade)) | 
					
						
							|  |  |  |       m_inkShades->setShade(brush.shade()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (brush.hasFlag(BrushSlot::Flags::PixelPerfect)) | 
					
						
							|  |  |  |       toolPref.freehandAlgorithm((brush.pixelPerfect() ? tools::FreehandAlgorithm::PIXEL_PERFECT : | 
					
						
							|  |  |  |                                                          tools::FreehandAlgorithm::REGULAR)); | 
					
						
							| 
									
										
										
										
											2015-05-07 04:39:40 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-12-16 04:12:11 +08:00
										 |  |  |   else { | 
					
						
							| 
									
										
										
										
											2016-09-12 23:19:12 +08:00
										 |  |  |     updateForTool(tool); | 
					
						
							| 
									
										
										
										
											2015-12-16 04:12:11 +08:00
										 |  |  |     m_brushType->showPopupAndHighlightSlot(slot); | 
					
						
							| 
									
										
										
										
											2015-05-07 04:39:40 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  | void ContextBar::setActiveBrush(const doc::BrushRef& brush) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-12-18 00:24:44 +08:00
										 |  |  |   if (brush->type() == kImageBrushType) | 
					
						
							|  |  |  |     m_activeBrush = brush; | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     Tool* tool = App::instance()->activeTool(); | 
					
						
							|  |  |  |     auto& brushPref = Preferences::instance().tool(tool).brush; | 
					
						
							|  |  |  |     auto newBrushType = static_cast<app::gen::BrushType>(brush->type()); | 
					
						
							|  |  |  |     if (brushPref.type() != newBrushType) | 
					
						
							|  |  |  |       brushPref.type(newBrushType); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_activeBrush = brush; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-07 00:05:06 +08:00
										 |  |  |   BrushChange(); | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-26 02:20:53 +08:00
										 |  |  |   updateForActiveTool(); | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-09 01:31:27 +08:00
										 |  |  | doc::BrushRef ContextBar::activeBrush(tools::Tool* tool, tools::Ink* ink) const | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-08-09 01:31:27 +08:00
										 |  |  |   if (ink == nullptr) | 
					
						
							|  |  |  |     ink = (tool ? tool->getInk(0) : nullptr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Selection tools use a brush with size = 1 (always)
 | 
					
						
							|  |  |  |   if (ink && ink->isSelection()) { | 
					
						
							|  |  |  |     doc::BrushRef brush; | 
					
						
							|  |  |  |     brush.reset(new Brush(kCircleBrushType, 1, 0)); | 
					
						
							|  |  |  |     return brush; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-21 12:20:59 +08:00
										 |  |  |   if ((tool == nullptr) || (tool == App::instance()->activeTool()) || | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  |       (ink && ink->isPaint() && m_activeBrush->type() == kImageBrushType)) { | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |     m_activeBrush->setPattern(Preferences::instance().brush.pattern()); | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  |     return m_activeBrush; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |   return ContextBar::createBrushFromPreferences(&Preferences::instance().tool(tool).brush); | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ContextBar::discardActiveBrush() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |   setActiveBrush(ContextBar::createBrushFromPreferences()); | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // static
 | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  | doc::BrushRef ContextBar::createBrushFromPreferences(ToolPreferences::Brush* brushPref) | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |   if (brushPref == nullptr) { | 
					
						
							|  |  |  |     tools::Tool* tool = App::instance()->activeTool(); | 
					
						
							|  |  |  |     brushPref = &Preferences::instance().tool(tool).brush; | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   doc::BrushRef brush; | 
					
						
							| 
									
										
										
										
											2015-05-19 03:53:25 +08:00
										 |  |  |   brush.reset(new Brush(static_cast<doc::BrushType>(brushPref->type()), | 
					
						
							|  |  |  |                         brushPref->size(), | 
					
						
							|  |  |  |                         brushPref->angle())); | 
					
						
							| 
									
										
										
										
											2015-04-29 05:21:33 +08:00
										 |  |  |   return brush; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-18 00:24:44 +08:00
										 |  |  | BrushSlot ContextBar::createBrushSlotFromPreferences() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-02-19 01:43:40 +08:00
										 |  |  |   tools::Tool* activeTool = App::instance()->activeTool(); | 
					
						
							| 
									
										
										
										
											2015-12-18 00:24:44 +08:00
										 |  |  |   auto& pref = Preferences::instance(); | 
					
						
							|  |  |  |   auto& saveBrush = pref.saveBrush; | 
					
						
							| 
									
										
										
										
											2016-02-19 01:43:40 +08:00
										 |  |  |   auto& toolPref = pref.tool(activeTool); | 
					
						
							| 
									
										
										
										
											2015-12-18 00:24:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   int flags = 0; | 
					
						
							|  |  |  |   if (saveBrush.brushType()) | 
					
						
							|  |  |  |     flags |= int(BrushSlot::Flags::BrushType); | 
					
						
							|  |  |  |   if (saveBrush.brushSize()) | 
					
						
							|  |  |  |     flags |= int(BrushSlot::Flags::BrushSize); | 
					
						
							|  |  |  |   if (saveBrush.brushAngle()) | 
					
						
							|  |  |  |     flags |= int(BrushSlot::Flags::BrushAngle); | 
					
						
							|  |  |  |   if (saveBrush.fgColor()) | 
					
						
							|  |  |  |     flags |= int(BrushSlot::Flags::FgColor); | 
					
						
							|  |  |  |   if (saveBrush.bgColor()) | 
					
						
							|  |  |  |     flags |= int(BrushSlot::Flags::BgColor); | 
					
						
							| 
									
										
										
										
											2016-09-20 21:14:41 +08:00
										 |  |  |   if (saveBrush.imageColor()) | 
					
						
							|  |  |  |     flags |= int(BrushSlot::Flags::ImageColor); | 
					
						
							| 
									
										
										
										
											2015-12-18 00:24:44 +08:00
										 |  |  |   if (saveBrush.inkType()) | 
					
						
							|  |  |  |     flags |= int(BrushSlot::Flags::InkType); | 
					
						
							|  |  |  |   if (saveBrush.inkOpacity()) | 
					
						
							|  |  |  |     flags |= int(BrushSlot::Flags::InkOpacity); | 
					
						
							|  |  |  |   if (saveBrush.shade()) | 
					
						
							|  |  |  |     flags |= int(BrushSlot::Flags::Shade); | 
					
						
							|  |  |  |   if (saveBrush.pixelPerfect()) | 
					
						
							|  |  |  |     flags |= int(BrushSlot::Flags::PixelPerfect); | 
					
						
							| 
									
										
										
										
											2024-12-17 01:52:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-18 00:24:44 +08:00
										 |  |  |   return BrushSlot(BrushSlot::Flags(flags), | 
					
						
							| 
									
										
										
										
											2016-02-19 01:43:40 +08:00
										 |  |  |                    activeBrush(activeTool), | 
					
						
							| 
									
										
										
										
											2015-12-18 00:24:44 +08:00
										 |  |  |                    pref.colorBar.fgColor(), | 
					
						
							|  |  |  |                    pref.colorBar.bgColor(), | 
					
						
							|  |  |  |                    toolPref.ink(), | 
					
						
							|  |  |  |                    toolPref.opacity(), | 
					
						
							|  |  |  |                    getShade(), | 
					
						
							|  |  |  |                    toolPref.freehandAlgorithm() == tools::FreehandAlgorithm::PIXEL_PERFECT); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 04:27:04 +08:00
										 |  |  | Shade ContextBar::getShade() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return m_inkShades->getShade(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  | doc::Remap* ContextBar::createShadeRemap(bool left) | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |   return m_inkShades->createShadeRemap(left); | 
					
						
							| 
									
										
										
										
											2015-08-27 03:48:01 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  | void ContextBar::reverseShadeColors() | 
					
						
							| 
									
										
										
										
											2015-11-21 05:44:08 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-11-25 05:37:13 +08:00
										 |  |  |   m_inkShades->reverseShadeColors(); | 
					
						
							| 
									
										
										
										
											2015-11-21 05:44:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-27 12:35:31 +08:00
										 |  |  | void ContextBar::setInkType(tools::InkType type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   m_inkType->setInkType(type); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-12 09:31:13 +08:00
										 |  |  | FontInfo ContextBar::fontInfo() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return m_fontSelector->info(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-07-15 10:17:25 +08:00
										 |  |  | FontEntry* ContextBar::fontEntry() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return m_fontSelector; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-24 07:41:30 +08:00
										 |  |  | render::DitheringMatrix ContextBar::ditheringMatrix() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return m_ditheringSelector->ditheringMatrix(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | render::DitheringAlgorithmBase* ContextBar::ditheringAlgorithm() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-08-09 04:27:26 +08:00
										 |  |  |   static std::unique_ptr<render::DitheringAlgorithmBase> s_dither; | 
					
						
							| 
									
										
										
										
											2017-05-24 07:41:30 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   switch (m_ditheringSelector->ditheringAlgorithm()) { | 
					
						
							|  |  |  |     case render::DitheringAlgorithm::None:    s_dither.reset(nullptr); break; | 
					
						
							|  |  |  |     case render::DitheringAlgorithm::Ordered: s_dither.reset(new render::OrderedDither2(-1)); break; | 
					
						
							|  |  |  |     case render::DitheringAlgorithm::Old:     s_dither.reset(new render::OrderedDither(-1)); break; | 
					
						
							| 
									
										
										
										
											2019-04-02 08:44:06 +08:00
										 |  |  |     case render::DitheringAlgorithm::ErrorDiffusion: | 
					
						
							|  |  |  |       s_dither.reset(new render::ErrorDiffusionDither(-1)); | 
					
						
							|  |  |  |       break; | 
					
						
							| 
									
										
										
										
											2017-05-24 07:41:30 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return s_dither.get(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-20 07:54:25 +08:00
										 |  |  | render::GradientType ContextBar::gradientType() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return m_gradientType->gradientType(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-05 03:15:57 +08:00
										 |  |  | const tools::DynamicsOptions& ContextBar::getDynamics() const | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  | { | 
					
						
							|  |  |  |   return m_dynamics->getDynamics(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-23 21:16:37 +08:00
										 |  |  | void ContextBar::setupTooltips(TooltipManager* tooltipManager) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |   tooltipManager->addTooltipFor(m_brushBack->at(0), Strings::context_bar_discard_brush(), BOTTOM); | 
					
						
							|  |  |  |   tooltipManager->addTooltipFor(m_brushType->at(0), Strings::context_bar_brush_type(), BOTTOM); | 
					
						
							|  |  |  |   tooltipManager->addTooltipFor(m_brushSize, Strings::context_bar_brush_size(), BOTTOM); | 
					
						
							|  |  |  |   tooltipManager->addTooltipFor(m_brushAngle, Strings::context_bar_brush_angle(), BOTTOM); | 
					
						
							|  |  |  |   tooltipManager->addTooltipFor(m_inkType->at(0), Strings::context_bar_ink(), BOTTOM); | 
					
						
							|  |  |  |   tooltipManager->addTooltipFor(m_inkOpacity, Strings::context_bar_opacity(), BOTTOM); | 
					
						
							|  |  |  |   tooltipManager->addTooltipFor(m_inkShades->at(0), Strings::context_bar_shades(), BOTTOM); | 
					
						
							|  |  |  |   tooltipManager->addTooltipFor(m_sprayWidth, Strings::context_bar_spray_width(), BOTTOM); | 
					
						
							|  |  |  |   tooltipManager->addTooltipFor(m_spraySpeed, Strings::context_bar_spray_speed(), BOTTOM); | 
					
						
							|  |  |  |   tooltipManager->addTooltipFor(m_pivot->at(0), Strings::context_bar_rotation_pivot(), BOTTOM); | 
					
						
							|  |  |  |   tooltipManager->addTooltipFor(m_rotAlgo, Strings::context_bar_rotation_algorithm(), BOTTOM); | 
					
						
							|  |  |  |   tooltipManager->addTooltipFor(m_dynamics->at(0), Strings::context_bar_dynamics(), BOTTOM); | 
					
						
							| 
									
										
										
										
											2023-12-23 02:03:07 +08:00
										 |  |  |   tooltipManager->addTooltipFor(m_freehandAlgo, | 
					
						
							|  |  |  |                                 key_tooltip(Strings::context_bar_freehand_trace_algorithm().c_str(), | 
					
						
							|  |  |  |                                             CommandId::PixelPerfectMode()), | 
					
						
							|  |  |  |                                 BOTTOM); | 
					
						
							|  |  |  |   tooltipManager->addTooltipFor( | 
					
						
							|  |  |  |     m_contiguous, | 
					
						
							|  |  |  |     key_tooltip(Strings::context_bar_contiguous_fill().c_str(), CommandId::ContiguousFill()), | 
					
						
							|  |  |  |     BOTTOM); | 
					
						
							| 
									
										
										
										
											2022-01-03 16:02:19 +08:00
										 |  |  |   tooltipManager->addTooltipFor(m_paintBucketSettings->at(0), | 
					
						
							|  |  |  |                                 Strings::context_bar_paint_bucket_option(), | 
					
						
							|  |  |  |                                 BOTTOM); | 
					
						
							| 
									
										
										
										
											2017-06-23 21:16:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   m_selectionMode->setupTooltips(tooltipManager); | 
					
						
							| 
									
										
										
										
											2019-03-20 07:54:25 +08:00
										 |  |  |   m_gradientType->setupTooltips(tooltipManager); | 
					
						
							| 
									
										
										
										
											2017-06-23 21:16:37 +08:00
										 |  |  |   m_dropPixels->setupTooltips(tooltipManager); | 
					
						
							|  |  |  |   m_symmetry->setupTooltips(tooltipManager); | 
					
						
							| 
									
										
										
										
											2019-05-07 21:28:37 +08:00
										 |  |  |   m_sliceFields->setupTooltips(tooltipManager); | 
					
						
							| 
									
										
										
										
											2025-08-07 00:21:10 +08:00
										 |  |  |   m_transformation->setupTooltips(tooltipManager); | 
					
						
							| 
									
										
										
										
											2017-06-23 21:16:37 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-01 03:23:31 +08:00
										 |  |  | void ContextBar::registerCommands() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Commands::instance()->add( | 
					
						
							|  |  |  |     new QuickCommand(CommandId::ShowBrushes(), [this] { this->showBrushes(); })); | 
					
						
							| 
									
										
										
										
											2024-12-17 01:52:19 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  |   Commands::instance()->add( | 
					
						
							|  |  |  |     new QuickCommand(CommandId::ShowDynamics(), [this] { this->showDynamics(); })); | 
					
						
							| 
									
										
										
										
											2017-12-01 03:23:31 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ContextBar::showBrushes() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  |   if (m_brushType->isVisible()) | 
					
						
							| 
									
										
										
										
											2020-05-02 00:38:12 +08:00
										 |  |  |     m_brushType->switchPopup(); | 
					
						
							| 
									
										
										
										
											2020-04-22 09:27:49 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void ContextBar::showDynamics() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (m_dynamics->isVisible()) | 
					
						
							| 
									
										
										
										
											2020-05-02 00:38:12 +08:00
										 |  |  |     m_dynamics->switchPopup(); | 
					
						
							| 
									
										
										
										
											2017-12-01 03:23:31 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-22 02:30:09 +08:00
										 |  |  | bool ContextBar::needZoomButtons(tools::Tool* tool) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return tool && (tool->getInk(0)->isZoom() || tool->getInk(1)->isZoom() || | 
					
						
							|  |  |  |                   tool->getInk(0)->isScrollMovement() || tool->getInk(1)->isScrollMovement()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | } // namespace app
 |