From 7062261b0e02b26faf9879f045d7a0ddcc47a49e Mon Sep 17 00:00:00 2001 From: ftomara Date: Sat, 24 May 2025 00:05:53 +0300 Subject: [PATCH 001/122] made the tab and added the colorpicker widget --- .../actions/object-recolor-art-symbolic.svg | 5 ++ .../actions/object-recolor-art-symbolic.svg | 5 ++ share/ui/recolor-art.glade | 30 ++++++++ src/ui/CMakeLists.txt | 4 +- src/ui/dialog/fill-and-stroke.cpp | 38 ++++++++++ src/ui/dialog/fill-and-stroke.h | 6 ++ src/ui/widget/recolor-art.cpp | 73 +++++++++++++++++++ src/ui/widget/recolor-art.h | 59 +++++++++++++++ 8 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 share/icons/Dash/symbolic/actions/object-recolor-art-symbolic.svg create mode 100644 share/icons/multicolor/symbolic/actions/object-recolor-art-symbolic.svg create mode 100644 share/ui/recolor-art.glade create mode 100644 src/ui/widget/recolor-art.cpp create mode 100644 src/ui/widget/recolor-art.h diff --git a/share/icons/Dash/symbolic/actions/object-recolor-art-symbolic.svg b/share/icons/Dash/symbolic/actions/object-recolor-art-symbolic.svg new file mode 100644 index 0000000000..b078cf421c --- /dev/null +++ b/share/icons/Dash/symbolic/actions/object-recolor-art-symbolic.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/share/icons/multicolor/symbolic/actions/object-recolor-art-symbolic.svg b/share/icons/multicolor/symbolic/actions/object-recolor-art-symbolic.svg new file mode 100644 index 0000000000..b078cf421c --- /dev/null +++ b/share/icons/multicolor/symbolic/actions/object-recolor-art-symbolic.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade new file mode 100644 index 0000000000..3129e8df84 --- /dev/null +++ b/share/ui/recolor-art.glade @@ -0,0 +1,30 @@ + + + + + recolor-art + vertical + true + true + + + + + vertical + true + + + + + + + Apply + end + end + 6 + 6 + + + + + \ No newline at end of file diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 314919702b..ac483291ec 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -298,10 +298,10 @@ set(ui_SRC widget/widget-vfuncs-class-init.cpp widget/xml-treeview.cpp widget/property-utils.cpp + widget/recolor-art.cpp view/svg-view-widget.cpp - # ------- # Headers builder-utils.h @@ -626,6 +626,8 @@ set(ui_SRC widget/xml-treeview.h widget/property-utils.h + widget/recolor-art.h + view/svg-view-widget.h ) diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index a60cbf731f..1bcdd92052 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -28,6 +28,7 @@ #include "ui/pack.h" #include "ui/widget/fill-style.h" #include "ui/widget/stroke-style.h" +#include "ui/widget/recolor-art.h" #include "ui/widget/notebook-page.h" namespace Inkscape::UI::Dialog { @@ -37,6 +38,7 @@ FillAndStroke::FillAndStroke() , _page_fill(Gtk::make_managed(1, 1)) , _page_stroke_paint(Gtk::make_managed(1, 1)) , _page_stroke_style(Gtk::make_managed(1, 1)) + , _page_recolor_art(Gtk::make_managed(1, 1)) , _composite_settings(INKSCAPE_ICON("dialog-fill-and-stroke"), "fillstroke", UI::Widget::SimpleFilterModifier::ISOLATION | @@ -45,6 +47,7 @@ FillAndStroke::FillAndStroke() UI::Widget::SimpleFilterModifier::OPACITY) , fillWdgt(nullptr) , strokeWdgt(nullptr) + ,recolorArtWdgt(nullptr) { set_spacing(2); UI::pack_start(*this, _notebook, true, true); @@ -52,6 +55,7 @@ FillAndStroke::FillAndStroke() _notebook.append_page(*_page_fill, _createPageTabLabel(_("_Fill"), INKSCAPE_ICON("object-fill"))); _notebook.append_page(*_page_stroke_paint, _createPageTabLabel(_("Stroke _paint"), INKSCAPE_ICON("object-stroke"))); _notebook.append_page(*_page_stroke_style, _createPageTabLabel(_("Stroke st_yle"), INKSCAPE_ICON("object-stroke-style"))); + _notebook.append_page(*_page_recolor_art, _createPageTabLabel(_("Recolor Art"), INKSCAPE_ICON("object-recolor-art"))); _notebook.set_vexpand(true); _switch_page_conn = _notebook.signal_switch_page().connect(sigc::mem_fun(*this, &FillAndStroke::_onSwitchPage)); @@ -59,6 +63,7 @@ FillAndStroke::FillAndStroke() _layoutPageFill(); _layoutPageStrokePaint(); _layoutPageStrokeStyle(); + _layoutPageRecolorArt(); UI::pack_end(*this, _composite_settings, UI::PackOptions::shrink); @@ -72,6 +77,7 @@ FillAndStroke::~FillAndStroke() fillWdgt->setDesktop(nullptr); strokeWdgt->setDesktop(nullptr); strokeStyleWdgt->setDesktop(nullptr); + recolorArtWdgt->setDesktop(nullptr); _subject.setDesktop(nullptr); } @@ -81,6 +87,7 @@ void FillAndStroke::selectionChanged(Selection *selection) changed_fill = true; changed_stroke = true; changed_stroke_style = true; + changed_recolor_art = true; } if (fillWdgt && npage == 0) { fillWdgt->performUpdate(); @@ -91,6 +98,9 @@ void FillAndStroke::selectionChanged(Selection *selection) if (strokeStyleWdgt && npage == 2) { strokeStyleWdgt->selectionChangedCB(); } + if (recolorArtWdgt && npage == 3) { + recolorArtWdgt->performUpdate(); + } } void FillAndStroke::selectionModified(Selection *selection, guint flags) @@ -98,6 +108,7 @@ void FillAndStroke::selectionModified(Selection *selection, guint flags) changed_fill = true; changed_stroke = true; changed_stroke_style = true; + changed_recolor_art = true; if (fillWdgt && npage == 0) { fillWdgt->selectionModifiedCB(flags); } @@ -107,6 +118,9 @@ void FillAndStroke::selectionModified(Selection *selection, guint flags) if (strokeStyleWdgt && npage == 2) { strokeStyleWdgt->selectionModifiedCB(flags); } + if (recolorArtWdgt && npage == 3) { + recolorArtWdgt->performUpdate(); + } } void FillAndStroke::desktopReplaced() @@ -114,6 +128,7 @@ void FillAndStroke::desktopReplaced() changed_fill = true; changed_stroke = true; changed_stroke_style = true; + changed_recolor_art = true; if (fillWdgt) { fillWdgt->setDesktop(getDesktop()); } @@ -122,6 +137,9 @@ void FillAndStroke::desktopReplaced() } if (strokeStyleWdgt) { strokeStyleWdgt->setDesktop(getDesktop()); + } + if (recolorArtWdgt) { + recolorArtWdgt->setDesktop(getDesktop()); } _subject.setDesktop(getDesktop()); } @@ -140,6 +158,9 @@ void FillAndStroke::_onSwitchPage(Gtk::Widget * page, guint pagenum) } else if (npage == 2 && changed_stroke_style) { update = true; changed_stroke_style = false; + }else if (npage == 3 && changed_recolor_art) { + update = true; + changed_recolor_art = false; } if (update) { page_changed = true; @@ -180,6 +201,14 @@ FillAndStroke::_layoutPageStrokeStyle() strokeStyleWdgt->set_halign(Gtk::Align::START); _page_stroke_style->table().attach(*strokeStyleWdgt, 0, 0, 1, 1); } +void +FillAndStroke::_layoutPageRecolorArt() +{ + recolorArtWdgt = Gtk::make_managed(); + recolorArtWdgt->set_hexpand(); + recolorArtWdgt->set_halign(Gtk::Align::FILL); + _page_recolor_art->table().attach(*recolorArtWdgt,0,0,1,1); +} void FillAndStroke::showPageFill() @@ -207,6 +236,15 @@ FillAndStroke::showPageStrokeStyle() } +void +FillAndStroke::showPageRecolorArt() +{ + blink(); + _notebook.set_current_page(3); + _savePagePref(3); + +} + Gtk::Box& FillAndStroke::_createPageTabLabel(const Glib::ustring& label, const char *label_image) { diff --git a/src/ui/dialog/fill-and-stroke.h b/src/ui/dialog/fill-and-stroke.h index 0a918df2f0..24d8c5f6eb 100644 --- a/src/ui/dialog/fill-and-stroke.h +++ b/src/ui/dialog/fill-and-stroke.h @@ -32,6 +32,7 @@ namespace Widget { class FillNStroke; class NotebookPage; class StrokeStyle; +class RecolorArt; } // namespace Widget namespace Dialog { @@ -47,6 +48,7 @@ public: void showPageFill(); void showPageStrokePaint(); void showPageStrokeStyle(); + void showPageRecolorArt(); protected: Gtk::Notebook _notebook; @@ -54,6 +56,7 @@ protected: UI::Widget::NotebookPage *_page_fill = nullptr; UI::Widget::NotebookPage *_page_stroke_paint = nullptr; UI::Widget::NotebookPage *_page_stroke_style = nullptr; + UI::Widget::NotebookPage *_page_recolor_art = nullptr; UI::Widget::StyleSubject::Selection _subject; UI::Widget::ObjectCompositeSettings _composite_settings; @@ -64,6 +67,7 @@ protected: void _layoutPageFill(); void _layoutPageStrokePaint(); void _layoutPageStrokeStyle(); + void _layoutPageRecolorArt(); void _savePagePref(guint page_num); void _onSwitchPage(Gtk::Widget *page, guint pagenum); @@ -75,9 +79,11 @@ private: bool changed_fill = true; bool changed_stroke = true; bool changed_stroke_style = true; + bool changed_recolor_art = true; UI::Widget::FillNStroke *fillWdgt = nullptr; UI::Widget::FillNStroke *strokeWdgt = nullptr; UI::Widget::StrokeStyle *strokeStyleWdgt = nullptr; + UI::Widget::RecolorArt *recolorArtWdgt = nullptr; sigc::scoped_connection _switch_page_conn; }; diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp new file mode 100644 index 0000000000..dd645039bd --- /dev/null +++ b/src/ui/widget/recolor-art.cpp @@ -0,0 +1,73 @@ +#include "recolor-art.h" + +#include +#include + +#include "actions/actions-tools.h" +#include "desktop-style.h" +#include "desktop.h" +#include "document-undo.h" +#include "document.h" +#include "gradient-chemistry.h" +#include "object/sp-defs.h" +#include "object/sp-linear-gradient.h" +#include "object/sp-mesh-gradient.h" +#include "object/sp-object.h" +#include "object/sp-pattern.h" +#include "object/sp-radial-gradient.h" +#include "object/sp-stop.h" +#include "object/sp-text.h" +#include "object/sp-use.h" +#include "pattern-manipulation.h" +#include "selection.h" +#include "style.h" +#include "ui/builder-utils.h" +#include "ui/dialog/dialog-base.h" +#include "ui/icon-names.h" +#include "ui/widget/color-notebook.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +RecolorArt::RecolorArt() + : Gtk::Box() + , _builder(create_builder("recolor-art.glade")) + , _solid_colors(std::make_shared()) + +{ + set_name("RecolorArt"); + append(get_widget(_builder, "recolor-art")); + _solid_colors->set(Color(0x000000ff)); + _layoutColorPicker(); +} +RecolorArt::~RecolorArt() {} + +void RecolorArt::setDesktop(SPDesktop *desktop) +{ + if (_desktop != desktop) { + _desktop = desktop; + } + g_message("setDesktop\n"); +} +void RecolorArt::_layoutColorPicker() +{ + _colorPickerWdgt = Gtk::make_managed(_solid_colors); + _colorPickerWdgt->set_visible(true); + _colorPickerWdgt->set_label(_("Selected Color")); + + auto container = _builder->get_widget("color-picker"); + if (container) { + container->append(*_colorPickerWdgt); + } else { + g_warning("color picker not found"); + } +} + +void RecolorArt::performUpdate() +{ + g_message("Performing Update\n"); +} +} // namespace Widget +} // namespace UI +} // namespace Inkscape \ No newline at end of file diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h new file mode 100644 index 0000000000..d12c204db3 --- /dev/null +++ b/src/ui/widget/recolor-art.h @@ -0,0 +1,59 @@ + + +#ifndef SEEN_DIALOGS_SP_RECOLOR_ART_H +#define SEEN_DIALOGS_SP_RECOLOR_ART_H + +#include + +#include "ui/widget/paint-selector.h" + +using namespace Inkscape::Colors; + +namespace Inkscape::Colors { +class Color; +class ColorSet; +namespace Space { +class AnySpace; +} +} // namespace Inkscape::Colors + +namespace Gtk { +class Widget; +class Builder; +} // namespace Gtk + +class SPDesktop; + +namespace Inkscape { +namespace UI { +namespace Tools { +class ToolBase; +} + +namespace Widget { +class ColorNotebook; + +class RecolorArt : public Gtk::Box +{ +private: + SPDesktop *_desktop = nullptr; + std::shared_ptr _solid_colors; + Inkscape::UI::Widget::ColorNotebook *_colorPickerWdgt = nullptr; + +protected: + Glib::RefPtr _builder; + void _layoutColorPicker(); + +public: + RecolorArt(); + ~RecolorArt(); + + void performUpdate(); + void setDesktop(SPDesktop *desktop); +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // SEEN_DIALOGS_SP_RECOLOR_ART_H -- GitLab From 18f87dba3b3c982dfa236bfab077061c8a9c5a3c Mon Sep 17 00:00:00 2001 From: ftomara Date: Sat, 24 May 2025 13:46:47 +0300 Subject: [PATCH 002/122] added colors list to the glade file --- .../symbolic/actions/arrow-symbolic.svg | 3 + .../actions/reset-colors-symbolic.svg | 4 ++ share/ui/recolor-art.glade | 72 +++++++++++++++++-- 3 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 share/icons/multicolor/symbolic/actions/arrow-symbolic.svg create mode 100644 share/icons/multicolor/symbolic/actions/reset-colors-symbolic.svg diff --git a/share/icons/multicolor/symbolic/actions/arrow-symbolic.svg b/share/icons/multicolor/symbolic/actions/arrow-symbolic.svg new file mode 100644 index 0000000000..f387849bc8 --- /dev/null +++ b/share/icons/multicolor/symbolic/actions/arrow-symbolic.svg @@ -0,0 +1,3 @@ + + + diff --git a/share/icons/multicolor/symbolic/actions/reset-colors-symbolic.svg b/share/icons/multicolor/symbolic/actions/reset-colors-symbolic.svg new file mode 100644 index 0000000000..7d47572893 --- /dev/null +++ b/share/icons/multicolor/symbolic/actions/reset-colors-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 3129e8df84..6df02059d3 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -1,20 +1,78 @@ - + recolor-art vertical true true - + + + original-reset-recolor + horizontal + center + center + 80 + + + Original + center + + + + + true + false + false + + + reset-colors + normal + + + + + + + Recolored + center + + + + + + + colors-list + horizontal + center + center + 24 + + + center + + + + + arrow + large + + + + + center + + + + + - vertical - true - + vertical + true - + @@ -24,7 +82,7 @@ 6 6 - + \ No newline at end of file -- GitLab From 69fb551db3f98cb0d6b9b6f1b776ed4fa50801d7 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sat, 24 May 2025 15:21:58 +0300 Subject: [PATCH 003/122] added colors list and checkbutton to the glade file --- share/ui/recolor-art.glade | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 6df02059d3..7ee45fad33 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -75,12 +75,26 @@ - - Apply - end - end - 6 - 6 + + liveP-apply + horizontal + 300 + + + liveP + Live Preview + end + start + + + + + apply + Apply + end + end + + -- GitLab From e8ad0815ff36828626ba4e44d4908b131e2a0870 Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 27 May 2025 01:11:44 +0300 Subject: [PATCH 004/122] collect fills & strokes make the colorList buttons --- share/ui/recolor-art.glade | 12 ++-- src/ui/widget/recolor-art.cpp | 123 +++++++++++++++++++++++++++++++++- src/ui/widget/recolor-art.h | 19 +++++- 3 files changed, 145 insertions(+), 9 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 7ee45fad33..4ebcb7fc25 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -45,26 +45,26 @@ colors-list - horizontal + vertical center center 24 - - + diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index dd645039bd..af3f0c1719 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -1,9 +1,14 @@ #include "recolor-art.h" #include +#include +#include #include +#include +#include #include "actions/actions-tools.h" +#include "canvas.h" #include "desktop-style.h" #include "desktop.h" #include "document-undo.h" @@ -20,6 +25,7 @@ #include "object/sp-use.h" #include "pattern-manipulation.h" #include "selection.h" +#include "style-internal.h" #include "style.h" #include "ui/builder-utils.h" #include "ui/dialog/dialog-base.h" @@ -40,6 +46,7 @@ RecolorArt::RecolorArt() append(get_widget(_builder, "recolor-art")); _solid_colors->set(Color(0x000000ff)); _layoutColorPicker(); + _colorList = _builder->get_widget("colors-list"); } RecolorArt::~RecolorArt() {} @@ -50,6 +57,80 @@ void RecolorArt::setDesktop(SPDesktop *desktop) } g_message("setDesktop\n"); } +void RecolorArt::_collectColors(std::vector items) +{ + _selected_colors.clear(); + for (auto item : items) { + _extractItemColors(item); + } +} +void RecolorArt::_extractItemColors(SPItem *item) +{ + if (item) { + _extractItemStyle(item); + } + if (auto group = dynamic_cast(item)) { + for (SPObject &child : group->children) { + if (auto childItem = dynamic_cast(&child)) { + _extractItemColors(childItem); + } + } + } +} +void RecolorArt::_extractGradientStops(SPGradient *item) {} +void RecolorArt::_populateMap(Color color, SPItem *item, std::string kind) +{ + ColorRef ref = ColorRef(item, kind); + if (_selected_colors.count(color.toString())) { + _selected_colors[color.toString()].first.push_back(ref); + } else { + _selected_colors.emplace(color.toString(), std::make_pair(std::vector{ref}, color)); + } +} +void RecolorArt::_extractItemStyle(SPItem *item) +{ + // check item style + if (!item || !item->style) + return; + + SPStyle *style = item->style; + // get flat fills + if (style->fill.isColor()) { + auto color = style->fill.getColor(); + _populateMap(color, item, "fill"); + } + // get gradient stops strokes + else if (style->fill.isPaintserver()) { + } + + if (style->stroke.isColor()) { + auto color = style->stroke.getColor(); + _populateMap(color, item, "stroke"); + } + // get gradient stops strokes + else if (style->stroke.isPaintserver()) { + } +} +void RecolorArt::_generateVisualList() +{ + if (_colorList) { + for (auto [key, value] : _selected_colors) { + auto box = std::make_unique(Gtk::Orientation::HORIZONTAL, 24); + auto original = std::make_unique(); + original->set_name("original_" + key); + _colorButtons(original.get(), key, "original_" + key); + + auto recolored = std::make_unique(); + auto arrow = std::make_unique(); + arrow->set_from_icon_name("arrow"); + // TODO : set recolored when getting signals from clicked original + box->append(*original); + box->append(*arrow); + box->append(*recolored); + _colorList->append(*box); + } + } +} void RecolorArt::_layoutColorPicker() { _colorPickerWdgt = Gtk::make_managed(_solid_colors); @@ -63,11 +144,49 @@ void RecolorArt::_layoutColorPicker() g_warning("color picker not found"); } } - +void RecolorArt::_colorButtons(Gtk::Button *button, std::string color, std::string id) +{ + if (button) { + auto css_provider = Gtk::CssProvider::create(); + Glib::ustring css = "button { background-color: " + Glib::ustring(color) + "; background-image: none;}"; + css_provider->load_from_data(css); + auto style_context = button->get_style_context(); + style_context->add_provider(css_provider, GTK_STYLE_PROVIDER_PRIORITY_USER); + } else { + g_message("button not found"); + } +} void RecolorArt::performUpdate() { + for (auto child : _colorList->get_children()) { + _colorList->remove(*child); + } + if (auto selection = _desktop->getSelection()) { + std::vector vec(selection->items().begin(), selection->items().end()); + _collectColors(vec); + if (!_selected_colors.empty()) { + _generateVisualList(); + } + } + g_message("Performing Update\n"); } } // namespace Widget } // namespace UI -} // namespace Inkscape \ No newline at end of file +} // namespace Inkscape + +// for (auto [key, value] : _selected_colors) { +// std::cout << key << " : "; +// for (auto item : value.first) { +// std::cout << item.item << " , "; +// if (item.kind == "fill" && key == "#000000") { +// uint32_t rgba = 0xFF00FFFF; +// Color c(rgba, true); +// SPCSSAttr *css = sp_repr_css_attr_new(); +// sp_repr_css_set_property_string(css, "fill", c.toString(false)); +// sp_desktop_apply_css_recursive(item.item, css, true); +// sp_repr_css_attr_unref(css); +// } +// } +// std::cout << std::endl; +// } \ No newline at end of file diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index d12c204db3..44757b58f9 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -5,6 +5,9 @@ #include +#include "canvas.h" +#include "style-internal.h" +#include "style.h" #include "ui/widget/paint-selector.h" using namespace Inkscape::Colors; @@ -33,21 +36,35 @@ class ToolBase; namespace Widget { class ColorNotebook; +struct ColorRef +{ + SPItem *item; + std::string kind; +}; + class RecolorArt : public Gtk::Box { private: SPDesktop *_desktop = nullptr; std::shared_ptr _solid_colors; + std::map, std::optional>> _selected_colors; Inkscape::UI::Widget::ColorNotebook *_colorPickerWdgt = nullptr; + Gtk::Box *_colorList = nullptr; protected: Glib::RefPtr _builder; + void _populateMap(Color color, SPItem *style, std::string kind); + void _collectColors(std::vector items); + void _extractGradientStops(SPGradient *item); + void _extractItemColors(SPItem *item); + void _extractItemStyle(SPItem *item); + void _generateVisualList(); void _layoutColorPicker(); + void _colorButtons(Gtk::Button *button, std::string color, std::string id); public: RecolorArt(); ~RecolorArt(); - void performUpdate(); void setDesktop(SPDesktop *desktop); }; -- GitLab From 0c7add5b653ffc51177e0ce6e30bb958b564fdfa Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 27 May 2025 01:59:30 +0300 Subject: [PATCH 005/122] added gradient stops to colorsList --- src/ui/widget/recolor-art.cpp | 20 ++++++++++++++++++-- src/ui/widget/recolor-art.h | 2 +- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index af3f0c1719..c9eff21188 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -15,6 +15,7 @@ #include "document.h" #include "gradient-chemistry.h" #include "object/sp-defs.h" +#include "object/sp-gradient.h" #include "object/sp-linear-gradient.h" #include "object/sp-mesh-gradient.h" #include "object/sp-object.h" @@ -77,7 +78,18 @@ void RecolorArt::_extractItemColors(SPItem *item) } } } -void RecolorArt::_extractGradientStops(SPGradient *item) {} +void RecolorArt::_extractGradientStops(SPItem *item, std::string kind, bool isFill) +{ + SPPaintServer *paint_server = isFill ? item->style->getFillPaintServer() : item->style->getStrokePaintServer(); + if (paint_server && dynamic_cast(paint_server)) { + SPGradient *gradient = dynamic_cast(paint_server); + for (auto stop : gradient->getGradientVector().stops) { + if (stop.color.has_value()) { + _populateMap(stop.color.value(), item, kind); + } + } + } +} void RecolorArt::_populateMap(Color color, SPItem *item, std::string kind) { ColorRef ref = ColorRef(item, kind); @@ -101,6 +113,7 @@ void RecolorArt::_extractItemStyle(SPItem *item) } // get gradient stops strokes else if (style->fill.isPaintserver()) { + _extractGradientStops(item, "stop-fill", true); } if (style->stroke.isColor()) { @@ -109,6 +122,7 @@ void RecolorArt::_extractItemStyle(SPItem *item) } // get gradient stops strokes else if (style->stroke.isPaintserver()) { + _extractGradientStops(item, "stop-stoke", false); } } void RecolorArt::_generateVisualList() @@ -116,7 +130,9 @@ void RecolorArt::_generateVisualList() if (_colorList) { for (auto [key, value] : _selected_colors) { auto box = std::make_unique(Gtk::Orientation::HORIZONTAL, 24); - auto original = std::make_unique(); + box->set_halign(Gtk::Align::CENTER); + box->set_valign(Gtk::Align::CENTER); + auto original = std::make_unique(); original->set_name("original_" + key); _colorButtons(original.get(), key, "original_" + key); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 44757b58f9..a3ddc2ab83 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -55,7 +55,7 @@ protected: Glib::RefPtr _builder; void _populateMap(Color color, SPItem *style, std::string kind); void _collectColors(std::vector items); - void _extractGradientStops(SPGradient *item); + void _extractGradientStops(SPItem *item, std::string kind, bool isFill); void _extractItemColors(SPItem *item); void _extractItemStyle(SPItem *item); void _generateVisualList(); -- GitLab From 990e79d613088191420ac28aec5cee6d7e41cd3a Mon Sep 17 00:00:00 2001 From: ftomara Date: Sat, 31 May 2025 23:33:53 +0300 Subject: [PATCH 006/122] reflected original color on the colorpicker updated recolorbutton with updated color from colorpicker --- src/ui/widget/recolor-art.cpp | 98 ++++++++++++++++++++++++++++------- src/ui/widget/recolor-art.h | 20 +++++-- 2 files changed, 95 insertions(+), 23 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index c9eff21188..e857fba960 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -9,6 +10,7 @@ #include "actions/actions-tools.h" #include "canvas.h" +#include "color-notebook.h" #include "desktop-style.h" #include "desktop.h" #include "document-undo.h" @@ -31,7 +33,6 @@ #include "ui/builder-utils.h" #include "ui/dialog/dialog-base.h" #include "ui/icon-names.h" -#include "ui/widget/color-notebook.h" namespace Inkscape { namespace UI { @@ -46,8 +47,14 @@ RecolorArt::RecolorArt() set_name("RecolorArt"); append(get_widget(_builder, "recolor-art")); _solid_colors->set(Color(0x000000ff)); + _layoutColorPicker(); - _colorList = _builder->get_widget("colors-list"); + _color_list = _builder->get_widget("colors-list"); + _apply = _builder->get_widget("apply"); + _live_preview = _builder->get_widget("liveP"); + + _apply->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::_onApplyButtonClicked)); + _live_preview->signal_toggled().connect(sigc::mem_fun(*this, &RecolorArt::_onLivePreviewToggled)); } RecolorArt::~RecolorArt() {} @@ -127,41 +134,55 @@ void RecolorArt::_extractItemStyle(SPItem *item) } void RecolorArt::_generateVisualList() { - if (_colorList) { + if (_color_list) { for (auto [key, value] : _selected_colors) { - auto box = std::make_unique(Gtk::Orientation::HORIZONTAL, 24); + auto box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL, 24); box->set_halign(Gtk::Align::CENTER); box->set_valign(Gtk::Align::CENTER); - auto original = std::make_unique(); - original->set_name("original_" + key); - _colorButtons(original.get(), key, "original_" + key); - - auto recolored = std::make_unique(); - auto arrow = std::make_unique(); + auto original = Gtk::make_managed(); + original->set_name(key); + _colorButtons(original, key); + original->signal_clicked().connect( + sigc::bind(sigc::mem_fun(*this, &RecolorArt::_onOriginalColorClicked), original->get_name())); + auto recolored = Gtk::make_managed(); + recolored->set_name("recolored_from" + key); + _colorButtons(recolored, Color(0xffffff00).toString()); + buttons[key] = {original, recolored}; + auto arrow = Gtk::make_managed(); arrow->set_from_icon_name("arrow"); // TODO : set recolored when getting signals from clicked original box->append(*original); box->append(*arrow); box->append(*recolored); - _colorList->append(*box); + _color_list->append(*box); } } } -void RecolorArt::_layoutColorPicker() +void RecolorArt::_layoutColorPicker(std::shared_ptr updated_color) { - _colorPickerWdgt = Gtk::make_managed(_solid_colors); - _colorPickerWdgt->set_visible(true); - _colorPickerWdgt->set_label(_("Selected Color")); + if (updated_color) + _solid_colors = updated_color; + _color_picker_wdgt = Gtk::make_managed(_solid_colors); + _color_picker_wdgt->set_visible(true); + _color_picker_wdgt->set_label(_("Selected Color")); + _solid_colors->signal_changed.connect(sigc::mem_fun(*this, &RecolorArt::_onColorPickerChanged)); auto container = _builder->get_widget("color-picker"); if (container) { - container->append(*_colorPickerWdgt); + for (auto child : container->get_children()) + container->remove(*child); + container->append(*_color_picker_wdgt); } else { g_warning("color picker not found"); } } -void RecolorArt::_colorButtons(Gtk::Button *button, std::string color, std::string id) +void RecolorArt::_colorButtons(Gtk::Button *button, std::string color) { + if (color.empty() || color.size() < 7 || color[0] != '#') { + g_warning("Invalid color string: %s", color.c_str()); + return; + } + if (button) { auto css_provider = Gtk::CssProvider::create(); Glib::ustring css = "button { background-color: " + Glib::ustring(color) + "; background-image: none;}"; @@ -172,11 +193,50 @@ void RecolorArt::_colorButtons(Gtk::Button *button, std::string color, std::stri g_message("button not found"); } } + +void RecolorArt::_onOriginalColorClicked(std::string color_id) +{ + _current_color_id = color_id; + auto it = _selected_colors.find(color_id); + if (it != _selected_colors.end() && it->second.second.has_value()) { + Color color = it->second.second.value(); + std::shared_ptr updated_color = std::make_shared(); + updated_color->set(color); + _layoutColorPicker(updated_color); + // g_message("original color selected at color %s", color_id.c_str()); + } +} +void RecolorArt::_onColorPickerChanged() +{ + auto it = buttons.find(_current_color_id); + if (it == buttons.end()) { + g_message("couldn't find the color id %s", _current_color_id.c_str()); + return; + } + Gtk::Button *_current_recolor_button = it->second.second; + std::optional new_color = _solid_colors->get(); + if (!new_color.has_value()) { + g_message("there is no color"); + return; + } + _colorButtons(_current_recolor_button, new_color.value().toString()); + g_message("color picker changed"); +} +void RecolorArt::_onLivePreviewToggled() +{ + g_message("LP toggled"); +} +void RecolorArt::_onApplyButtonClicked() +{ + g_message("apply clicked"); +} void RecolorArt::performUpdate() { - for (auto child : _colorList->get_children()) { - _colorList->remove(*child); + for (auto child : _color_list->get_children()) { + _color_list->remove(*child); } + buttons.clear(); + _current_color_id = ""; if (auto selection = _desktop->getSelection()) { std::vector vec(selection->items().begin(), selection->items().end()); _collectColors(vec); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index a3ddc2ab83..f95192a4d8 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -4,6 +4,8 @@ #define SEEN_DIALOGS_SP_RECOLOR_ART_H #include +#include +#include #include "canvas.h" #include "style-internal.h" @@ -48,8 +50,12 @@ private: SPDesktop *_desktop = nullptr; std::shared_ptr _solid_colors; std::map, std::optional>> _selected_colors; - Inkscape::UI::Widget::ColorNotebook *_colorPickerWdgt = nullptr; - Gtk::Box *_colorList = nullptr; + Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr; + Gtk::Box *_color_list = nullptr; + Gtk::Button *_apply = nullptr; + Gtk::CheckButton *_live_preview = nullptr; + std::string _current_color_id; + std::map> buttons; // color_id : {original , recolored} protected: Glib::RefPtr _builder; @@ -59,8 +65,14 @@ protected: void _extractItemColors(SPItem *item); void _extractItemStyle(SPItem *item); void _generateVisualList(); - void _layoutColorPicker(); - void _colorButtons(Gtk::Button *button, std::string color, std::string id); + void _layoutColorPicker(std::shared_ptr updated_color = nullptr); + void _colorButtons(Gtk::Button *button, std::string color); + + // signals handelrs + void _onOriginalColorClicked(std::string color_id); + void _onColorPickerChanged(); + void _onLivePreviewToggled(); + void _onApplyButtonClicked(); public: RecolorArt(); -- GitLab From b85db02ba96c96f71774e7255303194582b6f9e2 Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 3 Jun 2025 20:47:12 +0300 Subject: [PATCH 007/122] finished apply button function --- src/ui/widget/recolor-art.cpp | 53 +++++++++++++++++++++++++++-------- src/ui/widget/recolor-art.h | 10 ++++++- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index e857fba960..446f79ce4b 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -100,10 +100,11 @@ void RecolorArt::_extractGradientStops(SPItem *item, std::string kind, bool isFi void RecolorArt::_populateMap(Color color, SPItem *item, std::string kind) { ColorRef ref = ColorRef(item, kind); + ColorPair pair = ColorPair(color, color); if (_selected_colors.count(color.toString())) { _selected_colors[color.toString()].first.push_back(ref); } else { - _selected_colors.emplace(color.toString(), std::make_pair(std::vector{ref}, color)); + _selected_colors.emplace(color.toString(), std::make_pair(std::vector{ref}, pair)); } } void RecolorArt::_extractItemStyle(SPItem *item) @@ -141,12 +142,15 @@ void RecolorArt::_generateVisualList() box->set_valign(Gtk::Align::CENTER); auto original = Gtk::make_managed(); original->set_name(key); - _colorButtons(original, key); + _colorButtons(original, value.second.value().old_color.toString()); original->signal_clicked().connect( sigc::bind(sigc::mem_fun(*this, &RecolorArt::_onOriginalColorClicked), original->get_name())); auto recolored = Gtk::make_managed(); recolored->set_name("recolored_from" + key); - _colorButtons(recolored, Color(0xffffff00).toString()); + Color new_color = (value.second.value().old_color == value.second.value().new_color) + ? Color(0xffffff00) + : value.second.value().new_color; + _colorButtons(recolored, new_color.toString()); buttons[key] = {original, recolored}; auto arrow = Gtk::make_managed(); arrow->set_from_icon_name("arrow"); @@ -199,7 +203,7 @@ void RecolorArt::_onOriginalColorClicked(std::string color_id) _current_color_id = color_id; auto it = _selected_colors.find(color_id); if (it != _selected_colors.end() && it->second.second.has_value()) { - Color color = it->second.second.value(); + Color color = it->second.second.value().new_color; std::shared_ptr updated_color = std::make_shared(); updated_color->set(color); _layoutColorPicker(updated_color); @@ -210,7 +214,7 @@ void RecolorArt::_onColorPickerChanged() { auto it = buttons.find(_current_color_id); if (it == buttons.end()) { - g_message("couldn't find the color id %s", _current_color_id.c_str()); + g_message("couldn't find the color id \" %s \" ", _current_color_id.c_str()); return; } Gtk::Button *_current_recolor_button = it->second.second; @@ -219,24 +223,51 @@ void RecolorArt::_onColorPickerChanged() g_message("there is no color"); return; } - _colorButtons(_current_recolor_button, new_color.value().toString()); + std::string _color_string = new_color.value().toString(); + _colorButtons(_current_recolor_button, _color_string); + auto _selected = _selected_colors.find(_current_color_id); + if (_selected != _selected_colors.end()) + _selected->second.second.value().new_color = new_color.value(); + // if (_live_preview && _live_preview->property_active()) { + // auto _selected = _selected_colors.find(_current_color_id); + // if (_selected == _selected_colors.end()) { + // g_message("no items found"); + // return; + // } + // _selected->second.second.value().new_color = new_color.value(); + // for (auto &item : _selected->second.first) { + // SPCSSAttr *css = sp_repr_css_attr_new(); + // sp_repr_css_set_property_string(css, item.kind.c_str(), _color_string); + // sp_desktop_apply_css_recursive(item.item, css, true); + // sp_repr_css_attr_unref(css); + // } + // } g_message("color picker changed"); } -void RecolorArt::_onLivePreviewToggled() -{ - g_message("LP toggled"); -} void RecolorArt::_onApplyButtonClicked() { + for (auto [key, items] : _selected_colors) { + std::string _color_string = items.second.value().new_color.toString(); + for (auto &item : items.first) { + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property_string(css, item.kind.c_str(), _color_string); + sp_desktop_apply_css_recursive(item.item, css, true); + sp_repr_css_attr_unref(css); + } + } g_message("apply clicked"); } +void RecolorArt::_onLivePreviewToggled() +{ + g_message("LP toggled"); +} void RecolorArt::performUpdate() { for (auto child : _color_list->get_children()) { _color_list->remove(*child); } buttons.clear(); - _current_color_id = ""; + // _current_color_id = ""; if (auto selection = _desktop->getSelection()) { std::vector vec(selection->items().begin(), selection->items().end()); _collectColors(vec); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index f95192a4d8..3825769101 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -44,18 +44,26 @@ struct ColorRef std::string kind; }; +struct ColorPair +{ + Color old_color; + Color new_color; +}; + class RecolorArt : public Gtk::Box { private: SPDesktop *_desktop = nullptr; std::shared_ptr _solid_colors; - std::map, std::optional>> _selected_colors; + std::map, std::optional>> _selected_colors; Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr; Gtk::Box *_color_list = nullptr; Gtk::Button *_apply = nullptr; Gtk::CheckButton *_live_preview = nullptr; std::string _current_color_id; std::map> buttons; // color_id : {original , recolored} + bool _is_preview = false; + sigc::connection _color_changed_connection; protected: Glib::RefPtr _builder; -- GitLab From d00129798bb6254094b208792a680a1efbc7b42b Mon Sep 17 00:00:00 2001 From: ftomara Date: Fri, 20 Jun 2025 05:56:39 +0300 Subject: [PATCH 008/122] finished live_preview feature check button --- src/ui/dialog/fill-and-stroke.cpp | 13 +++++---- src/ui/widget/recolor-art.cpp | 45 +++++++++++-------------------- src/ui/widget/recolor-art.h | 1 + 3 files changed, 25 insertions(+), 34 deletions(-) diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index 1bcdd92052..2ef526c18e 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -21,6 +21,7 @@ #include #include +#include "desktop-style.h" #include "desktop.h" #include "preferences.h" #include "ui/icon-loader.h" @@ -99,7 +100,8 @@ void FillAndStroke::selectionChanged(Selection *selection) strokeStyleWdgt->selectionChangedCB(); } if (recolorArtWdgt && npage == 3) { - recolorArtWdgt->performUpdate(); + if (!recolorArtWdgt->isInPreviewMode()) + recolorArtWdgt->performUpdate(); } } @@ -118,8 +120,9 @@ void FillAndStroke::selectionModified(Selection *selection, guint flags) if (strokeStyleWdgt && npage == 2) { strokeStyleWdgt->selectionModifiedCB(flags); } - if (recolorArtWdgt && npage == 3) { - recolorArtWdgt->performUpdate(); + if (recolorArtWdgt && npage == 3) { + if (!recolorArtWdgt->isInPreviewMode()) + recolorArtWdgt->performUpdate(); } } @@ -138,13 +141,13 @@ void FillAndStroke::desktopReplaced() if (strokeStyleWdgt) { strokeStyleWdgt->setDesktop(getDesktop()); } - if (recolorArtWdgt) { + if (recolorArtWdgt) { recolorArtWdgt->setDesktop(getDesktop()); } _subject.setDesktop(getDesktop()); } -void FillAndStroke::_onSwitchPage(Gtk::Widget * page, guint pagenum) +void FillAndStroke::_onSwitchPage(Gtk::Widget *page, guint pagenum) { npage = pagenum; if (page->is_visible()) { diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 446f79ce4b..6e1afbbbf4 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -228,20 +228,20 @@ void RecolorArt::_onColorPickerChanged() auto _selected = _selected_colors.find(_current_color_id); if (_selected != _selected_colors.end()) _selected->second.second.value().new_color = new_color.value(); - // if (_live_preview && _live_preview->property_active()) { - // auto _selected = _selected_colors.find(_current_color_id); - // if (_selected == _selected_colors.end()) { - // g_message("no items found"); - // return; - // } - // _selected->second.second.value().new_color = new_color.value(); - // for (auto &item : _selected->second.first) { - // SPCSSAttr *css = sp_repr_css_attr_new(); - // sp_repr_css_set_property_string(css, item.kind.c_str(), _color_string); - // sp_desktop_apply_css_recursive(item.item, css, true); - // sp_repr_css_attr_unref(css); - // } - // } + if (_live_preview && _live_preview->property_active()) { + auto _selected = _selected_colors.find(_current_color_id); + if (_selected == _selected_colors.end()) { + g_message("no items found"); + return; + } + _selected->second.second.value().new_color = new_color.value(); + for (auto &item : _selected->second.first) { + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property_string(css, item.kind.c_str(), _color_string); + sp_desktop_apply_css_recursive(item.item, css, true); + sp_repr_css_attr_unref(css); + } + } g_message("color picker changed"); } void RecolorArt::_onApplyButtonClicked() @@ -259,6 +259,8 @@ void RecolorArt::_onApplyButtonClicked() } void RecolorArt::_onLivePreviewToggled() { + _is_preview = _live_preview->property_active(); + g_message(_is_preview?"is true":"is false"); g_message("LP toggled"); } void RecolorArt::performUpdate() @@ -282,18 +284,3 @@ void RecolorArt::performUpdate() } // namespace UI } // namespace Inkscape -// for (auto [key, value] : _selected_colors) { -// std::cout << key << " : "; -// for (auto item : value.first) { -// std::cout << item.item << " , "; -// if (item.kind == "fill" && key == "#000000") { -// uint32_t rgba = 0xFF00FFFF; -// Color c(rgba, true); -// SPCSSAttr *css = sp_repr_css_attr_new(); -// sp_repr_css_set_property_string(css, "fill", c.toString(false)); -// sp_desktop_apply_css_recursive(item.item, css, true); -// sp_repr_css_attr_unref(css); -// } -// } -// std::cout << std::endl; -// } \ No newline at end of file diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 3825769101..b57dc60a96 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -86,6 +86,7 @@ public: RecolorArt(); ~RecolorArt(); void performUpdate(); + bool isInPreviewMode() { return _is_preview; } void setDesktop(SPDesktop *desktop); }; -- GitLab From 95451f9f2a5e542ac65c83e86b079e7fd89444fc Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 24 Jun 2025 12:46:22 +0300 Subject: [PATCH 009/122] made live preview defualt to checked removed apply button saved changed colors on selection change --- share/ui/recolor-art.glade | 4 ++-- src/ui/dialog/fill-and-stroke.cpp | 8 ++++--- src/ui/widget/recolor-art.cpp | 35 +++++++++++++++---------------- src/ui/widget/recolor-art.h | 6 +++--- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 4ebcb7fc25..3075c3f8ea 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -87,14 +87,14 @@ start - + diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index 2ef526c18e..b96ed30514 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -31,6 +31,8 @@ #include "ui/widget/stroke-style.h" #include "ui/widget/recolor-art.h" #include "ui/widget/notebook-page.h" +#include "ui/widget/recolor-art.h" +#include "ui/widget/stroke-style.h" namespace Inkscape::UI::Dialog { @@ -100,8 +102,8 @@ void FillAndStroke::selectionChanged(Selection *selection) strokeStyleWdgt->selectionChangedCB(); } if (recolorArtWdgt && npage == 3) { - if (!recolorArtWdgt->isInPreviewMode()) - recolorArtWdgt->performUpdate(); + // if (!recolorArtWdgt->isInPreviewMode()) + recolorArtWdgt->performUpdate(); } } @@ -121,7 +123,7 @@ void FillAndStroke::selectionModified(Selection *selection, guint flags) strokeStyleWdgt->selectionModifiedCB(flags); } if (recolorArtWdgt && npage == 3) { - if (!recolorArtWdgt->isInPreviewMode()) + if (!recolorArtWdgt->isInPreviewMode()) { recolorArtWdgt->performUpdate(); } } diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 6e1afbbbf4..db62b2a747 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -50,11 +50,11 @@ RecolorArt::RecolorArt() _layoutColorPicker(); _color_list = _builder->get_widget("colors-list"); - _apply = _builder->get_widget("apply"); _live_preview = _builder->get_widget("liveP"); - - _apply->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::_onApplyButtonClicked)); + // _apply = _builder->get_widget("apply"); + // _apply->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::_onApplyButtonClicked)); _live_preview->signal_toggled().connect(sigc::mem_fun(*this, &RecolorArt::_onLivePreviewToggled)); + _live_preview->set_active(true); } RecolorArt::~RecolorArt() {} @@ -244,23 +244,23 @@ void RecolorArt::_onColorPickerChanged() } g_message("color picker changed"); } -void RecolorArt::_onApplyButtonClicked() -{ - for (auto [key, items] : _selected_colors) { - std::string _color_string = items.second.value().new_color.toString(); - for (auto &item : items.first) { - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, item.kind.c_str(), _color_string); - sp_desktop_apply_css_recursive(item.item, css, true); - sp_repr_css_attr_unref(css); - } - } - g_message("apply clicked"); -} +// void RecolorArt::_onApplyButtonClicked() +// { +// for (auto [key, items] : _selected_colors) { +// std::string _color_string = items.second.value().new_color.toString(); +// for (auto &item : items.first) { +// SPCSSAttr *css = sp_repr_css_attr_new(); +// sp_repr_css_set_property_string(css, item.kind.c_str(), _color_string); +// sp_desktop_apply_css_recursive(item.item, css, true); +// sp_repr_css_attr_unref(css); +// } +// } +// g_message("apply clicked"); +// } void RecolorArt::_onLivePreviewToggled() { _is_preview = _live_preview->property_active(); - g_message(_is_preview?"is true":"is false"); + g_message(_is_preview ? "is true" : "is false"); g_message("LP toggled"); } void RecolorArt::performUpdate() @@ -283,4 +283,3 @@ void RecolorArt::performUpdate() } // namespace Widget } // namespace UI } // namespace Inkscape - diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index b57dc60a96..42cb655d7e 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -58,12 +58,12 @@ private: std::map, std::optional>> _selected_colors; Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr; Gtk::Box *_color_list = nullptr; - Gtk::Button *_apply = nullptr; + // Gtk::Button *_apply = nullptr; Gtk::CheckButton *_live_preview = nullptr; std::string _current_color_id; std::map> buttons; // color_id : {original , recolored} bool _is_preview = false; - sigc::connection _color_changed_connection; + // sigc::connection _color_changed_connection; protected: Glib::RefPtr _builder; @@ -80,7 +80,7 @@ protected: void _onOriginalColorClicked(std::string color_id); void _onColorPickerChanged(); void _onLivePreviewToggled(); - void _onApplyButtonClicked(); + // void _onApplyButtonClicked(); public: RecolorArt(); -- GitLab From 9879a1434a7881c3d88b8dd18c84d767ff2b4710 Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 24 Jun 2025 12:51:06 +0300 Subject: [PATCH 010/122] made live preview defualt to checked removed apply button saved changed colors on selection change --- src/ui/dialog/fill-and-stroke.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index b96ed30514..9e8ca6e07a 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -127,6 +127,7 @@ void FillAndStroke::selectionModified(Selection *selection, guint flags) recolorArtWdgt->performUpdate(); } } +} void FillAndStroke::desktopReplaced() { -- GitLab From 06d33938fbfc2f07e074eff3690cdf682e3a29c7 Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 24 Jun 2025 18:43:41 +0300 Subject: [PATCH 011/122] undo functionality done --- src/ui/widget/recolor-art.cpp | 13 +++++++++---- src/ui/widget/recolor-art.h | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index db62b2a747..05cce05932 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -229,20 +229,25 @@ void RecolorArt::_onColorPickerChanged() if (_selected != _selected_colors.end()) _selected->second.second.value().new_color = new_color.value(); if (_live_preview && _live_preview->property_active()) { - auto _selected = _selected_colors.find(_current_color_id); + _LpChecked(new_color.value(),_color_string); + } + g_message("color picker changed"); +} +void RecolorArt::_LpChecked(Color new_color,std::string _color_string) +{ + auto _selected = _selected_colors.find(_current_color_id); if (_selected == _selected_colors.end()) { g_message("no items found"); return; } - _selected->second.second.value().new_color = new_color.value(); + _selected->second.second.value().new_color = new_color; for (auto &item : _selected->second.first) { SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property_string(css, item.kind.c_str(), _color_string); sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } - } - g_message("color picker changed"); + DocumentUndo::done(_desktop->getDocument(),_("Recolored items"),INKSCAPE_ICON("object-recolor-art")); } // void RecolorArt::_onApplyButtonClicked() // { diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 42cb655d7e..cabd02b9ae 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -80,6 +80,7 @@ protected: void _onOriginalColorClicked(std::string color_id); void _onColorPickerChanged(); void _onLivePreviewToggled(); + void _LpChecked(Color new_color, std::string _color_string); // void _onApplyButtonClicked(); public: -- GitLab From 61d5ca1e06613a41fc11d11d379ea01dedc1752c Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 24 Jun 2025 20:50:33 +0300 Subject: [PATCH 012/122] -renamed tab to recolor instead of recolor art -selected first color as defualt to change -live preview toggling handle revert and convert from original to recolored -added reset and arrow icons to hicolor and dash themes --- .../Dash/symbolic/actions/arrow-symbolic.svg | 3 + .../actions/reset-colors-symbolic.svg | 4 + .../symbolic/actions/arrow-symbolic.svg | 3 + .../actions/reset-colors-symbolic.svg | 4 + src/ui/dialog/fill-and-stroke.cpp | 8 +- src/ui/widget/recolor-art.cpp | 87 ++++++++++++++----- src/ui/widget/recolor-art.h | 4 +- 7 files changed, 84 insertions(+), 29 deletions(-) create mode 100644 share/icons/Dash/symbolic/actions/arrow-symbolic.svg create mode 100644 share/icons/Dash/symbolic/actions/reset-colors-symbolic.svg create mode 100644 share/icons/hicolor/symbolic/actions/arrow-symbolic.svg create mode 100644 share/icons/hicolor/symbolic/actions/reset-colors-symbolic.svg diff --git a/share/icons/Dash/symbolic/actions/arrow-symbolic.svg b/share/icons/Dash/symbolic/actions/arrow-symbolic.svg new file mode 100644 index 0000000000..f387849bc8 --- /dev/null +++ b/share/icons/Dash/symbolic/actions/arrow-symbolic.svg @@ -0,0 +1,3 @@ + + + diff --git a/share/icons/Dash/symbolic/actions/reset-colors-symbolic.svg b/share/icons/Dash/symbolic/actions/reset-colors-symbolic.svg new file mode 100644 index 0000000000..7d47572893 --- /dev/null +++ b/share/icons/Dash/symbolic/actions/reset-colors-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/share/icons/hicolor/symbolic/actions/arrow-symbolic.svg b/share/icons/hicolor/symbolic/actions/arrow-symbolic.svg new file mode 100644 index 0000000000..f387849bc8 --- /dev/null +++ b/share/icons/hicolor/symbolic/actions/arrow-symbolic.svg @@ -0,0 +1,3 @@ + + + diff --git a/share/icons/hicolor/symbolic/actions/reset-colors-symbolic.svg b/share/icons/hicolor/symbolic/actions/reset-colors-symbolic.svg new file mode 100644 index 0000000000..7d47572893 --- /dev/null +++ b/share/icons/hicolor/symbolic/actions/reset-colors-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index 9e8ca6e07a..b0eb9acdf7 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -58,7 +58,7 @@ FillAndStroke::FillAndStroke() _notebook.append_page(*_page_fill, _createPageTabLabel(_("_Fill"), INKSCAPE_ICON("object-fill"))); _notebook.append_page(*_page_stroke_paint, _createPageTabLabel(_("Stroke _paint"), INKSCAPE_ICON("object-stroke"))); _notebook.append_page(*_page_stroke_style, _createPageTabLabel(_("Stroke st_yle"), INKSCAPE_ICON("object-stroke-style"))); - _notebook.append_page(*_page_recolor_art, _createPageTabLabel(_("Recolor Art"), INKSCAPE_ICON("object-recolor-art"))); + _notebook.append_page(*_page_recolor_art, _createPageTabLabel(_("Recolor"), INKSCAPE_ICON("object-recolor-art"))); _notebook.set_vexpand(true); _switch_page_conn = _notebook.signal_switch_page().connect(sigc::mem_fun(*this, &FillAndStroke::_onSwitchPage)); @@ -123,9 +123,9 @@ void FillAndStroke::selectionModified(Selection *selection, guint flags) strokeStyleWdgt->selectionModifiedCB(flags); } if (recolorArtWdgt && npage == 3) { - if (!recolorArtWdgt->isInPreviewMode()) { - recolorArtWdgt->performUpdate(); - } + // if (!recolorArtWdgt->isInPreviewMode()) { + // recolorArtWdgt->performUpdate(); + // } } } diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 05cce05932..be07485476 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -229,42 +229,65 @@ void RecolorArt::_onColorPickerChanged() if (_selected != _selected_colors.end()) _selected->second.second.value().new_color = new_color.value(); if (_live_preview && _live_preview->property_active()) { - _LpChecked(new_color.value(),_color_string); + _lpChecked(); } g_message("color picker changed"); } -void RecolorArt::_LpChecked(Color new_color,std::string _color_string) +void RecolorArt::_lpChecked() { - auto _selected = _selected_colors.find(_current_color_id); - if (_selected == _selected_colors.end()) { - g_message("no items found"); - return; - } - _selected->second.second.value().new_color = new_color; - for (auto &item : _selected->second.first) { + auto _selected = _selected_colors.find(_current_color_id); + std::optional new_color = _solid_colors->get(); + if (!new_color.has_value()) { + g_message("there is no color"); + return; + } + std::string _color_string = new_color.value().toString(); + if (_selected == _selected_colors.end()) { + g_message("no items found"); + return; + } + _selected->second.second.value().new_color = new_color.value(); + for (auto &item : _selected->second.first) { + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property_string(css, item.kind.c_str(), _color_string); + sp_desktop_apply_css_recursive(item.item, css, true); + sp_repr_css_attr_unref(css); + } + DocumentUndo::done(_desktop->getDocument(), _("Recolored items"), INKSCAPE_ICON("object-recolor-art")); +} +void RecolorArt::_revertToOriginalColors() +{ + for (auto [key, items] : _selected_colors) { + for (auto &item : items.first) { SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, item.kind.c_str(), _color_string); + sp_repr_css_set_property_string(css, item.kind.c_str(), key); sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } - DocumentUndo::done(_desktop->getDocument(),_("Recolored items"),INKSCAPE_ICON("object-recolor-art")); + } +} +void RecolorArt::_convertToRecoloredColors() +{ + for (auto [key, items] : _selected_colors) { + if (items.second.has_value()) { + std::string new_color = items.second.value().new_color.toString(); + for (auto &item : items.first) { + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property_string(css, item.kind.c_str(), new_color); + sp_desktop_apply_css_recursive(item.item, css, true); + sp_repr_css_attr_unref(css); + } + } + } } -// void RecolorArt::_onApplyButtonClicked() -// { -// for (auto [key, items] : _selected_colors) { -// std::string _color_string = items.second.value().new_color.toString(); -// for (auto &item : items.first) { -// SPCSSAttr *css = sp_repr_css_attr_new(); -// sp_repr_css_set_property_string(css, item.kind.c_str(), _color_string); -// sp_desktop_apply_css_recursive(item.item, css, true); -// sp_repr_css_attr_unref(css); -// } -// } -// g_message("apply clicked"); -// } void RecolorArt::_onLivePreviewToggled() { _is_preview = _live_preview->property_active(); + if (_is_preview) { + _convertToRecoloredColors(); + } else { + _revertToOriginalColors(); + } g_message(_is_preview ? "is true" : "is false"); g_message("LP toggled"); } @@ -280,6 +303,8 @@ void RecolorArt::performUpdate() _collectColors(vec); if (!_selected_colors.empty()) { _generateVisualList(); + auto first_button_id = buttons.begin()->first; + _onOriginalColorClicked(first_button_id); } } @@ -288,3 +313,17 @@ void RecolorArt::performUpdate() } // namespace Widget } // namespace UI } // namespace Inkscape + +// void RecolorArt::_onApplyButtonClicked() +// { +// for (auto [key, items] : _selected_colors) { +// std::string _color_string = items.second.value().new_color.toString(); +// for (auto &item : items.first) { +// SPCSSAttr *css = sp_repr_css_attr_new(); +// sp_repr_css_set_property_string(css, item.kind.c_str(), _color_string); +// sp_desktop_apply_css_recursive(item.item, css, true); +// sp_repr_css_attr_unref(css); +// } +// } +// g_message("apply clicked"); +// } \ No newline at end of file diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index cabd02b9ae..2fbeb0d4d3 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -80,7 +80,9 @@ protected: void _onOriginalColorClicked(std::string color_id); void _onColorPickerChanged(); void _onLivePreviewToggled(); - void _LpChecked(Color new_color, std::string _color_string); + void _lpChecked(); + void _revertToOriginalColors(); + void _convertToRecoloredColors(); // void _onApplyButtonClicked(); public: -- GitLab From 868f6c2d243d54e6281ae10aab9657b194700832 Mon Sep 17 00:00:00 2001 From: ftomara Date: Wed, 25 Jun 2025 05:41:50 +0300 Subject: [PATCH 013/122] reset button functionality done --- share/ui/recolor-art.glade | 3 ++- src/ui/widget/recolor-art.cpp | 14 ++++++++++++-- src/ui/widget/recolor-art.h | 2 ++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 3075c3f8ea..3a1120fb99 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -21,7 +21,8 @@ - + + reset true false false diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index be07485476..c3f9a5f50c 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -51,10 +51,12 @@ RecolorArt::RecolorArt() _layoutColorPicker(); _color_list = _builder->get_widget("colors-list"); _live_preview = _builder->get_widget("liveP"); - // _apply = _builder->get_widget("apply"); - // _apply->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::_onApplyButtonClicked)); _live_preview->signal_toggled().connect(sigc::mem_fun(*this, &RecolorArt::_onLivePreviewToggled)); _live_preview->set_active(true); + _reset = _builder->get_widget("reset"); + _reset->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::_onResetClicked)); + // _apply = _builder->get_widget("apply"); + // _apply->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::_onApplyButtonClicked)); } RecolorArt::~RecolorArt() {} @@ -255,6 +257,14 @@ void RecolorArt::_lpChecked() } DocumentUndo::done(_desktop->getDocument(), _("Recolored items"), INKSCAPE_ICON("object-recolor-art")); } +void RecolorArt::_onResetClicked() +{ + for (auto [key, btns] : buttons) { + _colorButtons(btns.second, Color(0xffffff00).toString()); + } + _revertToOriginalColors(); + _onOriginalColorClicked(buttons.begin()->first); +} void RecolorArt::_revertToOriginalColors() { for (auto [key, items] : _selected_colors) { diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 2fbeb0d4d3..9500470a16 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -59,6 +59,7 @@ private: Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr; Gtk::Box *_color_list = nullptr; // Gtk::Button *_apply = nullptr; + Gtk::Button *_reset = nullptr; Gtk::CheckButton *_live_preview = nullptr; std::string _current_color_id; std::map> buttons; // color_id : {original , recolored} @@ -78,6 +79,7 @@ protected: // signals handelrs void _onOriginalColorClicked(std::string color_id); + void _onResetClicked(); void _onColorPickerChanged(); void _onLivePreviewToggled(); void _lpChecked(); -- GitLab From 359b2156b122a90cba4af2bff27baa88db3a25af Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 26 Jun 2025 08:51:59 +0300 Subject: [PATCH 014/122] added scrolled window to color list ui and grid view for lazy loading --- share/ui/recolor-art.glade | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 3a1120fb99..0ecc7023c2 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -36,21 +36,35 @@ - Recolored + New Color center - - - colors-list - vertical - center - center - 24 - + + -- GitLab From bf453b6beda4686bddbcc022faa8e0a55d8567d8 Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 26 Jun 2025 09:01:45 +0300 Subject: [PATCH 015/122] made orignal color equals new color at the begining instead of making new one transparent --- src/ui/widget/recolor-art.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index c3f9a5f50c..3a2759b547 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -149,10 +149,10 @@ void RecolorArt::_generateVisualList() sigc::bind(sigc::mem_fun(*this, &RecolorArt::_onOriginalColorClicked), original->get_name())); auto recolored = Gtk::make_managed(); recolored->set_name("recolored_from" + key); - Color new_color = (value.second.value().old_color == value.second.value().new_color) - ? Color(0xffffff00) - : value.second.value().new_color; - _colorButtons(recolored, new_color.toString()); + // Color new_color = (value.second.value().old_color == value.second.value().new_color) + // ? Color(0xffffff00) + // : value.second.value().new_color; + _colorButtons(recolored, value.second.value().old_color.toString()); buttons[key] = {original, recolored}; auto arrow = Gtk::make_managed(); arrow->set_from_icon_name("arrow"); @@ -260,7 +260,7 @@ void RecolorArt::_lpChecked() void RecolorArt::_onResetClicked() { for (auto [key, btns] : buttons) { - _colorButtons(btns.second, Color(0xffffff00).toString()); + _colorButtons(btns.second, key); } _revertToOriginalColors(); _onOriginalColorClicked(buttons.begin()->first); -- GitLab From 4a896b369e4187d0130577882814ff88212ddd6b Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 26 Jun 2025 10:01:11 +0300 Subject: [PATCH 016/122] refactored _generateVisualList to use grid view for lazy loading --- share/ui/recolor-art.glade | 5 +- src/ui/widget/recolor-art.cpp | 89 +++++++++++++++++++++++++---------- src/ui/widget/recolor-art.h | 30 +++++++++++- 3 files changed, 93 insertions(+), 31 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 0ecc7023c2..a156b0bc6c 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -57,11 +57,8 @@ center 24 - + True - - - True + + Color Wheel Content Goes Here - + true + + + color-whele-symbolic + normal + + + + + Color Whele + center + center + + + + vertical diff --git a/share/ui/style.css b/share/ui/style.css index 9105a3c2a3..2d0e01aabd 100644 --- a/share/ui/style.css +++ b/share/ui/style.css @@ -1679,12 +1679,14 @@ button.reduced-padding { * Recolor Art class * ********************** */ + #original, #recolored { min-width: 180px; min-height: 14px; border-radius: 4px; padding: 0; margin: 0px; + border: 2px solid black; } #original-recolor-box button#original:hover { border-color: white; @@ -1706,6 +1708,7 @@ button.reduced-padding { #original-recolor-box { min-width: 180px; min-height: 14px; + margin-left:36px; } #recolor-art gridview child:selected { @@ -1716,4 +1719,33 @@ button.reduced-padding { { padding: 0px; margin: 0px; + background-color:#2A2A2A ; +} + +#original-recolor-colors-list-box +{ + background-color:#2A2A2A ; +} +#reset +{ + background-color:#474747; + color:white; + border: 2px solid #000 ; + margin-top:6px; +} + +#list-wheel-box +{ + background-color:#2A2A2A; + margin:4px; + border: 2px solid #000 ; + +} + +#list-wheel-box label +{ + font-size: 16px; + color: white; + font-weight: 200; + background-image: none; } \ No newline at end of file -- GitLab From 0a3a4c7ff1e128e135faf8f46ae09d96677a3667 Mon Sep 17 00:00:00 2001 From: ftomara Date: Fri, 27 Jun 2025 17:55:50 +0300 Subject: [PATCH 021/122] used listview instead of grid view --- share/ui/recolor-art.glade | 7 +++-- share/ui/style.css | 46 ++++++++++++++++++++------- src/ui/widget/recolor-art.cpp | 59 +++++++++++++++++++++++++---------- src/ui/widget/recolor-art.h | 4 +-- 4 files changed, 85 insertions(+), 31 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 4988c8c196..333fe2073e 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -66,8 +66,11 @@ center center - - True + + false + center + true + center diff --git a/share/ui/style.css b/share/ui/style.css index 2d0e01aabd..fe9c03abeb 100644 --- a/share/ui/style.css +++ b/share/ui/style.css @@ -1682,20 +1682,27 @@ button.reduced-padding { #original, #recolored { min-width: 180px; - min-height: 14px; + min-height: 14px; border-radius: 4px; padding: 0; margin: 0px; border: 2px solid black; } #original-recolor-box button#original:hover { - border-color: white; - border-width: 1px; - border-style: solid; + min-width: 180px; + min-height: 14px; + border-radius: 4px; + padding: 0; + margin: 0px; + border: 2px solid white; } #original-recolor-box button.selected-button { - border: 1px solid white; + min-width: 180px; + min-height: 14px; border-radius: 4px; + padding: 0; + margin: 0px; + border: 2px solid white; } #original-reset-recolor label @@ -1705,17 +1712,27 @@ button.reduced-padding { } +#original-reset-recolor +{ + margin-right: 24px; + margin-bottom: 12px; + +} + #original-recolor-box { - min-width: 180px; - min-height: 14px; - margin-left:36px; + min-width: 180px; + min-height: 14px; + /* margin-left:36px; + margin-right:36px; */ } -#recolor-art gridview child:selected { +#recolor-art listview row:selected { background-color: transparent; + border-radius: 4px; + border: 2px solid #0D57C3; } -#recolor-art gridview +#recolor-art listview { padding: 0px; margin: 0px; @@ -1734,12 +1751,19 @@ button.reduced-padding { margin-top:6px; } +#reset:hover { + background-color: #202020; + color: white; + border: 2px solid #000; + margin-top: 6px; +} + #list-wheel-box { background-color:#2A2A2A; margin:4px; border: 2px solid #000 ; - + } #list-wheel-box label diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 97c82d1379..d93bf10c2b 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -6,9 +6,11 @@ #include #include #include -#include +#include #include #include +#include +#include #include #include @@ -62,7 +64,7 @@ RecolorArt::RecolorArt() _reset = _builder->get_widget("reset"); _reset->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::_onResetClicked)); - _grid_view = _builder->get_widget("recolor-art-grid"); + _list_view = _builder->get_widget("recolor-art-list"); _color_model = Gio::ListStore::create(); _selection_model = Gtk::SingleSelection::create(_color_model); _color_factory = Gtk::SignalListItemFactory::create(); @@ -73,6 +75,14 @@ RecolorArt::RecolorArt() auto arrow = Gtk::make_managed(); auto recolored = Gtk::make_managed(); + original->set_hexpand(false); + original->set_vexpand(false); + original->set_valign(Gtk::Align::CENTER); + + recolored->set_hexpand(false); + recolored->set_vexpand(false); + recolored->set_valign(Gtk::Align::CENTER); + arrow->set_use_markup(true); arrow->set_width_chars(3); arrow->set_markup("➔"); @@ -81,8 +91,10 @@ RecolorArt::RecolorArt() box->set_name("original-recolor-box"); box->set_spacing(14); - box->set_margin_top(2); - box->set_margin_bottom(2); + box->set_margin_top(0); + box->set_margin_bottom(0); + box->set_margin_start(0); + box->set_margin_end(0); box->append(*original); box->append(*arrow); box->append(*recolored); @@ -106,22 +118,37 @@ RecolorArt::RecolorArt() _colorButtons(recolored, item->new_color); original->set_name("original"); - original->set_hexpand(false); recolored->set_name("recolored"); - recolored->set_hexpand(false); - original->signal_clicked().connect( - sigc::bind(sigc::mem_fun(*this, &RecolorArt::_onOriginalColorClicked), item->key)); - + original->signal_clicked().connect([this, item, index = list_item->get_position()] { + // _selection_model->set_selected(index); + _onOriginalColorClicked(item->key); + }); buttons[item->key] = {original, recolored}; } }); - _grid_view->set_model(_selection_model); - _grid_view->set_factory(_color_factory); - _grid_view->set_max_columns(1); - _grid_view->set_min_columns(1); - _grid_view->set_hexpand(false); - _grid_view->set_vexpand(false); + _list_view->set_model(_selection_model); + _list_view->set_factory(_color_factory); + auto lm = _list_view->get_layout_manager(); + if (auto grid_layout = std::dynamic_pointer_cast(lm)) { + grid_layout->set_row_spacing(0); + } + _list_view->set_hexpand(false); + _list_view->set_vexpand(false); + + // _selection_model->signal_selection_changed().connect([this](guint pos, guint n_items) { + // int index = _selection_model->get_selected(); + // if (index < 0) + // return; + + // auto item = _color_model->get_item(index); + // auto color_item = std::dynamic_pointer_cast(item); + // if (!color_item) + // return; + + // _onOriginalColorClicked(color_item->key); + // }); + // _apply = _builder->get_widget("apply"); // _apply->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::_onApplyButtonClicked)); } @@ -211,7 +238,7 @@ void RecolorArt::_generateVisualList() auto new_color = value.second.value().old_color.toString(); _color_model->append(ColorItem::create(key, old_color, new_color)); } - _color_list->append(*_grid_view); + _color_list->append(*_list_view); } void RecolorArt::_layoutColorPicker(std::shared_ptr updated_color) { diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 84364ab813..668bdde87f 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include @@ -81,7 +81,7 @@ private: std::map, std::optional>> _selected_colors; Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr; Gtk::Box *_color_list = nullptr; - Gtk::GridView *_grid_view = nullptr; + Gtk::ListView *_list_view = nullptr; Gtk::Button *_reset = nullptr; Gtk::CheckButton *_live_preview = nullptr; std::string _current_color_id; -- GitLab From 1c6dd3f6b6efe599d7e956e6d6953c53d2d6eca9 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sat, 28 Jun 2025 07:14:29 +0300 Subject: [PATCH 022/122] used themed already exited icons , refactored functions name , made them privte not protected --- .../Dash/symbolic/actions/arrow-symbolic.svg | 3 - .../symbolic/actions/color-whele-symbolic.svg | 3 - .../Dash/symbolic/actions/list-symbolic.svg | 3 - .../Dash/symbolic/actions/reset-symbolic.svg | 5 -- .../symbolic/actions/arrow-symbolic.svg | 3 - .../symbolic/actions/color-whele-symbolic.svg | 3 - .../symbolic/actions/list-symbolic.svg | 3 - .../symbolic/actions/reset-symbolic.svg | 58 ------------ .../symbolic/actions/arrow-symbolic.svg | 3 - .../symbolic/actions/color-whele-symbolic.svg | 3 - .../symbolic/actions/list-symbolic.svg | 3 - .../symbolic/actions/reset-symbolic.svg | 58 ------------ share/ui/recolor-art.glade | 8 +- src/ui/widget/recolor-art.cpp | 90 +++++++++---------- src/ui/widget/recolor-art.h | 34 +++---- 15 files changed, 66 insertions(+), 214 deletions(-) delete mode 100644 share/icons/Dash/symbolic/actions/arrow-symbolic.svg delete mode 100644 share/icons/Dash/symbolic/actions/color-whele-symbolic.svg delete mode 100644 share/icons/Dash/symbolic/actions/list-symbolic.svg delete mode 100644 share/icons/Dash/symbolic/actions/reset-symbolic.svg delete mode 100644 share/icons/hicolor/symbolic/actions/arrow-symbolic.svg delete mode 100644 share/icons/hicolor/symbolic/actions/color-whele-symbolic.svg delete mode 100644 share/icons/hicolor/symbolic/actions/list-symbolic.svg delete mode 100644 share/icons/hicolor/symbolic/actions/reset-symbolic.svg delete mode 100644 share/icons/multicolor/symbolic/actions/arrow-symbolic.svg delete mode 100644 share/icons/multicolor/symbolic/actions/color-whele-symbolic.svg delete mode 100644 share/icons/multicolor/symbolic/actions/list-symbolic.svg delete mode 100644 share/icons/multicolor/symbolic/actions/reset-symbolic.svg diff --git a/share/icons/Dash/symbolic/actions/arrow-symbolic.svg b/share/icons/Dash/symbolic/actions/arrow-symbolic.svg deleted file mode 100644 index f387849bc8..0000000000 --- a/share/icons/Dash/symbolic/actions/arrow-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/share/icons/Dash/symbolic/actions/color-whele-symbolic.svg b/share/icons/Dash/symbolic/actions/color-whele-symbolic.svg deleted file mode 100644 index 718b77b382..0000000000 --- a/share/icons/Dash/symbolic/actions/color-whele-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/share/icons/Dash/symbolic/actions/list-symbolic.svg b/share/icons/Dash/symbolic/actions/list-symbolic.svg deleted file mode 100644 index 1ad1a80d41..0000000000 --- a/share/icons/Dash/symbolic/actions/list-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/share/icons/Dash/symbolic/actions/reset-symbolic.svg b/share/icons/Dash/symbolic/actions/reset-symbolic.svg deleted file mode 100644 index 09c40a1e30..0000000000 --- a/share/icons/Dash/symbolic/actions/reset-symbolic.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/share/icons/hicolor/symbolic/actions/arrow-symbolic.svg b/share/icons/hicolor/symbolic/actions/arrow-symbolic.svg deleted file mode 100644 index f387849bc8..0000000000 --- a/share/icons/hicolor/symbolic/actions/arrow-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/share/icons/hicolor/symbolic/actions/color-whele-symbolic.svg b/share/icons/hicolor/symbolic/actions/color-whele-symbolic.svg deleted file mode 100644 index 718b77b382..0000000000 --- a/share/icons/hicolor/symbolic/actions/color-whele-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/share/icons/hicolor/symbolic/actions/list-symbolic.svg b/share/icons/hicolor/symbolic/actions/list-symbolic.svg deleted file mode 100644 index 1ad1a80d41..0000000000 --- a/share/icons/hicolor/symbolic/actions/list-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/share/icons/hicolor/symbolic/actions/reset-symbolic.svg b/share/icons/hicolor/symbolic/actions/reset-symbolic.svg deleted file mode 100644 index 7dcef2b3f7..0000000000 --- a/share/icons/hicolor/symbolic/actions/reset-symbolic.svg +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - diff --git a/share/icons/multicolor/symbolic/actions/arrow-symbolic.svg b/share/icons/multicolor/symbolic/actions/arrow-symbolic.svg deleted file mode 100644 index f387849bc8..0000000000 --- a/share/icons/multicolor/symbolic/actions/arrow-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/share/icons/multicolor/symbolic/actions/color-whele-symbolic.svg b/share/icons/multicolor/symbolic/actions/color-whele-symbolic.svg deleted file mode 100644 index 718b77b382..0000000000 --- a/share/icons/multicolor/symbolic/actions/color-whele-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/share/icons/multicolor/symbolic/actions/list-symbolic.svg b/share/icons/multicolor/symbolic/actions/list-symbolic.svg deleted file mode 100644 index 1ad1a80d41..0000000000 --- a/share/icons/multicolor/symbolic/actions/list-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/share/icons/multicolor/symbolic/actions/reset-symbolic.svg b/share/icons/multicolor/symbolic/actions/reset-symbolic.svg deleted file mode 100644 index 7dcef2b3f7..0000000000 --- a/share/icons/multicolor/symbolic/actions/reset-symbolic.svg +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 333fe2073e..f77e1b4da4 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -38,7 +38,7 @@ false - reset-colors + reset-settings normal @@ -87,7 +87,7 @@ true - list-symbolic + hamburger-menu normal @@ -124,13 +124,13 @@ true - color-whele-symbolic + color-wheel-symbolic normal - Color Whele + Color Wheel center center diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index d93bf10c2b..c86a47e3d8 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -56,13 +56,13 @@ RecolorArt::RecolorArt() append(get_widget(_builder, "recolor-art")); _solid_colors->set(Color(0x000000ff)); - _layoutColorPicker(); + layoutColorPicker(); _color_list = _builder->get_widget("colors-list"); _live_preview = _builder->get_widget("liveP"); - _live_preview->signal_toggled().connect(sigc::mem_fun(*this, &RecolorArt::_onLivePreviewToggled)); + _live_preview->signal_toggled().connect(sigc::mem_fun(*this, &RecolorArt::onLivePreviewToggled)); _live_preview->set_active(true); _reset = _builder->get_widget("reset"); - _reset->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::_onResetClicked)); + _reset->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::onResetClicked)); _list_view = _builder->get_widget("recolor-art-list"); _color_model = Gio::ListStore::create(); @@ -114,14 +114,14 @@ RecolorArt::RecolorArt() auto recolored = dynamic_cast(box->get_last_child()); if (original && recolored) { - _colorButtons(original, item->old_color); - _colorButtons(recolored, item->new_color); + colorButtons(original, item->old_color); + colorButtons(recolored, item->new_color); original->set_name("original"); recolored->set_name("recolored"); original->signal_clicked().connect([this, item, index = list_item->get_position()] { // _selection_model->set_selected(index); - _onOriginalColorClicked(item->key); + onOriginalColorClicked(item->key); }); buttons[item->key] = {original, recolored}; } @@ -146,7 +146,7 @@ RecolorArt::RecolorArt() // if (!color_item) // return; - // _onOriginalColorClicked(color_item->key); + // onOriginalColorClicked(color_item->key); // }); // _apply = _builder->get_widget("apply"); @@ -161,39 +161,39 @@ void RecolorArt::setDesktop(SPDesktop *desktop) } g_message("setDesktop\n"); } -void RecolorArt::_collectColors(std::vector items) +void RecolorArt::collectColors(std::vector items) { _selected_colors.clear(); for (auto item : items) { - _extractItemColors(item); + extractItemColors(item); } } -void RecolorArt::_extractItemColors(SPItem *item) +void RecolorArt::extractItemColors(SPItem *item) { if (item) { - _extractItemStyle(item); + extractItemStyle(item); } if (auto group = dynamic_cast(item)) { for (SPObject &child : group->children) { if (auto childItem = dynamic_cast(&child)) { - _extractItemColors(childItem); + extractItemColors(childItem); } } } } -void RecolorArt::_extractGradientStops(SPItem *item, std::string kind, bool isFill) +void RecolorArt::extractGradientStops(SPItem *item, std::string kind, bool isFill) { SPPaintServer *paint_server = isFill ? item->style->getFillPaintServer() : item->style->getStrokePaintServer(); if (paint_server && dynamic_cast(paint_server)) { SPGradient *gradient = dynamic_cast(paint_server); for (auto stop : gradient->getGradientVector().stops) { if (stop.color.has_value()) { - _populateMap(stop.color.value(), item, kind); + populateMap(stop.color.value(), item, kind); } } } } -void RecolorArt::_populateMap(Color color, SPItem *item, std::string kind) +void RecolorArt::populateMap(Color color, SPItem *item, std::string kind) { ColorRef ref = ColorRef(item, kind); ColorPair pair = ColorPair(color, color); @@ -203,7 +203,7 @@ void RecolorArt::_populateMap(Color color, SPItem *item, std::string kind) _selected_colors.emplace(color.toString(), std::make_pair(std::vector{ref}, pair)); } } -void RecolorArt::_extractItemStyle(SPItem *item) +void RecolorArt::extractItemStyle(SPItem *item) { // check item style if (!item || !item->style) @@ -213,23 +213,23 @@ void RecolorArt::_extractItemStyle(SPItem *item) // get flat fills if (style->fill.isColor()) { auto color = style->fill.getColor(); - _populateMap(color, item, "fill"); + populateMap(color, item, "fill"); } // get gradient stops strokes else if (style->fill.isPaintserver()) { - _extractGradientStops(item, "stop-fill", true); + extractGradientStops(item, "stop-fill", true); } if (style->stroke.isColor()) { auto color = style->stroke.getColor(); - _populateMap(color, item, "stroke"); + populateMap(color, item, "stroke"); } // get gradient stops strokes else if (style->stroke.isPaintserver()) { - _extractGradientStops(item, "stop-stoke", false); + extractGradientStops(item, "stop-stoke", false); } } -void RecolorArt::_generateVisualList() +void RecolorArt::generateVisualList() { _color_model->remove_all(); buttons.clear(); @@ -240,14 +240,14 @@ void RecolorArt::_generateVisualList() } _color_list->append(*_list_view); } -void RecolorArt::_layoutColorPicker(std::shared_ptr updated_color) +void RecolorArt::layoutColorPicker(std::shared_ptr updated_color) { if (updated_color) _solid_colors = updated_color; _color_picker_wdgt = Gtk::make_managed(_solid_colors); _color_picker_wdgt->set_visible(true); _color_picker_wdgt->set_label(_("Selected Color")); - _solid_colors->signal_changed.connect(sigc::mem_fun(*this, &RecolorArt::_onColorPickerChanged)); + _solid_colors->signal_changed.connect(sigc::mem_fun(*this, &RecolorArt::onColorPickerChanged)); auto container = _builder->get_widget("color-picker"); if (container) { @@ -258,7 +258,7 @@ void RecolorArt::_layoutColorPicker(std::shared_ptr updated_co g_warning("color picker not found"); } } -void RecolorArt::_colorButtons(Gtk::Button *button, std::string color) +void RecolorArt::colorButtons(Gtk::Button *button, std::string color) { if (color.empty() || color.size() < 7 || color[0] != '#') { g_warning("Invalid color string: %s", color.c_str()); @@ -275,7 +275,7 @@ void RecolorArt::_colorButtons(Gtk::Button *button, std::string color) g_message("button not found"); } } -void RecolorArt::_colorBorderOnClick(Gtk::Button *button, bool kind) +void RecolorArt::colorBorderOnClick(Gtk::Button *button, bool kind) { auto &_last_button = kind == 1 ? _last_original_button : _last_recolored_button; if (_last_button && _last_button != button) { @@ -290,7 +290,7 @@ void RecolorArt::_colorBorderOnClick(Gtk::Button *button, bool kind) g_warning("button not found for border coloring"); } } -void RecolorArt::_onOriginalColorClicked(std::string color_id) +void RecolorArt::onOriginalColorClicked(std::string color_id) { _current_color_id = color_id; auto it = _selected_colors.find(color_id); @@ -299,13 +299,13 @@ void RecolorArt::_onOriginalColorClicked(std::string color_id) Color color = it->second.second.value().new_color; std::shared_ptr updated_color = std::make_shared(); updated_color->set(color); - _layoutColorPicker(updated_color); - _colorBorderOnClick(btns->second.first, 1); - _colorBorderOnClick(btns->second.second, 0); + layoutColorPicker(updated_color); + colorBorderOnClick(btns->second.first, 1); + colorBorderOnClick(btns->second.second, 0); // g_message("original color selected at color %s", color_id.c_str()); } } -void RecolorArt::_onColorPickerChanged() +void RecolorArt::onColorPickerChanged() { auto it = buttons.find(_current_color_id); if (it == buttons.end()) { @@ -319,16 +319,16 @@ void RecolorArt::_onColorPickerChanged() return; } std::string _color_string = new_color.value().toString(); - _colorButtons(_current_recolor_button, _color_string); + colorButtons(_current_recolor_button, _color_string); auto _selected = _selected_colors.find(_current_color_id); if (_selected != _selected_colors.end()) _selected->second.second.value().new_color = new_color.value(); if (_live_preview && _live_preview->property_active()) { - _lpChecked(); + lpChecked(); } g_message("color picker changed"); } -void RecolorArt::_lpChecked() +void RecolorArt::lpChecked() { auto _selected = _selected_colors.find(_current_color_id); std::optional new_color = _solid_colors->get(); @@ -350,15 +350,15 @@ void RecolorArt::_lpChecked() } DocumentUndo::done(_desktop->getDocument(), _("Recolored items"), INKSCAPE_ICON("object-recolor-art")); } -void RecolorArt::_onResetClicked() +void RecolorArt::onResetClicked() { for (auto [key, btns] : buttons) { - _colorButtons(btns.second, key); + colorButtons(btns.second, key); } - _revertToOriginalColors(); - _onOriginalColorClicked(buttons.begin()->first); + revertToOriginalColors(); + onOriginalColorClicked(buttons.begin()->first); } -void RecolorArt::_revertToOriginalColors() +void RecolorArt::revertToOriginalColors() { for (auto [key, items] : _selected_colors) { for (auto &item : items.first) { @@ -369,7 +369,7 @@ void RecolorArt::_revertToOriginalColors() } } } -void RecolorArt::_convertToRecoloredColors() +void RecolorArt::convertToRecoloredColors() { for (auto [key, items] : _selected_colors) { if (items.second.has_value()) { @@ -383,13 +383,13 @@ void RecolorArt::_convertToRecoloredColors() } } } -void RecolorArt::_onLivePreviewToggled() +void RecolorArt::onLivePreviewToggled() { _is_preview = _live_preview->property_active(); if (_is_preview) { - _convertToRecoloredColors(); + convertToRecoloredColors(); } else { - _revertToOriginalColors(); + revertToOriginalColors(); } g_message(_is_preview ? "is true" : "is false"); g_message("LP toggled"); @@ -405,11 +405,11 @@ void RecolorArt::performUpdate() // _current_color_id = ""; if (auto selection = _desktop->getSelection()) { std::vector vec(selection->items().begin(), selection->items().end()); - _collectColors(vec); + collectColors(vec); if (!_selected_colors.empty()) { - _generateVisualList(); + generateVisualList(); auto first_button_id = buttons.begin()->first; - _onOriginalColorClicked(first_button_id); + onOriginalColorClicked(first_button_id); } } diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 668bdde87f..53f66aa0eb 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -96,26 +96,26 @@ private: Gtk::Button *_last_recolored_button = nullptr; // Gtk::Button *_apply = nullptr; -protected: + Glib::RefPtr _builder; - void _populateMap(Color color, SPItem *style, std::string kind); - void _collectColors(std::vector items); - void _extractGradientStops(SPItem *item, std::string kind, bool isFill); - void _extractItemColors(SPItem *item); - void _extractItemStyle(SPItem *item); - void _generateVisualList(); - void _layoutColorPicker(std::shared_ptr updated_color = nullptr); - void _colorButtons(Gtk::Button *button, std::string color); - void _colorBorderOnClick(Gtk::Button *button , bool kind); + void populateMap(Color color, SPItem *style, std::string kind); + void collectColors(std::vector items); + void extractGradientStops(SPItem *item, std::string kind, bool isFill); + void extractItemColors(SPItem *item); + void extractItemStyle(SPItem *item); + void generateVisualList(); + void layoutColorPicker(std::shared_ptr updated_color = nullptr); + void colorButtons(Gtk::Button *button, std::string color); + void colorBorderOnClick(Gtk::Button *button , bool kind); // signals handelrs - void _onOriginalColorClicked(std::string color_id); - void _onResetClicked(); - void _onColorPickerChanged(); - void _onLivePreviewToggled(); - void _lpChecked(); - void _revertToOriginalColors(); - void _convertToRecoloredColors(); + void onOriginalColorClicked(std::string color_id); + void onResetClicked(); + void onColorPickerChanged(); + void onLivePreviewToggled(); + void lpChecked(); + void revertToOriginalColors(); + void convertToRecoloredColors(); // void _onApplyButtonClicked(); public: -- GitLab From 1076b576ac9080e11ab0be46c05be88a2fc29905 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sat, 28 Jun 2025 07:42:36 +0300 Subject: [PATCH 023/122] rewrite css in inkscape standard themed form --- share/ui/recolor-art.glade | 2 +- share/ui/style.css | 57 ++++++++++---------------------------- 2 files changed, 15 insertions(+), 44 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index f77e1b4da4..5c953c9301 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -23,7 +23,7 @@ horizontal center center - 64 + 85 Original diff --git a/share/ui/style.css b/share/ui/style.css index fe9c03abeb..70de3b7768 100644 --- a/share/ui/style.css +++ b/share/ui/style.css @@ -1684,25 +1684,25 @@ button.reduced-padding { min-width: 180px; min-height: 14px; border-radius: 4px; - padding: 0; + padding: 0px; margin: 0px; - border: 2px solid black; + border: 2px solid @theme_bg_color; } #original-recolor-box button#original:hover { min-width: 180px; min-height: 14px; border-radius: 4px; - padding: 0; + padding: 0px; margin: 0px; - border: 2px solid white; + border: 2px solid @theme_fq_color; } #original-recolor-box button.selected-button { min-width: 180px; min-height: 14px; border-radius: 4px; - padding: 0; + padding: 0px; margin: 0px; - border: 2px solid white; + border: 2px solid @theme_fq_color; } #original-reset-recolor label @@ -1714,62 +1714,33 @@ button.reduced-padding { #original-reset-recolor { - margin-right: 24px; - margin-bottom: 12px; + + margin-left: 2px; + margin-right: 38px; + margin-bottom: 6px; + margin-top: 6px; } #original-recolor-box { min-width: 180px; min-height: 14px; - /* margin-left:36px; - margin-right:36px; */ } #recolor-art listview row:selected { background-color: transparent; - border-radius: 4px; - border: 2px solid #0D57C3; -} - -#recolor-art listview -{ - padding: 0px; - margin: 0px; - background-color:#2A2A2A ; -} - -#original-recolor-colors-list-box -{ - background-color:#2A2A2A ; -} -#reset -{ - background-color:#474747; - color:white; - border: 2px solid #000 ; - margin-top:6px; -} - -#reset:hover { - background-color: #202020; - color: white; - border: 2px solid #000; - margin-top: 6px; + /* border-radius: 4px; */ + /* border: 2px solid #0D57C3; */ } - #list-wheel-box { - background-color:#2A2A2A; margin:4px; - border: 2px solid #000 ; + border: 2px solid @theme_bg_color ; } #list-wheel-box label { font-size: 16px; - color: white; font-weight: 200; - background-image: none; } \ No newline at end of file -- GitLab From f64f96997f26ec01049f1beec81009bd662d69a1 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sat, 28 Jun 2025 10:15:22 +0300 Subject: [PATCH 024/122] gradients changing colors --- src/ui/widget/recolor-art.cpp | 52 +++++++++++++++++++++++++++++++++-- src/ui/widget/recolor-art.h | 5 ++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index c86a47e3d8..6cd18fff2b 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -186,13 +186,29 @@ void RecolorArt::extractGradientStops(SPItem *item, std::string kind, bool isFil SPPaintServer *paint_server = isFill ? item->style->getFillPaintServer() : item->style->getStrokePaintServer(); if (paint_server && dynamic_cast(paint_server)) { SPGradient *gradient = dynamic_cast(paint_server); - for (auto stop : gradient->getGradientVector().stops) { + SPGradient *vectorGradient = gradient->getVector(); + if (vectorGradient) { + vectorGradient->ensureVector(); + int stopCount = vectorGradient->getStopCount(); + std::cout << "Stops count : " << stopCount << std::endl; + populateStopsMap(vectorGradient->getFirstStop()); + } + for (auto stop : vectorGradient->getGradientVector().stops) { if (stop.color.has_value()) { populateMap(stop.color.value(), item, kind); } } } } +void RecolorArt::populateStopsMap(SPStop *stop) +{ + g_message("populateStopsMap in"); + while (stop) { + std::string color = stop->getColor().toString(); + _gradient_stops[color].push_back(stop); + stop = stop->getNextStop(); + } +} void RecolorArt::populateMap(Color color, SPItem *item, std::string kind) { ColorRef ref = ColorRef(item, kind); @@ -217,7 +233,7 @@ void RecolorArt::extractItemStyle(SPItem *item) } // get gradient stops strokes else if (style->fill.isPaintserver()) { - extractGradientStops(item, "stop-fill", true); + extractGradientStops(item, "stop", true); } if (style->stroke.isColor()) { @@ -226,7 +242,7 @@ void RecolorArt::extractItemStyle(SPItem *item) } // get gradient stops strokes else if (style->stroke.isPaintserver()) { - extractGradientStops(item, "stop-stoke", false); + extractGradientStops(item, "stop", false); } } void RecolorArt::generateVisualList() @@ -343,11 +359,14 @@ void RecolorArt::lpChecked() } _selected->second.second.value().new_color = new_color.value(); for (auto &item : _selected->second.first) { + if (item.kind == "stop") + continue; SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property_string(css, item.kind.c_str(), _color_string); sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } + recolorStops(_selected->first, new_color.value()); DocumentUndo::done(_desktop->getDocument(), _("Recolored items"), INKSCAPE_ICON("object-recolor-art")); } void RecolorArt::onResetClicked() @@ -362,11 +381,14 @@ void RecolorArt::revertToOriginalColors() { for (auto [key, items] : _selected_colors) { for (auto &item : items.first) { + if (item.kind == "stop") + continue; SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property_string(css, item.kind.c_str(), key); sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } + recolorStops(key, items.second.value().old_color); } } void RecolorArt::convertToRecoloredColors() @@ -375,11 +397,23 @@ void RecolorArt::convertToRecoloredColors() if (items.second.has_value()) { std::string new_color = items.second.value().new_color.toString(); for (auto &item : items.first) { + if (item.kind == "stop") + continue; SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property_string(css, item.kind.c_str(), new_color); sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } + recolorStops(key, items.second.value().new_color); + } + } +} +void RecolorArt::recolorStops(std::string old_color, Color new_color) +{ + auto stops_vector = _gradient_stops.find(old_color); + if (stops_vector != _gradient_stops.end()) { + for (auto stop : stops_vector->second) { + stop->setColor(new_color); } } } @@ -400,6 +434,7 @@ void RecolorArt::performUpdate() _color_list->remove(*child); } buttons.clear(); + _gradient_stops.clear(); _last_original_button = nullptr; _last_recolored_button = nullptr; // _current_color_id = ""; @@ -412,7 +447,18 @@ void RecolorArt::performUpdate() onOriginalColorClicked(first_button_id); } } + if (!_gradient_stops.empty()) { + for (auto [key, value] : _gradient_stops) { + std::cout << key << " : "; + for (auto stop : value) + std::cout << stop << " "; + std::cout << std::endl; + } + g_message("filled stops map"); + } else { + g_message("empty stops map"); + } g_message("Performing Update\n"); } } // namespace Widget diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 53f66aa0eb..92ac72624d 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -95,6 +95,8 @@ private: Gtk::Button *_last_original_button = nullptr; Gtk::Button *_last_recolored_button = nullptr; + std::map>_gradient_stops; + // Gtk::Button *_apply = nullptr; Glib::RefPtr _builder; @@ -118,6 +120,9 @@ private: void convertToRecoloredColors(); // void _onApplyButtonClicked(); + void populateStopsMap(SPStop* stop); + void recolorStops(std::string old_color ,Color new_color); + public: RecolorArt(); ~RecolorArt(); -- GitLab From 401838f1818f245c578bfd0bedb7d4327c030fab Mon Sep 17 00:00:00 2001 From: ftomara Date: Sat, 28 Jun 2025 14:33:57 +0300 Subject: [PATCH 025/122] added mesh gradients color collection and ability to change it --- src/ui/widget/recolor-art.cpp | 54 ++++++++++++++++++++++++----------- src/ui/widget/recolor-art.h | 11 +++---- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 6cd18fff2b..cc8e565ecb 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -188,10 +188,21 @@ void RecolorArt::extractGradientStops(SPItem *item, std::string kind, bool isFil SPGradient *gradient = dynamic_cast(paint_server); SPGradient *vectorGradient = gradient->getVector(); if (vectorGradient) { - vectorGradient->ensureVector(); - int stopCount = vectorGradient->getStopCount(); - std::cout << "Stops count : " << stopCount << std::endl; - populateStopsMap(vectorGradient->getFirstStop()); + if (vectorGradient->hasPatches()) { + vectorGradient->ensureArray(); + std::unique_ptr nodeArray; + if (auto mesh = dynamic_cast(gradient)) { + nodeArray = std::make_unique(mesh); + extractMeshStops(nodeArray->nodes, item, kind); + } + + } else { + vectorGradient->ensureVector(); + // int stopCount = vectorGradient->getStopCount(); + // std::cout << "Stops count : " << stopCount << std::endl; + // std::cout << "has patches : " << vectorGradient->hasPatches() << std::endl; + populateStopsMap(vectorGradient->getFirstStop()); + } } for (auto stop : vectorGradient->getGradientVector().stops) { if (stop.color.has_value()) { @@ -200,6 +211,17 @@ void RecolorArt::extractGradientStops(SPItem *item, std::string kind, bool isFil } } } +void RecolorArt::extractMeshStops(std::vector> mesh_nodes, SPItem *item, std::string kind) +{ + for (auto nodes : mesh_nodes) { + for (auto node : nodes) { + populateStopsMap(node->stop); + if (node->color.has_value()) { + populateMap(node->color.value(), item, kind); + } + } + } +} void RecolorArt::populateStopsMap(SPStop *stop) { g_message("populateStopsMap in"); @@ -447,18 +469,6 @@ void RecolorArt::performUpdate() onOriginalColorClicked(first_button_id); } } - if (!_gradient_stops.empty()) { - for (auto [key, value] : _gradient_stops) { - std::cout << key << " : "; - for (auto stop : value) - std::cout << stop << " "; - std::cout << std::endl; - } - g_message("filled stops map"); - - } else { - g_message("empty stops map"); - } g_message("Performing Update\n"); } } // namespace Widget @@ -477,4 +487,16 @@ void RecolorArt::performUpdate() // } // } // g_message("apply clicked"); +// } +// if (!_gradient_stops.empty()) { +// for (auto [key, value] : _gradient_stops) { +// std::cout << key << " : "; +// for (auto stop : value) +// std::cout << stop << " "; +// std::cout << std::endl; +// } +// g_message("filled stops map"); + +// } else { +// g_message("empty stops map"); // } \ No newline at end of file diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 92ac72624d..2518d1b043 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -95,20 +95,21 @@ private: Gtk::Button *_last_original_button = nullptr; Gtk::Button *_last_recolored_button = nullptr; - std::map>_gradient_stops; + std::map> _gradient_stops; // Gtk::Button *_apply = nullptr; - + Glib::RefPtr _builder; void populateMap(Color color, SPItem *style, std::string kind); void collectColors(std::vector items); void extractGradientStops(SPItem *item, std::string kind, bool isFill); + void extractMeshStops(std::vector> mesh_nodes, SPItem *item, std::string kind); void extractItemColors(SPItem *item); void extractItemStyle(SPItem *item); void generateVisualList(); void layoutColorPicker(std::shared_ptr updated_color = nullptr); void colorButtons(Gtk::Button *button, std::string color); - void colorBorderOnClick(Gtk::Button *button , bool kind); + void colorBorderOnClick(Gtk::Button *button, bool kind); // signals handelrs void onOriginalColorClicked(std::string color_id); @@ -120,8 +121,8 @@ private: void convertToRecoloredColors(); // void _onApplyButtonClicked(); - void populateStopsMap(SPStop* stop); - void recolorStops(std::string old_color ,Color new_color); + void populateStopsMap(SPStop *stop); + void recolorStops(std::string old_color, Color new_color); public: RecolorArt(); -- GitLab From 2004c66d1f35571609069d17bb4f4a8179e412bc Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 29 Jun 2025 09:10:25 +0300 Subject: [PATCH 026/122] only shows recolor tab when selection is greater than 1 --- src/ui/dialog/fill-and-stroke.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index b0eb9acdf7..3b80512e0b 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -23,6 +23,7 @@ #include "desktop-style.h" #include "desktop.h" +#include "selection.h" #include "preferences.h" #include "ui/icon-loader.h" #include "ui/icon-names.h" @@ -86,6 +87,11 @@ FillAndStroke::~FillAndStroke() void FillAndStroke::selectionChanged(Selection *selection) { + if(selection->size()<=1) + _page_recolor_art->hide(); + else + _page_recolor_art->show(); + if (!page_changed) { changed_fill = true; changed_stroke = true; -- GitLab From 7aba8549eb434e93ebcd89340f686a9b16852588 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 29 Jun 2025 10:16:08 +0300 Subject: [PATCH 027/122] removed standard colorpicker on activiated color wheel tab --- src/ui/widget/recolor-art.cpp | 15 +++++++++++++++ src/ui/widget/recolor-art.h | 5 +++++ 2 files changed, 20 insertions(+) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index cc8e565ecb..aa7deccc16 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -15,6 +15,7 @@ #include // #include +#include #include #include "actions/actions-tools.h" @@ -64,6 +65,20 @@ RecolorArt::RecolorArt() _reset = _builder->get_widget("reset"); _reset->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::onResetClicked)); + _notebook = _builder->get_widget("list-wheel-box"); + _color_wheel_page = _builder->get_widget("color-wheel-page"); + _notebook->signal_switch_page().connect([this](Gtk::Widget* page, guint page_num) { + int wheel_index = _notebook->page_num(*_color_wheel_page); + + if (static_cast(page_num) == wheel_index) { + _color_picker_wdgt->set_visible(false); + // std::cout << "Color Wheel tab is active.\n"; + } else { + _color_picker_wdgt->set_visible(true); + // std::cout << "Color Wheel tab is NOT active.\n"; + } + }); + _list_view = _builder->get_widget("recolor-art-list"); _color_model = Gio::ListStore::create(); _selection_model = Gtk::SingleSelection::create(_color_model); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 2518d1b043..b50f548d7a 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -32,6 +33,7 @@ namespace Gtk { class Widget; class Builder; class ListStore; +class Notebook; } // namespace Gtk class SPDesktop; @@ -97,6 +99,9 @@ private: std::map> _gradient_stops; + Gtk::Notebook *_notebook = nullptr; + Gtk::Box *_color_wheel_page = nullptr; + // Gtk::Button *_apply = nullptr; Glib::RefPtr _builder; -- GitLab From 2c23856ee2f8f81fd242894e03f3dceaf6d52a12 Mon Sep 17 00:00:00 2001 From: ftomara Date: Wed, 2 Jul 2025 15:51:52 +0300 Subject: [PATCH 028/122] fixed row and items selection by changing the color model too --- src/ui/widget/recolor-art.cpp | 74 +++++++++++++++++++++-------------- src/ui/widget/recolor-art.h | 2 +- 2 files changed, 46 insertions(+), 30 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index aa7deccc16..f0abcc1223 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -135,7 +135,12 @@ RecolorArt::RecolorArt() original->set_name("original"); recolored->set_name("recolored"); original->signal_clicked().connect([this, item, index = list_item->get_position()] { - // _selection_model->set_selected(index); + _selection_model->set_selected(index); + onOriginalColorClicked(item->key); + }); + + recolored->signal_clicked().connect([this, item, index = list_item->get_position()] { + _selection_model->set_selected(index); onOriginalColorClicked(item->key); }); buttons[item->key] = {original, recolored}; @@ -151,18 +156,18 @@ RecolorArt::RecolorArt() _list_view->set_hexpand(false); _list_view->set_vexpand(false); - // _selection_model->signal_selection_changed().connect([this](guint pos, guint n_items) { - // int index = _selection_model->get_selected(); - // if (index < 0) - // return; + _selection_model->signal_selection_changed().connect([this](guint pos, guint n_items) { + int index = _selection_model->get_selected(); + if (index < 0) + return; - // auto item = _color_model->get_item(index); - // auto color_item = std::dynamic_pointer_cast(item); - // if (!color_item) - // return; + auto item = _color_model->get_item(index); + auto color_item = std::dynamic_pointer_cast(item); + if (!color_item) + return; - // onOriginalColorClicked(color_item->key); - // }); + onOriginalColorClicked(color_item->key); + }); // _apply = _builder->get_widget("apply"); // _apply->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::_onApplyButtonClicked)); @@ -288,7 +293,7 @@ void RecolorArt::generateVisualList() buttons.clear(); for (auto &[key, value] : _selected_colors) { auto old_color = value.second.value().old_color.toString(); - auto new_color = value.second.value().old_color.toString(); + auto new_color = value.second.value().new_color.toString(); _color_model->append(ColorItem::create(key, old_color, new_color)); } _color_list->append(*_list_view); @@ -328,21 +333,21 @@ void RecolorArt::colorButtons(Gtk::Button *button, std::string color) g_message("button not found"); } } -void RecolorArt::colorBorderOnClick(Gtk::Button *button, bool kind) -{ - auto &_last_button = kind == 1 ? _last_original_button : _last_recolored_button; - if (_last_button && _last_button != button) { - auto style_context = _last_button->get_style_context(); - style_context->remove_class("selected-button"); - } - if (button) { - auto style_context = button->get_style_context(); - style_context->add_class("selected-button"); - _last_button = button; - } else { - g_warning("button not found for border coloring"); - } -} +// void RecolorArt::colorBorderOnClick(Gtk::Button *button, bool kind) +// { +// auto &_last_button = kind == 1 ? _last_original_button : _last_recolored_button; +// if (_last_button && _last_button != button) { +// auto style_context = _last_button->get_style_context(); +// style_context->remove_class("selected-button"); +// } +// if (button) { +// auto style_context = button->get_style_context(); +// style_context->add_class("selected-button"); +// _last_button = button; +// } else { +// g_warning("button not found for border coloring"); +// } +// } void RecolorArt::onOriginalColorClicked(std::string color_id) { _current_color_id = color_id; @@ -353,8 +358,8 @@ void RecolorArt::onOriginalColorClicked(std::string color_id) std::shared_ptr updated_color = std::make_shared(); updated_color->set(color); layoutColorPicker(updated_color); - colorBorderOnClick(btns->second.first, 1); - colorBorderOnClick(btns->second.second, 0); + // colorBorderOnClick(btns->second.first, 1); + // colorBorderOnClick(btns->second.second, 0); // g_message("original color selected at color %s", color_id.c_str()); } } @@ -379,6 +384,10 @@ void RecolorArt::onColorPickerChanged() if (_live_preview && _live_preview->property_active()) { lpChecked(); } + guint index = _selection_model->get_selected(); + auto item = _color_model->get_item(index); + auto color_item = std::dynamic_pointer_cast(item); + color_item->new_color = _color_string; g_message("color picker changed"); } void RecolorArt::lpChecked() @@ -411,6 +420,13 @@ void RecolorArt::onResetClicked() for (auto [key, btns] : buttons) { colorButtons(btns.second, key); } + + for(auto i =0; i<_color_model->get_n_items();i++) + { + auto item = _color_model->get_item(i); + auto color_item = std::dynamic_pointer_cast(item); + color_item->new_color = color_item->key; + } revertToOriginalColors(); onOriginalColorClicked(buttons.begin()->first); } diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index b50f548d7a..0c9e9eda6a 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -114,7 +114,7 @@ private: void generateVisualList(); void layoutColorPicker(std::shared_ptr updated_color = nullptr); void colorButtons(Gtk::Button *button, std::string color); - void colorBorderOnClick(Gtk::Button *button, bool kind); + // void colorBorderOnClick(Gtk::Button *button, bool kind); // signals handelrs void onOriginalColorClicked(std::string color_id); -- GitLab From 2e55ef09486f59de34c8ccfde38a499ac787a187 Mon Sep 17 00:00:00 2001 From: ftomara Date: Wed, 2 Jul 2025 16:03:44 +0300 Subject: [PATCH 029/122] made the color button fill available horizontal space , removed unneccessary styles --- share/ui/recolor-art.glade | 20 ++++++------ share/ui/style.css | 61 ++--------------------------------- src/ui/widget/recolor-art.cpp | 15 +++------ 3 files changed, 18 insertions(+), 78 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 5c953c9301..40076633e2 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -27,7 +27,7 @@ Original - center + fill @@ -54,23 +54,25 @@ - True - False - True + true + true + true + centre never - False + false colors-list vertical - center - center + true + fill + fill false - center + fill true - center + fill diff --git a/share/ui/style.css b/share/ui/style.css index 70de3b7768..195ee9a75e 100644 --- a/share/ui/style.css +++ b/share/ui/style.css @@ -1681,66 +1681,11 @@ button.reduced-padding { */ #original, #recolored { - min-width: 180px; - min-height: 14px; + min-height: 6px; border-radius: 4px; - padding: 0px; - margin: 0px; border: 2px solid @theme_bg_color; } -#original-recolor-box button#original:hover { - min-width: 180px; - min-height: 14px; - border-radius: 4px; - padding: 0px; - margin: 0px; - border: 2px solid @theme_fq_color; -} -#original-recolor-box button.selected-button { - min-width: 180px; - min-height: 14px; - border-radius: 4px; - padding: 0px; - margin: 0px; - border: 2px solid @theme_fq_color; -} - -#original-reset-recolor label -{ - font-size: 16px; - font-weight: bold; - -} - -#original-reset-recolor -{ - - margin-left: 2px; - margin-right: 38px; - margin-bottom: 6px; - margin-top: 6px; - -} - -#original-recolor-box { - min-width: 180px; - min-height: 14px; -} - -#recolor-art listview row:selected { - background-color: transparent; - /* border-radius: 4px; */ - /* border: 2px solid #0D57C3; */ -} -#list-wheel-box -{ - margin:4px; - border: 2px solid @theme_bg_color ; +#original-recolor-box button#original:hover,button#recolored:hover { + border: 2px solid @theme_fq_color; } - -#list-wheel-box label -{ - font-size: 16px; - font-weight: 200; -} \ No newline at end of file diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index f0abcc1223..b253df920a 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -90,13 +90,11 @@ RecolorArt::RecolorArt() auto arrow = Gtk::make_managed(); auto recolored = Gtk::make_managed(); - original->set_hexpand(false); - original->set_vexpand(false); - original->set_valign(Gtk::Align::CENTER); + original->set_hexpand(true); + + + recolored->set_hexpand(true); - recolored->set_hexpand(false); - recolored->set_vexpand(false); - recolored->set_valign(Gtk::Align::CENTER); arrow->set_use_markup(true); arrow->set_width_chars(3); @@ -105,11 +103,6 @@ RecolorArt::RecolorArt() arrow->set_valign(Gtk::Align::CENTER); box->set_name("original-recolor-box"); - box->set_spacing(14); - box->set_margin_top(0); - box->set_margin_bottom(0); - box->set_margin_start(0); - box->set_margin_end(0); box->append(*original); box->append(*arrow); box->append(*recolored); -- GitLab From 03b83dde3ae0622f8759dced93faf973a33cd48f Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 3 Jul 2025 17:46:00 +0300 Subject: [PATCH 030/122] style refinements and unreformatted the style.css file --- share/ui/recolor-art.glade | 2 ++ share/ui/style.css | 17 +++++++++++++---- src/ui/widget/recolor-art.cpp | 3 ++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 40076633e2..1941dcec77 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -36,6 +36,8 @@ true false false + center + 18 reset-settings diff --git a/share/ui/style.css b/share/ui/style.css index 195ee9a75e..f46b4f24ea 100644 --- a/share/ui/style.css +++ b/share/ui/style.css @@ -1680,12 +1680,21 @@ button.reduced-padding { ********************** */ -#original, #recolored { + +#recolor-art #original, +#recolored { min-height: 6px; border-radius: 4px; - border: 2px solid @theme_bg_color; + border: 2px solid transparent; +} + +#original-recolor-box button#original:hover, +button#recolored:hover { + border-color: @theme_fq_color; } -#original-recolor-box button#original:hover,button#recolored:hover { - border: 2px solid @theme_fq_color; +#recolor-art listview row:selected { + background-color: transparent; + border: 2px solid @theme_selected_bg_color; + border-radius: 4px; } diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index b253df920a..ac9788db23 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -97,10 +97,11 @@ RecolorArt::RecolorArt() arrow->set_use_markup(true); - arrow->set_width_chars(3); + arrow->set_width_chars(6); arrow->set_markup("➔"); arrow->set_halign(Gtk::Align::CENTER); arrow->set_valign(Gtk::Align::CENTER); + arrow->set_margin_top(3); box->set_name("original-recolor-box"); box->append(*original); -- GitLab From a1f8ec9c6d63c71ff6a36ab556bc9289bb615f24 Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 3 Jul 2025 18:01:18 +0300 Subject: [PATCH 031/122] made the recolor art as a popover in the end of fill tab --- src/ui/dialog/fill-and-stroke.cpp | 87 +++++++++++++++---------------- src/ui/dialog/fill-and-stroke.h | 3 ++ 2 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index 3b80512e0b..d06523d14d 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -23,14 +23,12 @@ #include "desktop-style.h" #include "desktop.h" -#include "selection.h" #include "preferences.h" +#include "selection.h" #include "ui/icon-loader.h" #include "ui/icon-names.h" #include "ui/pack.h" #include "ui/widget/fill-style.h" -#include "ui/widget/stroke-style.h" -#include "ui/widget/recolor-art.h" #include "ui/widget/notebook-page.h" #include "ui/widget/recolor-art.h" #include "ui/widget/stroke-style.h" @@ -43,23 +41,24 @@ FillAndStroke::FillAndStroke() , _page_stroke_paint(Gtk::make_managed(1, 1)) , _page_stroke_style(Gtk::make_managed(1, 1)) , _page_recolor_art(Gtk::make_managed(1, 1)) - , _composite_settings(INKSCAPE_ICON("dialog-fill-and-stroke"), - "fillstroke", - UI::Widget::SimpleFilterModifier::ISOLATION | - UI::Widget::SimpleFilterModifier::BLEND | - UI::Widget::SimpleFilterModifier::BLUR | - UI::Widget::SimpleFilterModifier::OPACITY) + , _composite_settings(INKSCAPE_ICON("dialog-fill-and-stroke"), "fillstroke", + UI::Widget::SimpleFilterModifier::ISOLATION | UI::Widget::SimpleFilterModifier::BLEND | + UI::Widget::SimpleFilterModifier::BLUR | UI::Widget::SimpleFilterModifier::OPACITY) , fillWdgt(nullptr) , strokeWdgt(nullptr) - ,recolorArtWdgt(nullptr) + , recolorArtWdgt(nullptr) + , recolorButtonTriger(Gtk::make_managed()) + , recolorPopOver(Gtk::make_managed()) { set_spacing(2); UI::pack_start(*this, _notebook, true, true); _notebook.append_page(*_page_fill, _createPageTabLabel(_("_Fill"), INKSCAPE_ICON("object-fill"))); _notebook.append_page(*_page_stroke_paint, _createPageTabLabel(_("Stroke _paint"), INKSCAPE_ICON("object-stroke"))); - _notebook.append_page(*_page_stroke_style, _createPageTabLabel(_("Stroke st_yle"), INKSCAPE_ICON("object-stroke-style"))); - _notebook.append_page(*_page_recolor_art, _createPageTabLabel(_("Recolor"), INKSCAPE_ICON("object-recolor-art"))); + _notebook.append_page(*_page_stroke_style, + _createPageTabLabel(_("Stroke st_yle"), INKSCAPE_ICON("object-stroke-style"))); + // _notebook.append_page(*_page_recolor_art, _createPageTabLabel(_("Recolor"), + // INKSCAPE_ICON("object-recolor-art"))); _notebook.set_vexpand(true); _switch_page_conn = _notebook.signal_switch_page().connect(sigc::mem_fun(*this, &FillAndStroke::_onSwitchPage)); @@ -69,6 +68,14 @@ FillAndStroke::FillAndStroke() _layoutPageStrokeStyle(); _layoutPageRecolorArt(); + recolorButtonTriger->set_label("Recolor Selection"); + recolorButtonTriger->signal_clicked().connect([this]() { + recolorPopOver->popup(); + recolorArtWdgt->performUpdate(); + }); + recolorPopOver->set_parent(*recolorButtonTriger); + recolorPopOver->set_child(*_page_recolor_art); + UI::pack_end(*this, _composite_settings, UI::PackOptions::shrink); _composite_settings.setSubject(&_subject); @@ -87,10 +94,10 @@ FillAndStroke::~FillAndStroke() void FillAndStroke::selectionChanged(Selection *selection) { - if(selection->size()<=1) - _page_recolor_art->hide(); + if (selection->size() <= 1) + recolorButtonTriger->hide(); else - _page_recolor_art->show(); + recolorButtonTriger->show(); if (!page_changed) { changed_fill = true; @@ -107,10 +114,10 @@ void FillAndStroke::selectionChanged(Selection *selection) if (strokeStyleWdgt && npage == 2) { strokeStyleWdgt->selectionChangedCB(); } - if (recolorArtWdgt && npage == 3) { - // if (!recolorArtWdgt->isInPreviewMode()) - recolorArtWdgt->performUpdate(); - } + // if (recolorArtWdgt && npage == 3) { + // // if (!recolorArtWdgt->isInPreviewMode()) + // recolorArtWdgt->performUpdate(); + // } } void FillAndStroke::selectionModified(Selection *selection, guint flags) @@ -128,11 +135,11 @@ void FillAndStroke::selectionModified(Selection *selection, guint flags) if (strokeStyleWdgt && npage == 2) { strokeStyleWdgt->selectionModifiedCB(flags); } - if (recolorArtWdgt && npage == 3) { + // if (recolorArtWdgt && npage == 3) { // if (!recolorArtWdgt->isInPreviewMode()) { // recolorArtWdgt->performUpdate(); // } -} + // } } void FillAndStroke::desktopReplaced() @@ -170,7 +177,7 @@ void FillAndStroke::_onSwitchPage(Gtk::Widget *page, guint pagenum) } else if (npage == 2 && changed_stroke_style) { update = true; changed_stroke_style = false; - }else if (npage == 3 && changed_recolor_art) { + } else if (npage == 3 && changed_recolor_art) { update = true; changed_recolor_art = false; } @@ -183,82 +190,70 @@ void FillAndStroke::_onSwitchPage(Gtk::Widget *page, guint pagenum) _savePagePref(pagenum); } -void -FillAndStroke::_savePagePref(guint page_num) +void FillAndStroke::_savePagePref(guint page_num) { // remember the current page Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setInt("/dialogs/fillstroke/page", page_num); } -void -FillAndStroke::_layoutPageFill() +void FillAndStroke::_layoutPageFill() { fillWdgt = Gtk::make_managed(FILL); _page_fill->table().attach(*fillWdgt, 0, 0, 1, 1); + _page_fill->append(*recolorButtonTriger); } -void -FillAndStroke::_layoutPageStrokePaint() +void FillAndStroke::_layoutPageStrokePaint() { strokeWdgt = Gtk::make_managed(STROKE); _page_stroke_paint->table().attach(*strokeWdgt, 0, 0, 1, 1); } -void -FillAndStroke::_layoutPageStrokeStyle() +void FillAndStroke::_layoutPageStrokeStyle() { strokeStyleWdgt = Gtk::make_managed(); strokeStyleWdgt->set_hexpand(); strokeStyleWdgt->set_halign(Gtk::Align::START); _page_stroke_style->table().attach(*strokeStyleWdgt, 0, 0, 1, 1); } -void -FillAndStroke::_layoutPageRecolorArt() +void FillAndStroke::_layoutPageRecolorArt() { recolorArtWdgt = Gtk::make_managed(); recolorArtWdgt->set_hexpand(); recolorArtWdgt->set_halign(Gtk::Align::FILL); - _page_recolor_art->table().attach(*recolorArtWdgt,0,0,1,1); + _page_recolor_art->table().attach(*recolorArtWdgt, 0, 0, 1, 1); } -void -FillAndStroke::showPageFill() +void FillAndStroke::showPageFill() { blink(); _notebook.set_current_page(0); _savePagePref(0); - } -void -FillAndStroke::showPageStrokePaint() +void FillAndStroke::showPageStrokePaint() { blink(); _notebook.set_current_page(1); _savePagePref(1); } -void -FillAndStroke::showPageStrokeStyle() +void FillAndStroke::showPageStrokeStyle() { blink(); _notebook.set_current_page(2); _savePagePref(2); - } -void -FillAndStroke::showPageRecolorArt() +void FillAndStroke::showPageRecolorArt() { blink(); _notebook.set_current_page(3); _savePagePref(3); - } -Gtk::Box& -FillAndStroke::_createPageTabLabel(const Glib::ustring& label, const char *label_image) +Gtk::Box &FillAndStroke::_createPageTabLabel(Glib::ustring const &label, char const *label_image) { auto const _tab_label_box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL, 4); diff --git a/src/ui/dialog/fill-and-stroke.h b/src/ui/dialog/fill-and-stroke.h index 24d8c5f6eb..85d9630ea4 100644 --- a/src/ui/dialog/fill-and-stroke.h +++ b/src/ui/dialog/fill-and-stroke.h @@ -24,6 +24,7 @@ namespace Gtk { class Box; +class Popover; } // namespace Gtk namespace Inkscape::UI { @@ -84,6 +85,8 @@ private: UI::Widget::FillNStroke *strokeWdgt = nullptr; UI::Widget::StrokeStyle *strokeStyleWdgt = nullptr; UI::Widget::RecolorArt *recolorArtWdgt = nullptr; + Gtk::Button *recolorButtonTriger = nullptr; + Gtk::Popover* recolorPopOver=nullptr; sigc::scoped_connection _switch_page_conn; }; -- GitLab From c484a139fdf66476b9861d81badd284217dd4fbf Mon Sep 17 00:00:00 2001 From: ftomara Date: Sat, 5 Jul 2025 13:46:11 +0300 Subject: [PATCH 032/122] added the recolor popover to paint selector --- share/ui/recolor-art.glade | 1 + src/3rdparty/2geom | 2 +- src/3rdparty/libcroco | 2 +- src/ui/widget/paint-selector.cpp | 96 +++++++++++++++++++++++++++++++- src/ui/widget/paint-selector.h | 12 ++++ src/ui/widget/recolor-art.cpp | 12 +++- src/ui/widget/recolor-art.h | 1 + 7 files changed, 120 insertions(+), 6 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 1941dcec77..5fbb69be2d 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -11,6 +11,7 @@ list-wheel-box top false + 200 original-recolor-colors-list-box diff --git a/src/3rdparty/2geom b/src/3rdparty/2geom index 53f0cc3042..5957e3234b 160000 --- a/src/3rdparty/2geom +++ b/src/3rdparty/2geom @@ -1 +1 @@ -Subproject commit 53f0cc304297294a0b7ada73c28e2da8d4aeba61 +Subproject commit 5957e3234b40da48d50bc5f90160541e129d5f08 diff --git a/src/3rdparty/libcroco b/src/3rdparty/libcroco index 0b5d1c68a3..ea3de62c70 160000 --- a/src/3rdparty/libcroco +++ b/src/3rdparty/libcroco @@ -1 +1 @@ -Subproject commit 0b5d1c68a3fd1452bd1671ed4fb493ee88fdaf13 +Subproject commit ea3de62c70310d5aa09aa7e5c5e0f7298290a573 diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index 431c069465..365907f3d3 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -25,6 +25,8 @@ #include #include +#include "desktop-style.h" +#include "desktop.h" #include "document.h" #include "inkscape.h" #include "object/sp-hatch.h" @@ -33,6 +35,12 @@ #include "object/sp-pattern.h" #include "object/sp-radial-gradient.h" #include "object/sp-stop.h" +#include "path-prefix.h" +#include "pattern-manipulation.h" +#include "selection.h" +#include "style.h" +#include "svg/css-ostringstream.h" +#include "ui/icon-loader.h" #include "ui/icon-names.h" #include "ui/pack.h" #include "ui/widget/color-notebook.h" @@ -114,7 +122,14 @@ GradientSelectorInterface *PaintSelector::getGradientFromData() const PaintSelector::PaintSelector(FillOrStroke kind, std::shared_ptr colors) : _selected_colors(std::move(colors)) + , _recolorArtWdgt_1(Gtk::make_managed()) + , _recolorArtWdgt_2(Gtk::make_managed()) + , _recolorButtonTriger_1(Gtk::make_managed()) + , _recolorButtonTriger_2(Gtk::make_managed()) + , _recolorPopOver_1(Gtk::make_managed()) + , _recolorPopOver_2(Gtk::make_managed()) { + set_orientation(Gtk::Orientation::VERTICAL); _mode = static_cast(-1); // huh? do you mean 0xff? -- I think this means "not in the enum" @@ -188,6 +203,29 @@ PaintSelector::PaintSelector(FillOrStroke kind, std::shared_ptrset_visible(kind == FILL); + + _desktop = SP_ACTIVE_DESKTOP; + if (_desktop) { + auto selection = _desktop->getSelection(); + if (selection) { + selection->connectChanged(sigc::mem_fun(*this, &PaintSelector::onSelectionChanged)); + } + } + + setupRecolorButton(_recolorButtonTriger_1,_recolorPopOver_1 , _recolorArtWdgt_1); + setupRecolorButton(_recolorButtonTriger_2,_recolorPopOver_2,_recolorArtWdgt_2); + + _recolorButtonTriger_1->signal_clicked().connect([this]() { + _recolorPopOver_1->popup(); + _recolorArtWdgt_1->performUpdate(); + }); + + _recolorButtonTriger_2->signal_clicked().connect([this]() { + _recolorPopOver_2->popup(); + _recolorArtWdgt_2->performUpdate(); + }); + _frame->append(*_recolorButtonTriger_1); + _recolorButtonTriger_1->hide(); } StyleToggleButton *PaintSelector::style_button_add(gchar const *pixmap, PaintSelector::Mode mode, gchar const *tip) @@ -276,6 +314,11 @@ void PaintSelector::set_mode_ex(Mode mode, bool switch_style) { } _mode = mode; _signal_mode_changed.emit(_mode, switch_style); + if (_desktop = SP_ACTIVE_DESKTOP) { + if (auto sel = _desktop->getSelection()) { + onSelectionChanged(sel); + } +} _update = false; } } @@ -506,6 +549,9 @@ void PaintSelector::set_mode_color() auto const color_selector = Gtk::make_managed(_selected_colors); color_selector->set_visible(true); UI::pack_start(*_selector_solid_color, *color_selector, true, true); + UI::pack_start(*_selector_solid_color, *_recolorButtonTriger_2, false, false); + _recolorButtonTriger_2->hide(); + /* Pack everything to frame */ _frame->append(*_selector_solid_color); color_selector->set_label(_("Flat color")); @@ -911,8 +957,10 @@ void PaintSelector::pattern_destroy(GtkWidget *widget, PaintSelector * /*psel*/) g_object_unref(G_OBJECT(widget)); } -void PaintSelector::pattern_change(GtkWidget * /*widget*/, PaintSelector *psel) { psel->_signal_changed.emit(); } - +void PaintSelector::pattern_change(GtkWidget * /*widget*/, PaintSelector *psel) +{ + psel->_signal_changed.emit(); +} /*update pattern list*/ void PaintSelector::updatePatternList(SPPattern *pattern) @@ -1131,6 +1179,50 @@ PaintSelector::Mode PaintSelector::getModeForStyle(SPStyle const &style, FillOrS return mode; } +void PaintSelector::onSelectionChanged(Inkscape::Selection *selection) +{ + if(selection->size()>1) + { + if (_mode == MODE_MULTIPLE) + { + _recolorButtonTriger_1->show(); + _recolorButtonTriger_2->hide(); + std::cout<<"shoed 1 hide 2\n"; + } + else if (_mode == MODE_SOLID_COLOR) + { + _recolorButtonTriger_2->show(); + _recolorButtonTriger_1->hide(); + std::cout<<"shoed 2 hide 1\n"; + } + else + { + _recolorButtonTriger_1->hide(); + _recolorButtonTriger_2->hide(); + std::cout<<"hide 1,2 selection size : "<size()<<" mode : "<<_mode<hide(); + _recolorButtonTriger_2->hide(); + std::cout<<"hide 1,2\n"; + } +} + +void PaintSelector::setupRecolorButton(Gtk::Button *recolorButtonTriger, Gtk::Popover *recolorPopOver , UI::Widget::RecolorArt *recolorArtWdgt) +{ + recolorButtonTriger->set_label("Recolor Selection"); + recolorButtonTriger->set_hexpand(false); + recolorButtonTriger->set_margin_bottom(200); + recolorButtonTriger->set_hexpand(false); + recolorButtonTriger->set_size_request(180); + recolorButtonTriger->set_halign(Gtk::Align::CENTER); + recolorPopOver->set_parent(*recolorButtonTriger); + recolorPopOver->set_child(*recolorArtWdgt); + recolorPopOver->set_position(Gtk::PositionType::LEFT); + recolorButtonTriger->set_margin_top(8); +} } // namespace Widget } // namespace UI diff --git a/src/ui/widget/paint-selector.h b/src/ui/widget/paint-selector.h index c126f04252..1299cd26b9 100644 --- a/src/ui/widget/paint-selector.h +++ b/src/ui/widget/paint-selector.h @@ -19,6 +19,7 @@ #include "fill-or-stroke.h" #include "ui/widget/gradient-selector.h" #include "ui/widget/swatch-selector.h" +#include "selection.h" class SPGradient; class SPLinearGradient; @@ -27,6 +28,7 @@ class SPRadialGradient; class SPMeshGradient; #endif class SPDesktop; +class Selection; class SPPattern; class SPStyle; @@ -93,6 +95,16 @@ class PaintSelector : public Gtk::Box { Gtk::Box *_selector_mesh = nullptr; SwatchSelector *_selector_swatch = nullptr; PatternEditor* _selector_pattern = nullptr; + + UI::Widget::RecolorArt *_recolorArtWdgt_1 = nullptr; + UI::Widget::RecolorArt *_recolorArtWdgt_2 = nullptr; + Gtk::Button *_recolorButtonTriger_1 = nullptr; + Gtk::Button *_recolorButtonTriger_2 = nullptr; + Gtk::Popover* _recolorPopOver_1=nullptr; + Gtk::Popover* _recolorPopOver_2=nullptr; + SPDesktop*_desktop=nullptr; + void onSelectionChanged(Inkscape::Selection *selection); + void setupRecolorButton(Gtk::Button *recolorButtonTriger , Gtk::Popover*recolorPopOver , UI::Widget::RecolorArt *recolorArtWdgt); Gtk::Label *_label; GtkWidget *_patternmenu = nullptr; diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index ac9788db23..6f81527ca4 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -475,6 +475,13 @@ void RecolorArt::onLivePreviewToggled() g_message(_is_preview ? "is true" : "is false"); g_message("LP toggled"); } +bool RecolorArt::selectionSize() +{ + if (_desktop && _desktop->getSelection()->size() > 1) { + return true; + } + return false; +} void RecolorArt::performUpdate() { for (auto child : _color_list->get_children()) { @@ -493,8 +500,9 @@ void RecolorArt::performUpdate() auto first_button_id = buttons.begin()->first; onOriginalColorClicked(first_button_id); } - } - g_message("Performing Update\n"); + g_message("Performing Update\n"); + } else + g_message("Desktop is NULL in Performupdate in recolor widegt\n"); } } // namespace Widget } // namespace UI diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 0c9e9eda6a..16f7557ca8 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -135,6 +135,7 @@ public: void performUpdate(); bool isInPreviewMode() { return _is_preview; } void setDesktop(SPDesktop *desktop); + bool selectionSize(); }; } // namespace Widget -- GitLab From fb4b1d70e917e9e5756131d67b6ad13228a4bd04 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sat, 5 Jul 2025 16:09:32 +0300 Subject: [PATCH 033/122] fixed crashing and building issues caused by git confilicts --- share/ui/recolor-art.glade | 1 + src/ui/widget/paint-selector.cpp | 2 ++ src/ui/widget/paint-selector.h | 3 +++ src/ui/widget/recolor-art.cpp | 2 ++ 4 files changed, 8 insertions(+) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 5fbb69be2d..540e02da65 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -12,6 +12,7 @@ top false 200 + 400 original-recolor-colors-list-box diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index 365907f3d3..053509f09a 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -46,6 +46,8 @@ #include "ui/widget/color-notebook.h" #include "ui/widget/gradient-editor.h" #include "ui/widget/pattern-editor.h" +#include "ui/widget/swatch-selector.h" +#include "ui/widget/recolor-art.h" #include "widgets/widget-sizes.h" #ifdef SP_PS_VERBOSE diff --git a/src/ui/widget/paint-selector.h b/src/ui/widget/paint-selector.h index 1299cd26b9..9d6fcb4372 100644 --- a/src/ui/widget/paint-selector.h +++ b/src/ui/widget/paint-selector.h @@ -35,6 +35,8 @@ class SPStyle; namespace Gtk { class Label; class ToggleButton; +class Button; +class Popover; } // namespace Gtk namespace Inkscape::UI::Widget { @@ -43,6 +45,7 @@ class FillRuleRadioButton; class GradientEditor; class PatternEditor; class StyleToggleButton; +class RecolorArt; /** * Generic paint selector widget. diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 6f81527ca4..b6d8ab1553 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -40,6 +40,7 @@ #include "selection.h" #include "style-internal.h" #include "style.h" +#include "inkscape.h" #include "ui/builder-utils.h" #include "ui/dialog/dialog-base.h" #include "ui/icon-names.h" @@ -491,6 +492,7 @@ void RecolorArt::performUpdate() _gradient_stops.clear(); _last_original_button = nullptr; _last_recolored_button = nullptr; + _desktop = SP_ACTIVE_DESKTOP; // _current_color_id = ""; if (auto selection = _desktop->getSelection()) { std::vector vec(selection->items().begin(), selection->items().end()); -- GitLab From d656e71c3d569540eff390934036df8de8d28df0 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sat, 5 Jul 2025 20:21:34 +0300 Subject: [PATCH 034/122] fix : removed popover from fill page --- src/ui/dialog/fill-and-stroke.cpp | 55 ++----------------------------- src/ui/dialog/fill-and-stroke.h | 7 ---- 2 files changed, 3 insertions(+), 59 deletions(-) diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index d06523d14d..d1eb81236a 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -40,15 +40,11 @@ FillAndStroke::FillAndStroke() , _page_fill(Gtk::make_managed(1, 1)) , _page_stroke_paint(Gtk::make_managed(1, 1)) , _page_stroke_style(Gtk::make_managed(1, 1)) - , _page_recolor_art(Gtk::make_managed(1, 1)) , _composite_settings(INKSCAPE_ICON("dialog-fill-and-stroke"), "fillstroke", UI::Widget::SimpleFilterModifier::ISOLATION | UI::Widget::SimpleFilterModifier::BLEND | UI::Widget::SimpleFilterModifier::BLUR | UI::Widget::SimpleFilterModifier::OPACITY) , fillWdgt(nullptr) , strokeWdgt(nullptr) - , recolorArtWdgt(nullptr) - , recolorButtonTriger(Gtk::make_managed()) - , recolorPopOver(Gtk::make_managed()) { set_spacing(2); UI::pack_start(*this, _notebook, true, true); @@ -57,8 +53,6 @@ FillAndStroke::FillAndStroke() _notebook.append_page(*_page_stroke_paint, _createPageTabLabel(_("Stroke _paint"), INKSCAPE_ICON("object-stroke"))); _notebook.append_page(*_page_stroke_style, _createPageTabLabel(_("Stroke st_yle"), INKSCAPE_ICON("object-stroke-style"))); - // _notebook.append_page(*_page_recolor_art, _createPageTabLabel(_("Recolor"), - // INKSCAPE_ICON("object-recolor-art"))); _notebook.set_vexpand(true); _switch_page_conn = _notebook.signal_switch_page().connect(sigc::mem_fun(*this, &FillAndStroke::_onSwitchPage)); @@ -66,15 +60,6 @@ FillAndStroke::FillAndStroke() _layoutPageFill(); _layoutPageStrokePaint(); _layoutPageStrokeStyle(); - _layoutPageRecolorArt(); - - recolorButtonTriger->set_label("Recolor Selection"); - recolorButtonTriger->signal_clicked().connect([this]() { - recolorPopOver->popup(); - recolorArtWdgt->performUpdate(); - }); - recolorPopOver->set_parent(*recolorButtonTriger); - recolorPopOver->set_child(*_page_recolor_art); UI::pack_end(*this, _composite_settings, UI::PackOptions::shrink); @@ -88,22 +73,16 @@ FillAndStroke::~FillAndStroke() fillWdgt->setDesktop(nullptr); strokeWdgt->setDesktop(nullptr); strokeStyleWdgt->setDesktop(nullptr); - recolorArtWdgt->setDesktop(nullptr); _subject.setDesktop(nullptr); } void FillAndStroke::selectionChanged(Selection *selection) { - if (selection->size() <= 1) - recolorButtonTriger->hide(); - else - recolorButtonTriger->show(); if (!page_changed) { changed_fill = true; changed_stroke = true; changed_stroke_style = true; - changed_recolor_art = true; } if (fillWdgt && npage == 0) { fillWdgt->performUpdate(); @@ -114,10 +93,7 @@ void FillAndStroke::selectionChanged(Selection *selection) if (strokeStyleWdgt && npage == 2) { strokeStyleWdgt->selectionChangedCB(); } - // if (recolorArtWdgt && npage == 3) { - // // if (!recolorArtWdgt->isInPreviewMode()) - // recolorArtWdgt->performUpdate(); - // } + } void FillAndStroke::selectionModified(Selection *selection, guint flags) @@ -125,7 +101,6 @@ void FillAndStroke::selectionModified(Selection *selection, guint flags) changed_fill = true; changed_stroke = true; changed_stroke_style = true; - changed_recolor_art = true; if (fillWdgt && npage == 0) { fillWdgt->selectionModifiedCB(flags); } @@ -135,11 +110,7 @@ void FillAndStroke::selectionModified(Selection *selection, guint flags) if (strokeStyleWdgt && npage == 2) { strokeStyleWdgt->selectionModifiedCB(flags); } - // if (recolorArtWdgt && npage == 3) { - // if (!recolorArtWdgt->isInPreviewMode()) { - // recolorArtWdgt->performUpdate(); - // } - // } + } void FillAndStroke::desktopReplaced() @@ -147,7 +118,6 @@ void FillAndStroke::desktopReplaced() changed_fill = true; changed_stroke = true; changed_stroke_style = true; - changed_recolor_art = true; if (fillWdgt) { fillWdgt->setDesktop(getDesktop()); } @@ -157,9 +127,6 @@ void FillAndStroke::desktopReplaced() if (strokeStyleWdgt) { strokeStyleWdgt->setDesktop(getDesktop()); } - if (recolorArtWdgt) { - recolorArtWdgt->setDesktop(getDesktop()); - } _subject.setDesktop(getDesktop()); } @@ -177,9 +144,6 @@ void FillAndStroke::_onSwitchPage(Gtk::Widget *page, guint pagenum) } else if (npage == 2 && changed_stroke_style) { update = true; changed_stroke_style = false; - } else if (npage == 3 && changed_recolor_art) { - update = true; - changed_recolor_art = false; } if (update) { page_changed = true; @@ -201,7 +165,6 @@ void FillAndStroke::_layoutPageFill() { fillWdgt = Gtk::make_managed(FILL); _page_fill->table().attach(*fillWdgt, 0, 0, 1, 1); - _page_fill->append(*recolorButtonTriger); } void FillAndStroke::_layoutPageStrokePaint() @@ -217,13 +180,6 @@ void FillAndStroke::_layoutPageStrokeStyle() strokeStyleWdgt->set_halign(Gtk::Align::START); _page_stroke_style->table().attach(*strokeStyleWdgt, 0, 0, 1, 1); } -void FillAndStroke::_layoutPageRecolorArt() -{ - recolorArtWdgt = Gtk::make_managed(); - recolorArtWdgt->set_hexpand(); - recolorArtWdgt->set_halign(Gtk::Align::FILL); - _page_recolor_art->table().attach(*recolorArtWdgt, 0, 0, 1, 1); -} void FillAndStroke::showPageFill() { @@ -246,12 +202,7 @@ void FillAndStroke::showPageStrokeStyle() _savePagePref(2); } -void FillAndStroke::showPageRecolorArt() -{ - blink(); - _notebook.set_current_page(3); - _savePagePref(3); -} + Gtk::Box &FillAndStroke::_createPageTabLabel(Glib::ustring const &label, char const *label_image) { diff --git a/src/ui/dialog/fill-and-stroke.h b/src/ui/dialog/fill-and-stroke.h index 85d9630ea4..d8ac27dfe5 100644 --- a/src/ui/dialog/fill-and-stroke.h +++ b/src/ui/dialog/fill-and-stroke.h @@ -57,7 +57,6 @@ protected: UI::Widget::NotebookPage *_page_fill = nullptr; UI::Widget::NotebookPage *_page_stroke_paint = nullptr; UI::Widget::NotebookPage *_page_stroke_style = nullptr; - UI::Widget::NotebookPage *_page_recolor_art = nullptr; UI::Widget::StyleSubject::Selection _subject; UI::Widget::ObjectCompositeSettings _composite_settings; @@ -68,7 +67,6 @@ protected: void _layoutPageFill(); void _layoutPageStrokePaint(); void _layoutPageStrokeStyle(); - void _layoutPageRecolorArt(); void _savePagePref(guint page_num); void _onSwitchPage(Gtk::Widget *page, guint pagenum); @@ -80,14 +78,9 @@ private: bool changed_fill = true; bool changed_stroke = true; bool changed_stroke_style = true; - bool changed_recolor_art = true; UI::Widget::FillNStroke *fillWdgt = nullptr; UI::Widget::FillNStroke *strokeWdgt = nullptr; UI::Widget::StrokeStyle *strokeStyleWdgt = nullptr; - UI::Widget::RecolorArt *recolorArtWdgt = nullptr; - Gtk::Button *recolorButtonTriger = nullptr; - Gtk::Popover* recolorPopOver=nullptr; - sigc::scoped_connection _switch_page_conn; }; -- GitLab From 80440aff84c43d1d87ac8a3102edac9e31382a22 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sat, 5 Jul 2025 20:59:01 +0300 Subject: [PATCH 035/122] fixed some margins --- src/ui/widget/color-notebook.cpp | 4 ++-- src/ui/widget/paint-selector.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ui/widget/color-notebook.cpp b/src/ui/widget/color-notebook.cpp index 39117b6506..ff6c53e5cb 100644 --- a/src/ui/widget/color-notebook.cpp +++ b/src/ui/widget/color-notebook.cpp @@ -126,7 +126,7 @@ void ColorNotebook::_initUI() _book->set_margin_start(2); _book->set_margin_end(2); _book->set_hexpand(); - _book->set_vexpand(); + _book->set_vexpand(false); attach(*_book, 0, row, 2, 1); // restore the last active page @@ -193,7 +193,7 @@ void ColorNotebook::_initUI() gtk_widget_set_margin_start(rgbabox, XPAD); gtk_widget_set_margin_end(rgbabox, XPAD); - gtk_widget_set_margin_top(rgbabox, YPAD); + gtk_widget_set_margin_top(rgbabox, 8); gtk_widget_set_margin_bottom(rgbabox, YPAD); attach(*Glib::wrap(rgbabox), 0, row, 2, 1); diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index 053509f09a..243768cf9a 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -1216,10 +1216,10 @@ void PaintSelector::setupRecolorButton(Gtk::Button *recolorButtonTriger, Gtk::Po { recolorButtonTriger->set_label("Recolor Selection"); recolorButtonTriger->set_hexpand(false); - recolorButtonTriger->set_margin_bottom(200); - recolorButtonTriger->set_hexpand(false); + recolorButtonTriger->set_vexpand(false); recolorButtonTriger->set_size_request(180); recolorButtonTriger->set_halign(Gtk::Align::CENTER); + recolorButtonTriger->set_valign(Gtk::Align::START); recolorPopOver->set_parent(*recolorButtonTriger); recolorPopOver->set_child(*recolorArtWdgt); recolorPopOver->set_position(Gtk::PositionType::LEFT); -- GitLab From 0408370e3aaddbb868799aad23b7d696fad15983 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 6 Jul 2025 09:42:46 +0300 Subject: [PATCH 036/122] fixed recolor button position --- src/ui/widget/paint-selector.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index 243768cf9a..6d0efca776 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -560,6 +560,7 @@ void PaintSelector::set_mode_color() } _selector_solid_color->set_visible(true); + _selector_solid_color->set_vexpand(false); } _label->set_markup(""); //_("Flat color")); -- GitLab From c17287af8be1800b4682d8f39ede2da47b68b327 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 6 Jul 2025 10:06:04 +0300 Subject: [PATCH 037/122] fixed opacity bug in populate map --- src/ui/widget/recolor-art.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index b6d8ab1553..2c75bdca43 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -248,10 +248,11 @@ void RecolorArt::populateStopsMap(SPStop *stop) } void RecolorArt::populateMap(Color color, SPItem *item, std::string kind) { + color.addOpacity(); ColorRef ref = ColorRef(item, kind); ColorPair pair = ColorPair(color, color); if (_selected_colors.count(color.toString())) { - _selected_colors[color.toString()].first.push_back(ref); + _selected_colors[color.toString(true)].first.push_back(ref); } else { _selected_colors.emplace(color.toString(), std::make_pair(std::vector{ref}, pair)); } -- GitLab From 57bb4823f887ec80634ce0cccc9c3ca0915d409f Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 6 Jul 2025 11:37:02 +0300 Subject: [PATCH 038/122] collected and chnaged patterns colors --- src/ui/widget/recolor-art.cpp | 36 +++++++++++++++++++++-------------- src/ui/widget/recolor-art.h | 15 ++++++++------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 2c75bdca43..a907b76458 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -68,7 +68,7 @@ RecolorArt::RecolorArt() _notebook = _builder->get_widget("list-wheel-box"); _color_wheel_page = _builder->get_widget("color-wheel-page"); - _notebook->signal_switch_page().connect([this](Gtk::Widget* page, guint page_num) { + _notebook->signal_switch_page().connect([this](Gtk::Widget *page, guint page_num) { int wheel_index = _notebook->page_num(*_color_wheel_page); if (static_cast(page_num) == wheel_index) { @@ -92,11 +92,9 @@ RecolorArt::RecolorArt() auto recolored = Gtk::make_managed(); original->set_hexpand(true); - recolored->set_hexpand(true); - arrow->set_use_markup(true); arrow->set_width_chars(6); arrow->set_markup("➔"); @@ -176,27 +174,27 @@ void RecolorArt::setDesktop(SPDesktop *desktop) } g_message("setDesktop\n"); } -void RecolorArt::collectColors(std::vector items) +void RecolorArt::collectColors(std::vector items) { _selected_colors.clear(); for (auto item : items) { extractItemColors(item); } } -void RecolorArt::extractItemColors(SPItem *item) +void RecolorArt::extractItemColors(SPObject *item) { if (item) { extractItemStyle(item); } if (auto group = dynamic_cast(item)) { for (SPObject &child : group->children) { - if (auto childItem = dynamic_cast(&child)) { + if (auto childItem = dynamic_cast(&child)) { extractItemColors(childItem); } } } } -void RecolorArt::extractGradientStops(SPItem *item, std::string kind, bool isFill) +void RecolorArt::extractGradientStops(SPObject *item, std::string kind, bool isFill) { SPPaintServer *paint_server = isFill ? item->style->getFillPaintServer() : item->style->getStrokePaintServer(); if (paint_server && dynamic_cast(paint_server)) { @@ -226,7 +224,7 @@ void RecolorArt::extractGradientStops(SPItem *item, std::string kind, bool isFil } } } -void RecolorArt::extractMeshStops(std::vector> mesh_nodes, SPItem *item, std::string kind) +void RecolorArt::extractMeshStops(std::vector> mesh_nodes, SPObject *item, std::string kind) { for (auto nodes : mesh_nodes) { for (auto node : nodes) { @@ -246,7 +244,7 @@ void RecolorArt::populateStopsMap(SPStop *stop) stop = stop->getNextStop(); } } -void RecolorArt::populateMap(Color color, SPItem *item, std::string kind) +void RecolorArt::populateMap(Color color, SPObject *item, std::string kind) { color.addOpacity(); ColorRef ref = ColorRef(item, kind); @@ -257,12 +255,11 @@ void RecolorArt::populateMap(Color color, SPItem *item, std::string kind) _selected_colors.emplace(color.toString(), std::make_pair(std::vector{ref}, pair)); } } -void RecolorArt::extractItemStyle(SPItem *item) +void RecolorArt::extractItemStyle(SPObject *item) { // check item style if (!item || !item->style) return; - SPStyle *style = item->style; // get flat fills if (style->fill.isColor()) { @@ -271,6 +268,11 @@ void RecolorArt::extractItemStyle(SPItem *item) } // get gradient stops strokes else if (style->fill.isPaintserver()) { + auto ps = style->getFillPaintServer(); + if (auto pattern = dynamic_cast(ps)) { + extractPatternColors(pattern); + std::cout << "pattern detected\n"; + } extractGradientStops(item, "stop", true); } @@ -283,6 +285,13 @@ void RecolorArt::extractItemStyle(SPItem *item) extractGradientStops(item, "stop", false); } } +void RecolorArt::extractPatternColors(SPPattern *pattern) +{ + SPPattern *root = pattern->rootPattern(); + for (auto &child : root->children) { + extractItemStyle(&child); + } +} void RecolorArt::generateVisualList() { _color_model->remove_all(); @@ -417,8 +426,7 @@ void RecolorArt::onResetClicked() colorButtons(btns.second, key); } - for(auto i =0; i<_color_model->get_n_items();i++) - { + for (auto i = 0; i < _color_model->get_n_items(); i++) { auto item = _color_model->get_item(i); auto color_item = std::dynamic_pointer_cast(item); color_item->new_color = color_item->key; @@ -496,7 +504,7 @@ void RecolorArt::performUpdate() _desktop = SP_ACTIVE_DESKTOP; // _current_color_id = ""; if (auto selection = _desktop->getSelection()) { - std::vector vec(selection->items().begin(), selection->items().end()); + std::vector vec(selection->items().begin(), selection->items().end()); collectColors(vec); if (!_selected_colors.empty()) { generateVisualList(); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 16f7557ca8..5906150ced 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -49,7 +49,7 @@ class ColorNotebook; struct ColorRef { - SPItem *item; + SPObject *item; std::string kind; }; @@ -105,12 +105,13 @@ private: // Gtk::Button *_apply = nullptr; Glib::RefPtr _builder; - void populateMap(Color color, SPItem *style, std::string kind); - void collectColors(std::vector items); - void extractGradientStops(SPItem *item, std::string kind, bool isFill); - void extractMeshStops(std::vector> mesh_nodes, SPItem *item, std::string kind); - void extractItemColors(SPItem *item); - void extractItemStyle(SPItem *item); + void populateMap(Color color, SPObject *style, std::string kind); + void collectColors(std::vector items); + void extractGradientStops(SPObject *item, std::string kind, bool isFill); + void extractMeshStops(std::vector> mesh_nodes, SPObject *item, std::string kind); + void extractItemColors(SPObject *item); + void extractItemStyle(SPObject *item); + void extractPatternColors(SPPattern*pattern); void generateVisualList(); void layoutColorPicker(std::shared_ptr updated_color = nullptr); void colorButtons(Gtk::Button *button, std::string color); -- GitLab From 681c4ff5e960eecaf304ec642406acfb2ca816b3 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 6 Jul 2025 17:54:58 +0300 Subject: [PATCH 039/122] showed recolor selection buttons for groups --- src/ui/widget/paint-selector.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index 6d0efca776..1445506700 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -1184,32 +1184,33 @@ PaintSelector::Mode PaintSelector::getModeForStyle(SPStyle const &style, FillOrS } void PaintSelector::onSelectionChanged(Inkscape::Selection *selection) { - if(selection->size()>1) + auto group = dynamic_cast(selection->single()); + if(selection->size()>1 || group) { - if (_mode == MODE_MULTIPLE) + if (_mode == MODE_MULTIPLE || _mode == MODE_UNSET) { _recolorButtonTriger_1->show(); _recolorButtonTriger_2->hide(); - std::cout<<"shoed 1 hide 2\n"; + // std::cout<<"shoed 1 hide 2\n"; } else if (_mode == MODE_SOLID_COLOR) { _recolorButtonTriger_2->show(); _recolorButtonTriger_1->hide(); - std::cout<<"shoed 2 hide 1\n"; + // std::cout<<"shoed 2 hide 1\n"; } else { _recolorButtonTriger_1->hide(); _recolorButtonTriger_2->hide(); - std::cout<<"hide 1,2 selection size : "<size()<<" mode : "<<_mode<size()<<" mode : "<<_mode<hide(); _recolorButtonTriger_2->hide(); - std::cout<<"hide 1,2\n"; + // std::cout<<"hide 1,2\n"; } } -- GitLab From 3398a5389600929ea833bf002b0f87a6214800b8 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 6 Jul 2025 18:21:37 +0300 Subject: [PATCH 040/122] fixed group coloring bug --- src/ui/widget/recolor-art.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index a907b76458..88d5911379 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -183,9 +183,6 @@ void RecolorArt::collectColors(std::vector items) } void RecolorArt::extractItemColors(SPObject *item) { - if (item) { - extractItemStyle(item); - } if (auto group = dynamic_cast(item)) { for (SPObject &child : group->children) { if (auto childItem = dynamic_cast(&child)) { @@ -193,6 +190,9 @@ void RecolorArt::extractItemColors(SPObject *item) } } } + else if (item) { + extractItemStyle(item); + } } void RecolorArt::extractGradientStops(SPObject *item, std::string kind, bool isFill) { -- GitLab From a48f930c99308b4612f215d066f464a1c6bb400e Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 6 Jul 2025 18:21:37 +0300 Subject: [PATCH 041/122] fixed row selection on reset clicked --- src/ui/widget/recolor-art.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 88d5911379..d69e77d60f 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -432,6 +432,7 @@ void RecolorArt::onResetClicked() color_item->new_color = color_item->key; } revertToOriginalColors(); + _selection_model->set_selected(0); onOriginalColorClicked(buttons.begin()->first); } void RecolorArt::revertToOriginalColors() -- GitLab From e9d068afc95e819d041aae0ea3d0e08e1c9bb7d9 Mon Sep 17 00:00:00 2001 From: ftomara Date: Mon, 7 Jul 2025 12:17:04 +0300 Subject: [PATCH 042/122] added color collection and changing for markers --- src/ui/widget/recolor-art.cpp | 29 ++++++++++++++++++++++++----- src/ui/widget/recolor-art.h | 1 + 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index d69e77d60f..08ba482c9d 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -29,6 +29,7 @@ #include "object/sp-defs.h" #include "object/sp-gradient.h" #include "object/sp-linear-gradient.h" +#include "object/sp-marker.h" #include "object/sp-mesh-gradient.h" #include "object/sp-object.h" #include "object/sp-pattern.h" @@ -185,12 +186,9 @@ void RecolorArt::extractItemColors(SPObject *item) { if (auto group = dynamic_cast(item)) { for (SPObject &child : group->children) { - if (auto childItem = dynamic_cast(&child)) { - extractItemColors(childItem); - } + extractItemColors(&child); } - } - else if (item) { + } else if (item) { extractItemStyle(item); } } @@ -261,6 +259,10 @@ void RecolorArt::extractItemStyle(SPObject *item) if (!item || !item->style) return; SPStyle *style = item->style; + extractMarkerColors(style->marker_start.get_value(), item); + extractMarkerColors(style->marker_mid.get_value(), item); + extractMarkerColors(style->marker_end.get_value(), item); + // get flat fills if (style->fill.isColor()) { auto color = style->fill.getColor(); @@ -292,6 +294,23 @@ void RecolorArt::extractPatternColors(SPPattern *pattern) extractItemStyle(&child); } } +void RecolorArt::extractMarkerColors(Glib::ustring marker, SPObject *item) +{ + // std::cout << "markerout : " << marker << std::endl; + if (marker.size() > 0 && item->document) { + // std::cout << "marker in : " << marker << std::endl; + std::string marker_id = std::string(marker.c_str() + 4, std::strlen(marker.c_str()) - 5); + // std::cout<<"marker id : "<document->getObjectByHref(marker_id); + if(!m) std::cout<<"m is null\n"; + if (auto marker_obj = dynamic_cast(m)) { + for (auto &child : marker_obj->item_list()) { + extractItemColors(&*child); + } + } + } else + return; +} void RecolorArt::generateVisualList() { _color_model->remove_all(); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 5906150ced..c04a3cb5b2 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -112,6 +112,7 @@ private: void extractItemColors(SPObject *item); void extractItemStyle(SPObject *item); void extractPatternColors(SPPattern*pattern); + void extractMarkerColors(Glib::ustring marker ,SPObject *item); void generateVisualList(); void layoutColorPicker(std::shared_ptr updated_color = nullptr); void colorButtons(Gtk::Button *button, std::string color); -- GitLab From 7c2df725d19af519c42737feda9b5cc6cbc6ca0d Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 8 Jul 2025 10:49:19 +0300 Subject: [PATCH 043/122] fixed color reseting bugs --- src/ui/widget/recolor-art.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 08ba482c9d..00eff2b841 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -412,7 +412,7 @@ void RecolorArt::onColorPickerChanged() auto item = _color_model->get_item(index); auto color_item = std::dynamic_pointer_cast(item); color_item->new_color = _color_string; - g_message("color picker changed"); + // g_message("color picker changed"); } void RecolorArt::lpChecked() { @@ -451,12 +451,16 @@ void RecolorArt::onResetClicked() color_item->new_color = color_item->key; } revertToOriginalColors(); - _selection_model->set_selected(0); - onOriginalColorClicked(buttons.begin()->first); + guint index = _selection_model->get_selected(); + auto item = _color_model->get_item(index); + auto color_item = std::dynamic_pointer_cast(item); + + onOriginalColorClicked(color_item->key); } void RecolorArt::revertToOriginalColors() { - for (auto [key, items] : _selected_colors) { + for (auto &[key, items] : _selected_colors) { + items.second.value().new_color = items.second.value().old_color; for (auto &item : items.first) { if (item.kind == "stop") continue; @@ -489,7 +493,7 @@ void RecolorArt::recolorStops(std::string old_color, Color new_color) { auto stops_vector = _gradient_stops.find(old_color); if (stops_vector != _gradient_stops.end()) { - for (auto stop : stops_vector->second) { + for (auto& stop : stops_vector->second) { stop->setColor(new_color); } } -- GitLab From 3ad8947c0030f859c3ca86bfe35c9b28f6aeae2a Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 8 Jul 2025 14:05:57 +0300 Subject: [PATCH 044/122] added selection colors highlighting and pattern detection for stroke --- src/ui/widget/recolor-art.cpp | 40 +++++++++++++++++++++++++++++++++++ src/ui/widget/recolor-art.h | 3 +++ 2 files changed, 43 insertions(+) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 00eff2b841..932ad74300 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -57,6 +57,7 @@ RecolorArt::RecolorArt() { set_name("RecolorArt"); append(get_widget(_builder, "recolor-art")); + signal_unmap().connect([&]() { resetOpacity(); }); _solid_colors->set(Color(0x000000ff)); layoutColorPicker(); @@ -284,6 +285,11 @@ void RecolorArt::extractItemStyle(SPObject *item) } // get gradient stops strokes else if (style->stroke.isPaintserver()) { + auto ps = style->getStrokePaintServer(); + if (auto pattern = dynamic_cast(ps)) { + extractPatternColors(pattern); + std::cout << "pattern detected\n"; + } extractGradientStops(item, "stop", false); } } @@ -374,6 +380,7 @@ void RecolorArt::colorButtons(Gtk::Button *button, std::string color) // } void RecolorArt::onOriginalColorClicked(std::string color_id) { + getSelection(color_id); _current_color_id = color_id; auto it = _selected_colors.find(color_id); auto btns = buttons.find(color_id); @@ -498,6 +505,39 @@ void RecolorArt::recolorStops(std::string old_color, Color new_color) } } } +void RecolorArt::getSelection(std::string color) +{ + for (auto &[key, value] : _selected_colors) { + for (auto &item : value.first) { + if (key != color) + item.item->style->opacity.set_double(0.50); + item.item->updateRepr(); + } + } + auto it = _selected_colors.find(color); + if (it == _selected_colors.end()) + return; + for (auto &item : it->second.first) { + item.item->style->opacity.set_double(1); + item.item->updateRepr(); + } + + if (_desktop && _desktop->getDocument()) { + _desktop->getDocument()->ensureUpToDate(); + } +} +void RecolorArt::resetOpacity() +{ + for (auto &[key, value] : _selected_colors) { + for (auto &item : value.first) { + item.item->style->opacity.set_double(1); + item.item->updateRepr(); + } + } + if (_desktop && _desktop->getDocument()) { + _desktop->getDocument()->ensureUpToDate(); + } +} void RecolorArt::onLivePreviewToggled() { _is_preview = _live_preview->property_active(); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index c04a3cb5b2..65e932b218 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -131,6 +131,9 @@ private: void populateStopsMap(SPStop *stop); void recolorStops(std::string old_color, Color new_color); + void getSelection(std::string color); + void resetOpacity(); + public: RecolorArt(); ~RecolorArt(); -- GitLab From e8aa3f84e96831fdc26802016d2c76ec326c82de Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 8 Jul 2025 15:28:17 +0300 Subject: [PATCH 045/122] added selection highlighting on hover --- src/ui/widget/recolor-art.cpp | 54 +++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 932ad74300..3081872c29 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,7 @@ #include "document-undo.h" #include "document.h" #include "gradient-chemistry.h" +#include "inkscape.h" #include "object/sp-defs.h" #include "object/sp-gradient.h" #include "object/sp-linear-gradient.h" @@ -41,7 +43,6 @@ #include "selection.h" #include "style-internal.h" #include "style.h" -#include "inkscape.h" #include "ui/builder-utils.h" #include "ui/dialog/dialog-base.h" #include "ui/icon-names.h" @@ -120,6 +121,10 @@ RecolorArt::RecolorArt() if (!box || box->get_first_child() == nullptr || box->get_last_child() == nullptr) return; + auto item_controller = Gtk::EventControllerMotion::create(); + item_controller->signal_enter().connect([box, item, this](double x, double y) { getSelection(item->key); }); + box->add_controller(item_controller); + auto original = dynamic_cast(box->get_first_child()); auto recolored = dynamic_cast(box->get_last_child()); @@ -138,6 +143,16 @@ RecolorArt::RecolorArt() _selection_model->set_selected(index); onOriginalColorClicked(item->key); }); + + auto original_controller = Gtk::EventControllerMotion::create(); + auto recolor_controller = Gtk::EventControllerMotion::create(); + original_controller->signal_enter().connect( + [original, item, this](double x, double y) { getSelection(item->key); }); + recolor_controller->signal_enter().connect( + [recolored, item, this](double x, double y) { getSelection(item->key); }); + + original->add_controller(original_controller); + recolored->add_controller(recolor_controller); buttons[item->key] = {original, recolored}; } }); @@ -187,7 +202,7 @@ void RecolorArt::extractItemColors(SPObject *item) { if (auto group = dynamic_cast(item)) { for (SPObject &child : group->children) { - extractItemColors(&child); + extractItemColors(&child); } } else if (item) { extractItemStyle(item); @@ -308,7 +323,8 @@ void RecolorArt::extractMarkerColors(Glib::ustring marker, SPObject *item) std::string marker_id = std::string(marker.c_str() + 4, std::strlen(marker.c_str()) - 5); // std::cout<<"marker id : "<document->getObjectByHref(marker_id); - if(!m) std::cout<<"m is null\n"; + if (!m) + std::cout << "m is null\n"; if (auto marker_obj = dynamic_cast(m)) { for (auto &child : marker_obj->item_list()) { extractItemColors(&*child); @@ -467,7 +483,7 @@ void RecolorArt::onResetClicked() void RecolorArt::revertToOriginalColors() { for (auto &[key, items] : _selected_colors) { - items.second.value().new_color = items.second.value().old_color; + items.second.value().new_color = items.second.value().old_color; for (auto &item : items.first) { if (item.kind == "stop") continue; @@ -500,7 +516,7 @@ void RecolorArt::recolorStops(std::string old_color, Color new_color) { auto stops_vector = _gradient_stops.find(old_color); if (stops_vector != _gradient_stops.end()) { - for (auto& stop : stops_vector->second) { + for (auto &stop : stops_vector->second) { stop->setColor(new_color); } } @@ -509,34 +525,34 @@ void RecolorArt::getSelection(std::string color) { for (auto &[key, value] : _selected_colors) { for (auto &item : value.first) { - if (key != color) - item.item->style->opacity.set_double(0.50); - item.item->updateRepr(); + if (key != color) { + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property_string(css, "opacity", "0.5"); + sp_desktop_apply_css_recursive(item.item, css, true); + sp_repr_css_attr_unref(css); + } } } auto it = _selected_colors.find(color); if (it == _selected_colors.end()) return; for (auto &item : it->second.first) { - item.item->style->opacity.set_double(1); - item.item->updateRepr(); - } - - if (_desktop && _desktop->getDocument()) { - _desktop->getDocument()->ensureUpToDate(); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property_string(css, "opacity", "1"); + sp_desktop_apply_css_recursive(item.item, css, true); + sp_repr_css_attr_unref(css); } } void RecolorArt::resetOpacity() { for (auto &[key, value] : _selected_colors) { for (auto &item : value.first) { - item.item->style->opacity.set_double(1); - item.item->updateRepr(); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property_string(css, "opacity", "1"); + sp_desktop_apply_css_recursive(item.item, css, true); + sp_repr_css_attr_unref(css); } } - if (_desktop && _desktop->getDocument()) { - _desktop->getDocument()->ensureUpToDate(); - } } void RecolorArt::onLivePreviewToggled() { -- GitLab From 869b3165555121252572f722d2ded23f2e6214dd Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 8 Jul 2025 18:58:11 +0300 Subject: [PATCH 046/122] updated onhover selection highlighting --- src/ui/widget/recolor-art.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 3081872c29..3bf82d8f63 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -46,6 +46,7 @@ #include "ui/builder-utils.h" #include "ui/dialog/dialog-base.h" #include "ui/icon-names.h" +#include "xml/repr.h" namespace Inkscape { namespace UI { @@ -123,6 +124,8 @@ RecolorArt::RecolorArt() auto item_controller = Gtk::EventControllerMotion::create(); item_controller->signal_enter().connect([box, item, this](double x, double y) { getSelection(item->key); }); + item_controller->signal_leave().connect([box, this]() { resetOpacity(); }); + box->add_controller(item_controller); auto original = dynamic_cast(box->get_first_child()); @@ -148,8 +151,10 @@ RecolorArt::RecolorArt() auto recolor_controller = Gtk::EventControllerMotion::create(); original_controller->signal_enter().connect( [original, item, this](double x, double y) { getSelection(item->key); }); + original_controller->signal_leave().connect([original, this]() { resetOpacity(); }); recolor_controller->signal_enter().connect( [recolored, item, this](double x, double y) { getSelection(item->key); }); + recolor_controller->signal_leave().connect([recolored, this]() { resetOpacity(); }); original->add_controller(original_controller); recolored->add_controller(recolor_controller); @@ -524,34 +529,32 @@ void RecolorArt::recolorStops(std::string old_color, Color new_color) void RecolorArt::getSelection(std::string color) { for (auto &[key, value] : _selected_colors) { + Color new_color = value.second.value().new_color; + new_color.setOpacity(0.15); for (auto &item : value.first) { if (key != color) { SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, "opacity", "0.5"); + sp_repr_css_set_property_string(css, item.kind.c_str(), new_color.toString()); sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } } - } - auto it = _selected_colors.find(color); - if (it == _selected_colors.end()) - return; - for (auto &item : it->second.first) { - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, "opacity", "1"); - sp_desktop_apply_css_recursive(item.item, css, true); - sp_repr_css_attr_unref(css); + if (key != color) { + recolorStops(key, new_color); + } } } void RecolorArt::resetOpacity() { for (auto &[key, value] : _selected_colors) { + std::string new_color = value.second.value().new_color.toString(); for (auto &item : value.first) { SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, "opacity", "1"); + sp_repr_css_set_property_string(css, item.kind.c_str(), new_color); sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } + recolorStops(key, value.second.value().new_color); } } void RecolorArt::onLivePreviewToggled() -- GitLab From 97c9cb301d88c22f04824d592a88b13ee073d1a2 Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 10 Jul 2025 10:42:42 +0300 Subject: [PATCH 047/122] waiting for hover on first row selected --- src/ui/widget/recolor-art.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 3bf82d8f63..983d88d1e0 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -200,6 +200,12 @@ void RecolorArt::collectColors(std::vector items) { _selected_colors.clear(); for (auto item : items) { + std::cout << "item: " << *item << std::endl; + std::cout << "parent: "; + if (item->parent == nullptr) + std::cout << "nullptr\n"; + else + std::cout<<*item->parent << std::endl; extractItemColors(item); } } @@ -401,7 +407,6 @@ void RecolorArt::colorButtons(Gtk::Button *button, std::string color) // } void RecolorArt::onOriginalColorClicked(std::string color_id) { - getSelection(color_id); _current_color_id = color_id; auto it = _selected_colors.find(color_id); auto btns = buttons.find(color_id); -- GitLab From e64e6c41625ff737c4f5b6717fe49be18a0b386f Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 10 Jul 2025 11:20:59 +0300 Subject: [PATCH 048/122] added the recolor selection button to mesh mode in paint selector --- src/ui/widget/paint-selector.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index 1445506700..7cc504146f 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -874,6 +874,7 @@ void PaintSelector::set_mode_mesh(PaintSelector::Mode mode) UI::pack_start(*_selector_mesh, *hb2, false, false, AUX_BETWEEN_BUTTON_GROUPS); _frame->append(*_selector_mesh); + _frame->reorder_child_after(*_recolorButtonTriger_1,*_selector_mesh); } _selector_mesh->set_visible(true); @@ -1185,9 +1186,9 @@ PaintSelector::Mode PaintSelector::getModeForStyle(SPStyle const &style, FillOrS void PaintSelector::onSelectionChanged(Inkscape::Selection *selection) { auto group = dynamic_cast(selection->single()); - if(selection->size()>1 || group) + if(selection->size()>1 || group || _mode == MODE_GRADIENT_MESH) { - if (_mode == MODE_MULTIPLE || _mode == MODE_UNSET) + if (_mode == MODE_MULTIPLE || _mode == MODE_UNSET || _mode == MODE_GRADIENT_MESH) { _recolorButtonTriger_1->show(); _recolorButtonTriger_2->hide(); -- GitLab From 584173191b9e18783c55bb4daf534936c9d62863 Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 10 Jul 2025 11:23:22 +0300 Subject: [PATCH 049/122] updated opacity to be 0.05 --- src/ui/widget/recolor-art.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 983d88d1e0..2f073489e7 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -535,7 +535,7 @@ void RecolorArt::getSelection(std::string color) { for (auto &[key, value] : _selected_colors) { Color new_color = value.second.value().new_color; - new_color.setOpacity(0.15); + new_color.setOpacity(0.05); for (auto &item : value.first) { if (key != color) { SPCSSAttr *css = sp_repr_css_attr_new(); -- GitLab From e341faebce0eb95b3a4bd1850ede03aaba21c58a Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 10 Jul 2025 12:30:31 +0300 Subject: [PATCH 050/122] fixed lp convert to recolored colors probelm --- src/ui/widget/recolor-art.cpp | 7 ++++--- src/ui/widget/recolor-art.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 2f073489e7..d1b818b5dc 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -483,17 +483,18 @@ void RecolorArt::onResetClicked() auto color_item = std::dynamic_pointer_cast(item); color_item->new_color = color_item->key; } - revertToOriginalColors(); + revertToOriginalColors(true); guint index = _selection_model->get_selected(); auto item = _color_model->get_item(index); auto color_item = std::dynamic_pointer_cast(item); onOriginalColorClicked(color_item->key); } -void RecolorArt::revertToOriginalColors() +void RecolorArt::revertToOriginalColors(bool is_reset_clicked) { for (auto &[key, items] : _selected_colors) { - items.second.value().new_color = items.second.value().old_color; + if(is_reset_clicked) + items.second.value().new_color = items.second.value().old_color; for (auto &item : items.first) { if (item.kind == "stop") continue; diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 65e932b218..b21cff177a 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -124,7 +124,7 @@ private: void onColorPickerChanged(); void onLivePreviewToggled(); void lpChecked(); - void revertToOriginalColors(); + void revertToOriginalColors(bool is_reset_clicked=false); void convertToRecoloredColors(); // void _onApplyButtonClicked(); -- GitLab From 446238d18a569b0c3add24a2925485fa687c71c4 Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 10 Jul 2025 22:50:08 +0300 Subject: [PATCH 051/122] added license --- src/ui/widget/recolor-art.cpp | 1 + src/ui/widget/recolor-art.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index d1b818b5dc..2484c78ee8 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later #include "recolor-art.h" #include diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index b21cff177a..caab8b57a9 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -1,4 +1,4 @@ - +// SPDX-License-Identifier: GPL-2.0-or-later #ifndef SEEN_DIALOGS_SP_RECOLOR_ART_H #define SEEN_DIALOGS_SP_RECOLOR_ART_H -- GitLab From 0bb63d8221d2e7f827e25d636448fc9c02e3a326 Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 15 Jul 2025 12:20:47 +0300 Subject: [PATCH 052/122] added clones --- src/ui/widget/paint-selector.cpp | 12 ++++++++++++ src/ui/widget/paint-selector.h | 2 ++ src/ui/widget/recolor-art.cpp | 10 ++++++++++ src/ui/widget/recolor-art.h | 2 ++ 4 files changed, 26 insertions(+) diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index 7cc504146f..4102b3271a 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -1185,6 +1185,11 @@ PaintSelector::Mode PaintSelector::getModeForStyle(SPStyle const &style, FillOrS } void PaintSelector::onSelectionChanged(Inkscape::Selection *selection) { + + if (_change_sel) { + std::cout << "return\n"; + return; + } auto group = dynamic_cast(selection->single()); if(selection->size()>1 || group || _mode == MODE_GRADIENT_MESH) { @@ -1217,6 +1222,7 @@ void PaintSelector::onSelectionChanged(Inkscape::Selection *selection) void PaintSelector::setupRecolorButton(Gtk::Button *recolorButtonTriger, Gtk::Popover *recolorPopOver , UI::Widget::RecolorArt *recolorArtWdgt) { + recolorArtWdgt->setPaintSelector(this); recolorButtonTriger->set_label("Recolor Selection"); recolorButtonTriger->set_hexpand(false); recolorButtonTriger->set_vexpand(false); @@ -1229,6 +1235,12 @@ void PaintSelector::setupRecolorButton(Gtk::Button *recolorButtonTriger, Gtk::Po recolorButtonTriger->set_margin_top(8); } +void PaintSelector::set_change_selection(bool value) +{ + _change_sel = value; +} + + } // namespace Widget } // namespace UI } // namespace Inkscape diff --git a/src/ui/widget/paint-selector.h b/src/ui/widget/paint-selector.h index 9d6fcb4372..f508e7ecf0 100644 --- a/src/ui/widget/paint-selector.h +++ b/src/ui/widget/paint-selector.h @@ -105,6 +105,7 @@ class PaintSelector : public Gtk::Box { Gtk::Button *_recolorButtonTriger_2 = nullptr; Gtk::Popover* _recolorPopOver_1=nullptr; Gtk::Popover* _recolorPopOver_2=nullptr; + bool _change_sel=false; SPDesktop*_desktop=nullptr; void onSelectionChanged(Inkscape::Selection *selection); void setupRecolorButton(Gtk::Button *recolorButtonTriger , Gtk::Popover*recolorPopOver , UI::Widget::RecolorArt *recolorArtWdgt); @@ -207,6 +208,7 @@ class PaintSelector : public Gtk::Box { Geom::Scale get_pattern_gap(); Glib::ustring get_pattern_label(); bool is_pattern_scale_uniform(); + void set_change_selection(bool value); }; enum { diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 2484c78ee8..3428dace1b 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -582,6 +582,11 @@ bool RecolorArt::selectionSize() } return false; } +void RecolorArt::setPaintSelector(PaintSelector *ps) +{ + _paint_selector = ps; +} + void RecolorArt::performUpdate() { for (auto child : _color_list->get_children()) { @@ -594,6 +599,11 @@ void RecolorArt::performUpdate() _desktop = SP_ACTIVE_DESKTOP; // _current_color_id = ""; if (auto selection = _desktop->getSelection()) { + if (_paint_selector) + _paint_selector->set_change_selection(true); + selection->unlinkRecursive(false, true, false); + if (_paint_selector) + _paint_selector->set_change_selection(false); std::vector vec(selection->items().begin(), selection->items().end()); collectColors(vec); if (!_selected_colors.empty()) { diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index caab8b57a9..3c875b4af7 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -101,6 +101,7 @@ private: Gtk::Notebook *_notebook = nullptr; Gtk::Box *_color_wheel_page = nullptr; + PaintSelector* _paint_selector = nullptr; // Gtk::Button *_apply = nullptr; @@ -141,6 +142,7 @@ public: bool isInPreviewMode() { return _is_preview; } void setDesktop(SPDesktop *desktop); bool selectionSize(); + void setPaintSelector(PaintSelector* ps); }; } // namespace Widget -- GitLab From 347d737a43bea4d7d5d128d71a6e45c552fd9c34 Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 15 Jul 2025 22:41:26 +0300 Subject: [PATCH 053/122] added indicator for amount of used objects per color & indicator - of objects/ fills indicates & color buttons that shows color opacity --- share/ui/style.css | 15 ++- src/ui/widget/color-preview.cpp | 7 +- src/ui/widget/color-preview.h | 1 + src/ui/widget/recolor-art.cpp | 213 ++++++++++++++++++++++---------- src/ui/widget/recolor-art.h | 29 +++-- 5 files changed, 182 insertions(+), 83 deletions(-) diff --git a/share/ui/style.css b/share/ui/style.css index f46b4f24ea..652f19d1c1 100644 --- a/share/ui/style.css +++ b/share/ui/style.css @@ -1683,16 +1683,21 @@ button.reduced-padding { #recolor-art #original, #recolored { - min-height: 6px; + min-height: 12px; border-radius: 4px; - border: 2px solid transparent; + /* border: 2px solid transparent; */ } -#original-recolor-box button#original:hover, -button#recolored:hover { +/* #original-recolor-box #original:hover, +#recolored:hover { border-color: @theme_fq_color; +} */ +.type_box { + background-color: #c1c1c1b7; + border-radius: 2px; + padding-left: 2px; + padding-right: 6px; } - #recolor-art listview row:selected { background-color: transparent; border: 2px solid @theme_selected_bg_color; diff --git a/src/ui/widget/color-preview.cpp b/src/ui/widget/color-preview.cpp index 4854cbbad6..1eae4a0500 100644 --- a/src/ui/widget/color-preview.cpp +++ b/src/ui/widget/color-preview.cpp @@ -50,7 +50,12 @@ void ColorPreview::setRgba32(std::uint32_t const rgba) { queue_draw(); } -void ColorPreview::setPattern(Cairo::RefPtr pattern) { +std::uint32_t ColorPreview::getRgba32() +{ + return _rgba; +} +void ColorPreview::setPattern(Cairo::RefPtr pattern) +{ if (_pattern == pattern) return; _pattern = pattern; diff --git a/src/ui/widget/color-preview.h b/src/ui/widget/color-preview.h index b8016aeca1..88b561ca06 100644 --- a/src/ui/widget/color-preview.h +++ b/src/ui/widget/color-preview.h @@ -47,6 +47,7 @@ public: ColorPreview(BaseObjectType* cobject, const Glib::RefPtr& builder); // set preview color RGBA with opacity (alpha) void setRgba32(std::uint32_t rgba); + std::uint32_t getRgba32(); // set arbitrary pattern-based preview void setPattern(Cairo::RefPtr pattern); // simple color patch vs outlined color patch diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 3428dace1b..5e0026cc80 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -7,12 +7,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include @@ -47,6 +49,7 @@ #include "ui/builder-utils.h" #include "ui/dialog/dialog-base.h" #include "ui/icon-names.h" +#include "ui/widget/color-preview.h" #include "xml/repr.h" namespace Inkscape { @@ -92,9 +95,25 @@ RecolorArt::RecolorArt() _color_factory->signal_setup().connect([](Glib::RefPtr const &list_item) { auto box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); - auto original = Gtk::make_managed(); + auto original = Gtk::make_managed(); auto arrow = Gtk::make_managed(); - auto recolored = Gtk::make_managed(); + auto recolored = Gtk::make_managed(); + + auto original_preview = Gtk::make_managed(Color(0x00000000).toRGBA()); + auto recolored_preview = Gtk::make_managed(Color(0x00000000).toRGBA()); + + original_preview->set_hexpand(true); + recolored_preview->set_hexpand(true); + + original_preview->set_vexpand(true); + recolored_preview->set_vexpand(true); + + auto original_overlay = Gtk::make_managed(); + + original_overlay->set_child(*original_preview); + + original->append(*original_overlay); + recolored->append(*recolored_preview); original->set_hexpand(true); @@ -129,24 +148,50 @@ RecolorArt::RecolorArt() box->add_controller(item_controller); - auto original = dynamic_cast(box->get_first_child()); - auto recolored = dynamic_cast(box->get_last_child()); + auto original = dynamic_cast(box->get_first_child()); + auto recolored = dynamic_cast(box->get_last_child()); if (original && recolored) { - colorButtons(original, item->old_color); - colorButtons(recolored, item->new_color); + auto original_overlay = dynamic_cast(original->get_first_child()); + auto type_box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); + if (original_overlay) { + original_overlay->add_overlay(*type_box); + _type_boxes[item->key] = type_box; + } + + colorButtons(original, item->old_color.value(), true); + colorButtons(recolored, item->new_color.value()); original->set_name("original"); recolored->set_name("recolored"); - original->signal_clicked().connect([this, item, index = list_item->get_position()] { - _selection_model->set_selected(index); - onOriginalColorClicked(item->key); - }); - recolored->signal_clicked().connect([this, item, index = list_item->get_position()] { - _selection_model->set_selected(index); - onOriginalColorClicked(item->key); - }); + auto original_click = Gtk::GestureClick::create(); + auto recolored_click = Gtk::GestureClick::create(); + + original_click->signal_pressed().connect( + [this, item, index = list_item->get_position()](gint n_press, gdouble x, gdouble y) { + _selection_model->set_selected(index); + onOriginalColorClicked(item->key); + }); + + recolored_click->signal_pressed().connect( + [this, item, index = list_item->get_position()](gint n_press, gdouble x, gdouble y) { + _selection_model->set_selected(index); + onOriginalColorClicked(item->key); + }); + + original->add_controller(original_click); + recolored->add_controller(recolored_click); + + // original->signal_clicked().connect([this, item, index = list_item->get_position()] { + // _selection_model->set_selected(index); + // onOriginalColorClicked(item->key); + // }); + + // recolored->signal_clicked().connect([this, item, index = list_item->get_position()] { + // _selection_model->set_selected(index); + // onOriginalColorClicked(item->key); + // }); auto original_controller = Gtk::EventControllerMotion::create(); auto recolor_controller = Gtk::EventControllerMotion::create(); @@ -206,7 +251,7 @@ void RecolorArt::collectColors(std::vector items) if (item->parent == nullptr) std::cout << "nullptr\n"; else - std::cout<<*item->parent << std::endl; + std::cout << *item->parent << std::endl; extractItemColors(item); } } @@ -220,7 +265,7 @@ void RecolorArt::extractItemColors(SPObject *item) extractItemStyle(item); } } -void RecolorArt::extractGradientStops(SPObject *item, std::string kind, bool isFill) +void RecolorArt::extractGradientStops(SPObject *item, bool isFill) { SPPaintServer *paint_server = isFill ? item->style->getFillPaintServer() : item->style->getStrokePaintServer(); if (paint_server && dynamic_cast(paint_server)) { @@ -232,17 +277,19 @@ void RecolorArt::extractGradientStops(SPObject *item, std::string kind, bool isF std::unique_ptr nodeArray; if (auto mesh = dynamic_cast(gradient)) { nodeArray = std::make_unique(mesh); - extractMeshStops(nodeArray->nodes, item, kind); + extractMeshStops(nodeArray->nodes, item, "mesh"); } } else { vectorGradient->ensureVector(); - // int stopCount = vectorGradient->getStopCount(); - // std::cout << "Stops count : " << stopCount << std::endl; - // std::cout << "has patches : " << vectorGradient->hasPatches() << std::endl; populateStopsMap(vectorGradient->getFirstStop()); } } + std::string kind = ""; + if (is(vectorGradient)) + kind = "linear"; + else if (is(vectorGradient)) + kind = "ridal"; for (auto stop : vectorGradient->getGradientVector().stops) { if (stop.color.has_value()) { populateMap(stop.color.value(), item, kind); @@ -303,7 +350,7 @@ void RecolorArt::extractItemStyle(SPObject *item) extractPatternColors(pattern); std::cout << "pattern detected\n"; } - extractGradientStops(item, "stop", true); + extractGradientStops(item, true); } if (style->stroke.isColor()) { @@ -317,7 +364,7 @@ void RecolorArt::extractItemStyle(SPObject *item) extractPatternColors(pattern); std::cout << "pattern detected\n"; } - extractGradientStops(item, "stop", false); + extractGradientStops(item, false); } } void RecolorArt::extractPatternColors(SPPattern *pattern) @@ -350,8 +397,8 @@ void RecolorArt::generateVisualList() _color_model->remove_all(); buttons.clear(); for (auto &[key, value] : _selected_colors) { - auto old_color = value.second.value().old_color.toString(); - auto new_color = value.second.value().new_color.toString(); + auto old_color = value.second.value().old_color; + auto new_color = value.second.value().new_color; _color_model->append(ColorItem::create(key, old_color, new_color)); } _color_list->append(*_list_view); @@ -374,38 +421,81 @@ void RecolorArt::layoutColorPicker(std::shared_ptr updated_col g_warning("color picker not found"); } } -void RecolorArt::colorButtons(Gtk::Button *button, std::string color) +void RecolorArt::colorButtons(Gtk::Box *button, Color color, bool is_original) { - if (color.empty() || color.size() < 7 || color[0] != '#') { - g_warning("Invalid color string: %s", color.c_str()); - return; + if (button) { + auto child = + is_original + ? dynamic_cast(dynamic_cast(button->get_first_child())->get_child()) + : dynamic_cast(button->get_first_child()); + if (child) { + auto rgba = color.toRGBA(); + child->setRgba32(rgba); + } + if (is_original) { + auto typebox = _type_boxes[color.toString()]; + setUpTypeBox(typebox, color); + } } + // if (color.empty() || color.size() < 7 || color[0] != '#') { + // g_warning("Invalid color string: %s", color.c_str()); + // return; + // } + + // if (button) { + // auto css_provider = Gtk::CssProvider::create(); + // Glib::ustring css = "box { background-color: " + Glib::ustring(color) + "; background-image: none;}"; + // css_provider->load_from_data(css); + // auto style_context = button->get_style_context(); + // style_context->add_provider(css_provider, GTK_STYLE_PROVIDER_PRIORITY_USER); + // } else { + // g_message("button not found"); + // } +} +void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) +{ + box->set_spacing(2); + box->set_margin_start(4); + box->set_hexpand(false); + box->set_vexpand(false); + box->set_halign(Gtk::Align::START); + box->set_valign(Gtk::Align::CENTER); + box->get_style_context()->add_class("type_box"); + std::string color_string = color.toString(); + auto it = _selected_colors.find(color_string); + if (it != _selected_colors.end()) { + std::string size = "" + std::to_string(it->second.first.size()) + ""; + Gtk::Label *label = Gtk::make_managed(); + label->set_use_markup(true); + label->set_markup(size); + box->append(*label); + std::set kinds; + for (auto item : it->second.first) { + if (item.kind == "fill") { + kinds.insert(INKSCAPE_ICON("object-fill")); + } else if (item.kind == "stroke") { + kinds.insert(INKSCAPE_ICON("object-stroke")); + } else if (item.kind == "mesh") { + kinds.insert(INKSCAPE_ICON("paint-gradient-mesh")); + } else if (item.kind == "linear") { + kinds.insert(INKSCAPE_ICON("paint-gradient-linear")); + } else if (item.kind == "ridal") { + kinds.insert(INKSCAPE_ICON("paint-gradient-radial")); + } + } - if (button) { - auto css_provider = Gtk::CssProvider::create(); - Glib::ustring css = "button { background-color: " + Glib::ustring(color) + "; background-image: none;}"; - css_provider->load_from_data(css); - auto style_context = button->get_style_context(); - style_context->add_provider(css_provider, GTK_STYLE_PROVIDER_PRIORITY_USER); - } else { - g_message("button not found"); + for (auto icon : kinds) { + Gtk::Image *img = nullptr; + img = Gtk::make_managed(); + img->set_from_icon_name(icon); + + if (img) { + img->set_pixel_size(8); + box->append(*img); + } + } } } -// void RecolorArt::colorBorderOnClick(Gtk::Button *button, bool kind) -// { -// auto &_last_button = kind == 1 ? _last_original_button : _last_recolored_button; -// if (_last_button && _last_button != button) { -// auto style_context = _last_button->get_style_context(); -// style_context->remove_class("selected-button"); -// } -// if (button) { -// auto style_context = button->get_style_context(); -// style_context->add_class("selected-button"); -// _last_button = button; -// } else { -// g_warning("button not found for border coloring"); -// } -// } void RecolorArt::onOriginalColorClicked(std::string color_id) { _current_color_id = color_id; @@ -416,9 +506,6 @@ void RecolorArt::onOriginalColorClicked(std::string color_id) std::shared_ptr updated_color = std::make_shared(); updated_color->set(color); layoutColorPicker(updated_color); - // colorBorderOnClick(btns->second.first, 1); - // colorBorderOnClick(btns->second.second, 0); - // g_message("original color selected at color %s", color_id.c_str()); } } void RecolorArt::onColorPickerChanged() @@ -428,14 +515,14 @@ void RecolorArt::onColorPickerChanged() g_message("couldn't find the color id \" %s \" ", _current_color_id.c_str()); return; } - Gtk::Button *_current_recolor_button = it->second.second; + Gtk::Box *_current_recolor_button = it->second.second; std::optional new_color = _solid_colors->get(); if (!new_color.has_value()) { g_message("there is no color"); return; } std::string _color_string = new_color.value().toString(); - colorButtons(_current_recolor_button, _color_string); + colorButtons(_current_recolor_button, new_color.value()); auto _selected = _selected_colors.find(_current_color_id); if (_selected != _selected_colors.end()) _selected->second.second.value().new_color = new_color.value(); @@ -445,7 +532,7 @@ void RecolorArt::onColorPickerChanged() guint index = _selection_model->get_selected(); auto item = _color_model->get_item(index); auto color_item = std::dynamic_pointer_cast(item); - color_item->new_color = _color_string; + color_item->new_color = new_color.value(); // g_message("color picker changed"); } void RecolorArt::lpChecked() @@ -476,13 +563,17 @@ void RecolorArt::lpChecked() void RecolorArt::onResetClicked() { for (auto [key, btns] : buttons) { - colorButtons(btns.second, key); + std::uint32_t rgba = + dynamic_cast(dynamic_cast(btns.first->get_first_child())->get_child()) + ->getRgba32(); + Color color(rgba); + colorButtons(btns.second, color); } for (auto i = 0; i < _color_model->get_n_items(); i++) { auto item = _color_model->get_item(i); auto color_item = std::dynamic_pointer_cast(item); - color_item->new_color = color_item->key; + color_item->new_color = color_item->old_color; } revertToOriginalColors(true); guint index = _selection_model->get_selected(); @@ -494,7 +585,7 @@ void RecolorArt::onResetClicked() void RecolorArt::revertToOriginalColors(bool is_reset_clicked) { for (auto &[key, items] : _selected_colors) { - if(is_reset_clicked) + if (is_reset_clicked) items.second.value().new_color = items.second.value().old_color; for (auto &item : items.first) { if (item.kind == "stop") @@ -594,8 +685,6 @@ void RecolorArt::performUpdate() } buttons.clear(); _gradient_stops.clear(); - _last_original_button = nullptr; - _last_recolored_button = nullptr; _desktop = SP_ACTIVE_DESKTOP; // _current_color_id = ""; if (auto selection = _desktop->getSelection()) { diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 3c875b4af7..3fe309061b 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -62,11 +62,10 @@ struct ColorPair struct ColorItem : public Glib::Object { Glib::ustring key; - Glib::ustring old_color; - Glib::ustring new_color; + std::optional old_color; + std::optional new_color; - static Glib::RefPtr create(Glib::ustring const &k, Glib::ustring const &old_c, - Glib::ustring const &new_c) + static Glib::RefPtr create(Glib::ustring const &k, Color const &old_c, Color const &new_c) { auto item = Glib::make_refptr_for_instance(new ColorItem()); item->key = k; @@ -87,36 +86,34 @@ private: Gtk::Button *_reset = nullptr; Gtk::CheckButton *_live_preview = nullptr; std::string _current_color_id; - std::map> buttons; // color_id : {original , recolored} + std::map> buttons; // color_id : {original , recolored} + std::map _type_boxes; bool _is_preview = false; Glib::RefPtr> _color_model; Glib::RefPtr _color_factory; Glib::RefPtr _selection_model; - Gtk::Button *_last_original_button = nullptr; - Gtk::Button *_last_recolored_button = nullptr; - std::map> _gradient_stops; Gtk::Notebook *_notebook = nullptr; Gtk::Box *_color_wheel_page = nullptr; - PaintSelector* _paint_selector = nullptr; + PaintSelector *_paint_selector = nullptr; // Gtk::Button *_apply = nullptr; Glib::RefPtr _builder; void populateMap(Color color, SPObject *style, std::string kind); void collectColors(std::vector items); - void extractGradientStops(SPObject *item, std::string kind, bool isFill); + void extractGradientStops(SPObject *item, bool isFill); void extractMeshStops(std::vector> mesh_nodes, SPObject *item, std::string kind); void extractItemColors(SPObject *item); void extractItemStyle(SPObject *item); - void extractPatternColors(SPPattern*pattern); - void extractMarkerColors(Glib::ustring marker ,SPObject *item); + void extractPatternColors(SPPattern *pattern); + void extractMarkerColors(Glib::ustring marker, SPObject *item); void generateVisualList(); void layoutColorPicker(std::shared_ptr updated_color = nullptr); - void colorButtons(Gtk::Button *button, std::string color); + void colorButtons(Gtk::Box *button, Color color, bool is_original = false); // void colorBorderOnClick(Gtk::Button *button, bool kind); // signals handelrs @@ -125,7 +122,7 @@ private: void onColorPickerChanged(); void onLivePreviewToggled(); void lpChecked(); - void revertToOriginalColors(bool is_reset_clicked=false); + void revertToOriginalColors(bool is_reset_clicked = false); void convertToRecoloredColors(); // void _onApplyButtonClicked(); @@ -135,6 +132,8 @@ private: void getSelection(std::string color); void resetOpacity(); + void setUpTypeBox(Gtk::Box *box, Color color); + public: RecolorArt(); ~RecolorArt(); @@ -142,7 +141,7 @@ public: bool isInPreviewMode() { return _is_preview; } void setDesktop(SPDesktop *desktop); bool selectionSize(); - void setPaintSelector(PaintSelector* ps); + void setPaintSelector(PaintSelector *ps); }; } // namespace Widget -- GitLab From 53fc720a0a19ef660e7f117fc53407f1280dc9da Mon Sep 17 00:00:00 2001 From: ftomara Date: Wed, 16 Jul 2025 13:04:06 +0300 Subject: [PATCH 054/122] fixed recolor button on group of clones --- share/ui/style.css | 2 +- src/ui/widget/paint-selector.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/share/ui/style.css b/share/ui/style.css index 652f19d1c1..f37b11c129 100644 --- a/share/ui/style.css +++ b/share/ui/style.css @@ -1693,7 +1693,7 @@ button.reduced-padding { border-color: @theme_fq_color; } */ .type_box { - background-color: #c1c1c1b7; + background-color: alpha(@theme_bg_color,0.8); border-radius: 2px; padding-left: 2px; padding-right: 6px; diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index 4102b3271a..542f9bc186 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -33,6 +33,7 @@ #include "object/sp-linear-gradient.h" #include "object/sp-mesh-gradient.h" #include "object/sp-pattern.h" +#include "object/sp-use.h" #include "object/sp-radial-gradient.h" #include "object/sp-stop.h" #include "path-prefix.h" @@ -1191,7 +1192,8 @@ void PaintSelector::onSelectionChanged(Inkscape::Selection *selection) return; } auto group = dynamic_cast(selection->single()); - if(selection->size()>1 || group || _mode == MODE_GRADIENT_MESH) + auto use_group = dynamic_cast(selection->single()); + if(selection->size()>1 || group ||use_group|| _mode == MODE_GRADIENT_MESH) { if (_mode == MODE_MULTIPLE || _mode == MODE_UNSET || _mode == MODE_GRADIENT_MESH) { -- GitLab From f30f302cf880e624859a6277a315ecc282c95aac Mon Sep 17 00:00:00 2001 From: ftomara Date: Wed, 16 Jul 2025 15:56:47 +0300 Subject: [PATCH 055/122] added masks color collection and changings --- src/ui/widget/paint-selector.cpp | 8 +++++++- src/ui/widget/recolor-art.cpp | 16 ++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index 542f9bc186..b76a501959 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -34,6 +34,7 @@ #include "object/sp-mesh-gradient.h" #include "object/sp-pattern.h" #include "object/sp-use.h" +#include "object/sp-mask.h" #include "object/sp-radial-gradient.h" #include "object/sp-stop.h" #include "path-prefix.h" @@ -1193,7 +1194,12 @@ void PaintSelector::onSelectionChanged(Inkscape::Selection *selection) } auto group = dynamic_cast(selection->single()); auto use_group = dynamic_cast(selection->single()); - if(selection->size()>1 || group ||use_group|| _mode == MODE_GRADIENT_MESH) + auto item = dynamic_cast(selection->single()); + SPMask* mask = nullptr; + if(item) + mask = dynamic_cast(item->getMaskObject()); + + if(selection->size()>1 || group ||use_group||mask|| _mode == MODE_GRADIENT_MESH) { if (_mode == MODE_MULTIPLE || _mode == MODE_UNSET || _mode == MODE_GRADIENT_MESH) { diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 5e0026cc80..2526a873a7 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -35,6 +35,7 @@ #include "object/sp-gradient.h" #include "object/sp-linear-gradient.h" #include "object/sp-marker.h" +#include "object/sp-mask.h" #include "object/sp-mesh-gradient.h" #include "object/sp-object.h" #include "object/sp-pattern.h" @@ -246,12 +247,15 @@ void RecolorArt::collectColors(std::vector items) { _selected_colors.clear(); for (auto item : items) { - std::cout << "item: " << *item << std::endl; - std::cout << "parent: "; - if (item->parent == nullptr) - std::cout << "nullptr\n"; - else - std::cout << *item->parent << std::endl; + auto it = dynamic_cast(item); + auto mask = dynamic_cast(it->getMaskObject()); + if (mask) { + std::vector children_vec; + for (auto &child : mask->children) { + children_vec.push_back(&child); + } + collectColors(children_vec); + } extractItemColors(item); } } -- GitLab From da57cf4c584a40587dbb7f5bf5803e6430deb858 Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 17 Jul 2025 11:37:15 +0300 Subject: [PATCH 056/122] fixed masks and objects color collection bug --- share/ui/recolor-art.glade | 1 - src/ui/widget/recolor-art.cpp | 16 +++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 540e02da65..c4a6ece18a 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -61,7 +61,6 @@ true true true - centre never false diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 2526a873a7..98d392d46a 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -245,16 +245,17 @@ void RecolorArt::setDesktop(SPDesktop *desktop) } void RecolorArt::collectColors(std::vector items) { - _selected_colors.clear(); for (auto item : items) { auto it = dynamic_cast(item); - auto mask = dynamic_cast(it->getMaskObject()); - if (mask) { - std::vector children_vec; - for (auto &child : mask->children) { - children_vec.push_back(&child); + if (it) { + auto mask = dynamic_cast(it->getMaskObject()); + if (mask) { + std::vector children_vec; + for (auto &child : mask->children) { + children_vec.push_back(&child); + } + collectColors(children_vec); } - collectColors(children_vec); } extractItemColors(item); } @@ -689,6 +690,7 @@ void RecolorArt::performUpdate() } buttons.clear(); _gradient_stops.clear(); + _selected_colors.clear(); _desktop = SP_ACTIVE_DESKTOP; // _current_color_id = ""; if (auto selection = _desktop->getSelection()) { -- GitLab From 6b5ffd446c814369983d271620b489f3cf42483b Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 17 Jul 2025 12:07:50 +0300 Subject: [PATCH 057/122] added arrow icon instead of label --- share/icons/Dash/symbolic/actions/go-right-symbolic.svg | 1 + .../icons/hicolor/symbolic/actions/go-right-symbolic.svg | 1 + .../multicolor/symbolic/actions/go-right-symbolic.svg | 1 + src/ui/widget/recolor-art.cpp | 8 ++++---- 4 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 share/icons/Dash/symbolic/actions/go-right-symbolic.svg create mode 100644 share/icons/hicolor/symbolic/actions/go-right-symbolic.svg create mode 100644 share/icons/multicolor/symbolic/actions/go-right-symbolic.svg diff --git a/share/icons/Dash/symbolic/actions/go-right-symbolic.svg b/share/icons/Dash/symbolic/actions/go-right-symbolic.svg new file mode 100644 index 0000000000..5d08323d90 --- /dev/null +++ b/share/icons/Dash/symbolic/actions/go-right-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/share/icons/hicolor/symbolic/actions/go-right-symbolic.svg b/share/icons/hicolor/symbolic/actions/go-right-symbolic.svg new file mode 100644 index 0000000000..5d08323d90 --- /dev/null +++ b/share/icons/hicolor/symbolic/actions/go-right-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/share/icons/multicolor/symbolic/actions/go-right-symbolic.svg b/share/icons/multicolor/symbolic/actions/go-right-symbolic.svg new file mode 100644 index 0000000000..5d08323d90 --- /dev/null +++ b/share/icons/multicolor/symbolic/actions/go-right-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 98d392d46a..1b39204da5 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -97,7 +97,7 @@ RecolorArt::RecolorArt() _color_factory->signal_setup().connect([](Glib::RefPtr const &list_item) { auto box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); auto original = Gtk::make_managed(); - auto arrow = Gtk::make_managed(); + auto arrow = Gtk::make_managed(); auto recolored = Gtk::make_managed(); auto original_preview = Gtk::make_managed(Color(0x00000000).toRGBA()); @@ -120,12 +120,12 @@ RecolorArt::RecolorArt() recolored->set_hexpand(true); - arrow->set_use_markup(true); - arrow->set_width_chars(6); - arrow->set_markup("➔"); + arrow->set_from_icon_name(INKSCAPE_ICON("go-right")); arrow->set_halign(Gtk::Align::CENTER); arrow->set_valign(Gtk::Align::CENTER); arrow->set_margin_top(3); + arrow->set_margin_start(6); + arrow->set_margin_end(6); box->set_name("original-recolor-box"); box->append(*original); -- GitLab From aebf08357bd019996a1786ac3c4cf1a639b7a293 Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 17 Jul 2025 12:22:55 +0300 Subject: [PATCH 058/122] chnaged typed box implementation to be lazy loaded ? --- src/ui/widget/recolor-art.cpp | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 1b39204da5..3c34c029c3 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -103,6 +103,15 @@ RecolorArt::RecolorArt() auto original_preview = Gtk::make_managed(Color(0x00000000).toRGBA()); auto recolored_preview = Gtk::make_managed(Color(0x00000000).toRGBA()); + auto type_box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); + type_box->set_spacing(2); + type_box->set_margin_start(4); + type_box->set_hexpand(false); + type_box->set_vexpand(false); + type_box->set_halign(Gtk::Align::START); + type_box->set_valign(Gtk::Align::CENTER); + type_box->get_style_context()->add_class("type_box"); + original_preview->set_hexpand(true); recolored_preview->set_hexpand(true); @@ -112,6 +121,7 @@ RecolorArt::RecolorArt() auto original_overlay = Gtk::make_managed(); original_overlay->set_child(*original_preview); + original_overlay->add_overlay(*type_box); original->append(*original_overlay); recolored->append(*recolored_preview); @@ -131,6 +141,7 @@ RecolorArt::RecolorArt() box->append(*original); box->append(*arrow); box->append(*recolored); + list_item->set_data("typebox", type_box); list_item->set_child(*box); }); @@ -153,15 +164,9 @@ RecolorArt::RecolorArt() auto recolored = dynamic_cast(box->get_last_child()); if (original && recolored) { - auto original_overlay = dynamic_cast(original->get_first_child()); - auto type_box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); - if (original_overlay) { - original_overlay->add_overlay(*type_box); - _type_boxes[item->key] = type_box; - } - colorButtons(original, item->old_color.value(), true); colorButtons(recolored, item->new_color.value()); + setUpTypeBox(static_cast(list_item->get_data("typebox")), item->old_color.value()); original->set_name("original"); recolored->set_name("recolored"); @@ -437,10 +442,6 @@ void RecolorArt::colorButtons(Gtk::Box *button, Color color, bool is_original) auto rgba = color.toRGBA(); child->setRgba32(rgba); } - if (is_original) { - auto typebox = _type_boxes[color.toString()]; - setUpTypeBox(typebox, color); - } } // if (color.empty() || color.size() < 7 || color[0] != '#') { // g_warning("Invalid color string: %s", color.c_str()); @@ -459,13 +460,6 @@ void RecolorArt::colorButtons(Gtk::Box *button, Color color, bool is_original) } void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) { - box->set_spacing(2); - box->set_margin_start(4); - box->set_hexpand(false); - box->set_vexpand(false); - box->set_halign(Gtk::Align::START); - box->set_valign(Gtk::Align::CENTER); - box->get_style_context()->add_class("type_box"); std::string color_string = color.toString(); auto it = _selected_colors.find(color_string); if (it != _selected_colors.end()) { -- GitLab From a8333a14bfdb1f66708139799836da885399e16f Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 17 Jul 2025 14:06:31 +0300 Subject: [PATCH 059/122] added pattern,masks,markers to type box --- src/ui/widget/recolor-art.cpp | 79 +++++++++++++++++++++++++++-------- src/ui/widget/recolor-art.h | 6 +-- 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 3c34c029c3..5ed5d2a9d6 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -248,7 +248,7 @@ void RecolorArt::setDesktop(SPDesktop *desktop) } g_message("setDesktop\n"); } -void RecolorArt::collectColors(std::vector items) +void RecolorArt::collectColors(std::vector items, std::string kind) { for (auto item : items) { auto it = dynamic_cast(item); @@ -259,20 +259,20 @@ void RecolorArt::collectColors(std::vector items) for (auto &child : mask->children) { children_vec.push_back(&child); } - collectColors(children_vec); + collectColors(children_vec, "mask"); } } - extractItemColors(item); + extractItemColors(item, kind); } } -void RecolorArt::extractItemColors(SPObject *item) +void RecolorArt::extractItemColors(SPObject *item, std::string kind) { if (auto group = dynamic_cast(item)) { for (SPObject &child : group->children) { - extractItemColors(&child); + extractItemColors(&child, kind); } } else if (item) { - extractItemStyle(item); + extractItemStyle(item, kind); } } void RecolorArt::extractGradientStops(SPObject *item, bool isFill) @@ -338,7 +338,7 @@ void RecolorArt::populateMap(Color color, SPObject *item, std::string kind) _selected_colors.emplace(color.toString(), std::make_pair(std::vector{ref}, pair)); } } -void RecolorArt::extractItemStyle(SPObject *item) +void RecolorArt::extractItemStyle(SPObject *item, std::string kind) { // check item style if (!item || !item->style) @@ -351,7 +351,7 @@ void RecolorArt::extractItemStyle(SPObject *item) // get flat fills if (style->fill.isColor()) { auto color = style->fill.getColor(); - populateMap(color, item, "fill"); + populateMap(color, item, (kind == "" ? "fill" : kind + "-fill")); } // get gradient stops strokes else if (style->fill.isPaintserver()) { @@ -365,14 +365,13 @@ void RecolorArt::extractItemStyle(SPObject *item) if (style->stroke.isColor()) { auto color = style->stroke.getColor(); - populateMap(color, item, "stroke"); + populateMap(color, item, (kind == "" ? "stroke" : kind + "-stroke")); } // get gradient stops strokes else if (style->stroke.isPaintserver()) { auto ps = style->getStrokePaintServer(); if (auto pattern = dynamic_cast(ps)) { extractPatternColors(pattern); - std::cout << "pattern detected\n"; } extractGradientStops(item, false); } @@ -381,7 +380,7 @@ void RecolorArt::extractPatternColors(SPPattern *pattern) { SPPattern *root = pattern->rootPattern(); for (auto &child : root->children) { - extractItemStyle(&child); + extractItemStyle(&child, "pattern"); } } void RecolorArt::extractMarkerColors(Glib::ustring marker, SPObject *item) @@ -396,7 +395,7 @@ void RecolorArt::extractMarkerColors(Glib::ustring marker, SPObject *item) std::cout << "m is null\n"; if (auto marker_obj = dynamic_cast(m)) { for (auto &child : marker_obj->item_list()) { - extractItemColors(&*child); + extractItemColors(&*child, "marker"); } } } else @@ -460,6 +459,9 @@ void RecolorArt::colorButtons(Gtk::Box *button, Color color, bool is_original) } void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) { + if (!box->get_children().empty()) + return; + std::string color_string = color.toString(); auto it = _selected_colors.find(color_string); if (it != _selected_colors.end()) { @@ -480,6 +482,12 @@ void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) kinds.insert(INKSCAPE_ICON("paint-gradient-linear")); } else if (item.kind == "ridal") { kinds.insert(INKSCAPE_ICON("paint-gradient-radial")); + } else if (item.kind.find("pattern") != std::string::npos) { + kinds.insert(INKSCAPE_ICON("paint-pattern")); + } else if (item.kind.find("marker") != std::string::npos) { + kinds.insert(INKSCAPE_ICON("markers")); + } else if (item.kind.find("mask") != std::string::npos) { + kinds.insert(INKSCAPE_ICON("overlay-mask")); } } @@ -489,7 +497,12 @@ void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) img->set_from_icon_name(icon); if (img) { - img->set_pixel_size(8); + if (icon == INKSCAPE_ICON("overlay-mask")) { + img->set_pixel_size(16); + img->set_halign(Gtk::Align::CENTER); + img->set_valign(Gtk::Align::CENTER); + } else + img->set_pixel_size(8); box->append(*img); } } @@ -551,8 +564,14 @@ void RecolorArt::lpChecked() for (auto &item : _selected->second.first) { if (item.kind == "stop") continue; + std::string k = (item.kind.find("fill") != std::string::npos) + ? "fill" + : (item.kind.find("stroke") != std::string::npos ? "stroke" : ""); + if (k == "") + continue; + SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, item.kind.c_str(), _color_string); + sp_repr_css_set_property_string(css, k.c_str(), _color_string); sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } @@ -589,8 +608,13 @@ void RecolorArt::revertToOriginalColors(bool is_reset_clicked) for (auto &item : items.first) { if (item.kind == "stop") continue; + std::string k = (item.kind.find("fill") != std::string::npos) + ? "fill" + : (item.kind.find("stroke") != std::string::npos ? "stroke" : ""); + if (k == "") + continue; SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, item.kind.c_str(), key); + sp_repr_css_set_property_string(css, k.c_str(), key); sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } @@ -605,8 +629,13 @@ void RecolorArt::convertToRecoloredColors() for (auto &item : items.first) { if (item.kind == "stop") continue; + std::string k = (item.kind.find("fill") != std::string::npos) + ? "fill" + : (item.kind.find("stroke") != std::string::npos ? "stroke" : ""); + if (k == "") + continue; SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, item.kind.c_str(), new_color); + sp_repr_css_set_property_string(css, k.c_str(), new_color); sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } @@ -630,8 +659,15 @@ void RecolorArt::getSelection(std::string color) new_color.setOpacity(0.05); for (auto &item : value.first) { if (key != color) { + if (item.kind == "stop") + continue; + std::string k = (item.kind.find("fill") != std::string::npos) + ? "fill" + : (item.kind.find("stroke") != std::string::npos ? "stroke" : ""); + if (k == "") + continue; SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, item.kind.c_str(), new_color.toString()); + sp_repr_css_set_property_string(css, k.c_str(), new_color.toString()); sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } @@ -646,8 +682,15 @@ void RecolorArt::resetOpacity() for (auto &[key, value] : _selected_colors) { std::string new_color = value.second.value().new_color.toString(); for (auto &item : value.first) { + if (item.kind == "stop") + continue; + std::string k = (item.kind.find("fill") != std::string::npos) + ? "fill" + : (item.kind.find("stroke") != std::string::npos ? "stroke" : ""); + if (k == "") + continue; SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, item.kind.c_str(), new_color); + sp_repr_css_set_property_string(css, k.c_str(), new_color); sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 3fe309061b..069bec6c22 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -104,11 +104,11 @@ private: Glib::RefPtr _builder; void populateMap(Color color, SPObject *style, std::string kind); - void collectColors(std::vector items); + void collectColors(std::vector items,std::string kind=""); void extractGradientStops(SPObject *item, bool isFill); void extractMeshStops(std::vector> mesh_nodes, SPObject *item, std::string kind); - void extractItemColors(SPObject *item); - void extractItemStyle(SPObject *item); + void extractItemColors(SPObject *item,std::string kind=""); + void extractItemStyle(SPObject *item ,std::string kind=""); void extractPatternColors(SPPattern *pattern); void extractMarkerColors(Glib::ustring marker, SPObject *item); void generateVisualList(); -- GitLab From 8af265e3630690b3309001adf5c0630d616818f4 Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 17 Jul 2025 14:14:22 +0300 Subject: [PATCH 060/122] solved hovering from original to button issue --- src/ui/widget/recolor-art.cpp | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 5ed5d2a9d6..5f3b563bee 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -188,28 +188,6 @@ RecolorArt::RecolorArt() original->add_controller(original_click); recolored->add_controller(recolored_click); - - // original->signal_clicked().connect([this, item, index = list_item->get_position()] { - // _selection_model->set_selected(index); - // onOriginalColorClicked(item->key); - // }); - - // recolored->signal_clicked().connect([this, item, index = list_item->get_position()] { - // _selection_model->set_selected(index); - // onOriginalColorClicked(item->key); - // }); - - auto original_controller = Gtk::EventControllerMotion::create(); - auto recolor_controller = Gtk::EventControllerMotion::create(); - original_controller->signal_enter().connect( - [original, item, this](double x, double y) { getSelection(item->key); }); - original_controller->signal_leave().connect([original, this]() { resetOpacity(); }); - recolor_controller->signal_enter().connect( - [recolored, item, this](double x, double y) { getSelection(item->key); }); - recolor_controller->signal_leave().connect([recolored, this]() { resetOpacity(); }); - - original->add_controller(original_controller); - recolored->add_controller(recolor_controller); buttons[item->key] = {original, recolored}; } }); -- GitLab From 61d9b62ff13a4f58c39871068365ae016cfab8d1 Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 17 Jul 2025 17:10:35 +0300 Subject: [PATCH 061/122] resized the recolor widget --- share/ui/recolor-art.glade | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index c4a6ece18a..2ba044b92c 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -11,8 +11,7 @@ list-wheel-box top false - 200 - 400 + 250 original-recolor-colors-list-box -- GitLab From cf9699ecc30a7d257beeb8f03879f749b44411ac Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 17 Jul 2025 18:30:47 +0300 Subject: [PATCH 062/122] used flow box for original,reset,recolor box --- share/ui/recolor-art.glade | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 2ba044b92c..938809a7a8 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -19,12 +19,9 @@ true true - + original-reset-recolor - horizontal - center - center - 85 + 3 Original -- GitLab From 95ac37295469d9822128c8439f0fe639f0efc73c Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 17 Jul 2025 20:27:50 +0300 Subject: [PATCH 063/122] fixed gradient linking issue --- src/ui/widget/recolor-art.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 5f3b563bee..e5a5e47cf0 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -258,6 +258,8 @@ void RecolorArt::extractGradientStops(SPObject *item, bool isFill) SPPaintServer *paint_server = isFill ? item->style->getFillPaintServer() : item->style->getStrokePaintServer(); if (paint_server && dynamic_cast(paint_server)) { SPGradient *gradient = dynamic_cast(paint_server); + if (!gradient) + return; SPGradient *vectorGradient = gradient->getVector(); if (vectorGradient) { if (vectorGradient->hasPatches()) { @@ -269,16 +271,19 @@ void RecolorArt::extractGradientStops(SPObject *item, bool isFill) } } else { - vectorGradient->ensureVector(); - populateStopsMap(vectorGradient->getFirstStop()); + gradient = sp_gradient_get_forked_vector_if_necessary(gradient, true); + if (!gradient) + return; + gradient->ensureVector(); + populateStopsMap(gradient->getFirstStop()); } } std::string kind = ""; - if (is(vectorGradient)) + if (is(gradient)) kind = "linear"; - else if (is(vectorGradient)) + else if (is(gradient)) kind = "ridal"; - for (auto stop : vectorGradient->getGradientVector().stops) { + for (auto stop : gradient->getGradientVector().stops) { if (stop.color.has_value()) { populateMap(stop.color.value(), item, kind); } -- GitLab From 3f1e18966647a486d2ea0950b2d83efa5ac1cc45 Mon Sep 17 00:00:00 2001 From: ftomara Date: Fri, 18 Jul 2025 09:10:32 +0300 Subject: [PATCH 064/122] added recolor button to gradient editor in paint selector --- src/ui/widget/gradient-editor.h | 2 + src/ui/widget/paint-selector.cpp | 74 +++++++++++++++++++------------- src/ui/widget/paint-selector.h | 3 ++ 3 files changed, 50 insertions(+), 29 deletions(-) diff --git a/src/ui/widget/gradient-editor.h b/src/ui/widget/gradient-editor.h index dd4a0c7648..f5da2cbad0 100644 --- a/src/ui/widget/gradient-editor.h +++ b/src/ui/widget/gradient-editor.h @@ -73,6 +73,8 @@ public: ColorPickerPanel::PlateType get_color_picker_plate() const; SPGradientType get_type() const; ColorPickerPanel& get_picker() { return *_color_picker; } + Gtk::Box& getColorBox(){return _colors_box ; }; + private: void set_gradient(SPGradient* gradient); diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index b76a501959..2f60b91b74 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -128,10 +128,13 @@ PaintSelector::PaintSelector(FillOrStroke kind, std::shared_ptr()) , _recolorArtWdgt_2(Gtk::make_managed()) + , _recolorArtWdgt_3(Gtk::make_managed()) , _recolorButtonTriger_1(Gtk::make_managed()) , _recolorButtonTriger_2(Gtk::make_managed()) + , _recolorButtonTriger_3(Gtk::make_managed()) , _recolorPopOver_1(Gtk::make_managed()) , _recolorPopOver_2(Gtk::make_managed()) + , _recolorPopOver_3(Gtk::make_managed()) { set_orientation(Gtk::Orientation::VERTICAL); @@ -216,8 +219,9 @@ PaintSelector::PaintSelector(FillOrStroke kind, std::shared_ptrsignal_clicked().connect([this]() { _recolorPopOver_1->popup(); @@ -228,6 +232,12 @@ PaintSelector::PaintSelector(FillOrStroke kind, std::shared_ptrpopup(); _recolorArtWdgt_2->performUpdate(); }); + + _recolorButtonTriger_3->signal_clicked().connect([this]() { + _recolorPopOver_3->popup(); + _recolorArtWdgt_3->performUpdate(); + }); + _frame->append(*_recolorButtonTriger_1); _recolorButtonTriger_1->hide(); } @@ -267,7 +277,9 @@ void PaintSelector::fillrule_toggled(FillRuleRadioButton *tb) } } -void PaintSelector::setMode(Mode mode) { +void PaintSelector::setMode(Mode mode) +{ + if(_recolorPopOver_1->get_visible()||_recolorPopOver_2->get_visible()||_recolorPopOver_3->get_visible()) return; set_mode_ex(mode, false); } @@ -607,6 +619,8 @@ void PaintSelector::set_mode_gradient(PaintSelector::Mode mode) _selector_gradient->signal_changed().connect(sigc::mem_fun(*this, &PaintSelector::gradient_changed)); _selector_gradient->signal_stop_selected().connect([this](SPStop* stop) { _signal_stop_selected.emit(stop); }); /* Pack everything to frame */ + _selector_gradient->getColorBox().append(*_recolorButtonTriger_3); + _recolorButtonTriger_3->hide(); _frame->append(*_selector_gradient); } catch (std::exception& ex) { @@ -1192,38 +1206,40 @@ void PaintSelector::onSelectionChanged(Inkscape::Selection *selection) std::cout << "return\n"; return; } - auto group = dynamic_cast(selection->single()); - auto use_group = dynamic_cast(selection->single()); - auto item = dynamic_cast(selection->single()); - SPMask* mask = nullptr; - if(item) - mask = dynamic_cast(item->getMaskObject()); - - if(selection->size()>1 || group ||use_group||mask|| _mode == MODE_GRADIENT_MESH) - { - if (_mode == MODE_MULTIPLE || _mode == MODE_UNSET || _mode == MODE_GRADIENT_MESH) - { - _recolorButtonTriger_1->show(); - _recolorButtonTriger_2->hide(); - // std::cout<<"shoed 1 hide 2\n"; - } - else if (_mode == MODE_SOLID_COLOR) - { - _recolorButtonTriger_2->show(); - _recolorButtonTriger_1->hide(); - // std::cout<<"shoed 2 hide 1\n"; - } - else - { - _recolorButtonTriger_1->hide(); - _recolorButtonTriger_2->hide(); - // std::cout<<"hide 1,2 selection size : "<size()<<" mode : "<<_mode<(selection->single()); + auto use_group = dynamic_cast(selection->single()); + auto item = dynamic_cast(selection->single()); + SPMask *mask = nullptr; + if (item) + mask = dynamic_cast(item->getMaskObject()); + if (selection->size() > 1 || group || use_group || mask || _mode == MODE_GRADIENT_MESH) { + if (_mode == MODE_MULTIPLE || _mode == MODE_UNSET || _mode == MODE_GRADIENT_MESH) { + _recolorButtonTriger_1->show(); + _recolorButtonTriger_2->hide(); + _recolorButtonTriger_3->hide(); + // std::cout<<"shoed 1 hide 2\n"; + } else if (_mode == MODE_SOLID_COLOR) { + _recolorButtonTriger_2->show(); + _recolorButtonTriger_1->hide(); + _recolorButtonTriger_3->hide(); + // std::cout<<"shoed 2 hide 1\n"; + } else if (_mode == MODE_GRADIENT_RADIAL || _mode == MODE_GRADIENT_LINEAR) { + _recolorButtonTriger_1->hide(); + _recolorButtonTriger_2->hide(); + _recolorButtonTriger_3->show(); + // std::cout<<"hide 1,2 selection size : "<size()<<" mode : "<<_mode<hide(); + _recolorButtonTriger_2->hide(); + _recolorButtonTriger_3->hide(); + // std::cout<<"hide 1,2 selection size : "<size()<<" mode : "<<_mode<hide(); _recolorButtonTriger_2->hide(); + _recolorButtonTriger_3->hide(); // std::cout<<"hide 1,2\n"; } } diff --git a/src/ui/widget/paint-selector.h b/src/ui/widget/paint-selector.h index f508e7ecf0..9909a17add 100644 --- a/src/ui/widget/paint-selector.h +++ b/src/ui/widget/paint-selector.h @@ -101,10 +101,13 @@ class PaintSelector : public Gtk::Box { UI::Widget::RecolorArt *_recolorArtWdgt_1 = nullptr; UI::Widget::RecolorArt *_recolorArtWdgt_2 = nullptr; + UI::Widget::RecolorArt *_recolorArtWdgt_3 = nullptr; Gtk::Button *_recolorButtonTriger_1 = nullptr; Gtk::Button *_recolorButtonTriger_2 = nullptr; + Gtk::Button *_recolorButtonTriger_3 = nullptr; Gtk::Popover* _recolorPopOver_1=nullptr; Gtk::Popover* _recolorPopOver_2=nullptr; + Gtk::Popover* _recolorPopOver_3=nullptr; bool _change_sel=false; SPDesktop*_desktop=nullptr; void onSelectionChanged(Inkscape::Selection *selection); -- GitLab From 88eaad1e3b3cbfad3f2596de20123af8503f7fe4 Mon Sep 17 00:00:00 2001 From: ftomara Date: Fri, 18 Jul 2025 16:19:06 +0300 Subject: [PATCH 065/122] added recolor button to pattern editor in case of multiple colored pattern --- share/ui/pattern-edit.glade | 2 +- src/ui/widget/paint-selector.cpp | 66 ++++++++++++++++++++++++++++++-- src/ui/widget/paint-selector.h | 4 ++ src/ui/widget/pattern-editor.h | 3 ++ 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/share/ui/pattern-edit.glade b/share/ui/pattern-edit.glade index 7993af04ab..59e90b9c2b 100644 --- a/share/ui/pattern-edit.glade +++ b/share/ui/pattern-edit.glade @@ -367,7 +367,7 @@ Gap 0 - 7 + 8 diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index 2f60b91b74..e98ab76301 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -129,12 +129,15 @@ PaintSelector::PaintSelector(FillOrStroke kind, std::shared_ptr()) , _recolorArtWdgt_2(Gtk::make_managed()) , _recolorArtWdgt_3(Gtk::make_managed()) + , _recolorArtWdgt_4(Gtk::make_managed()) , _recolorButtonTriger_1(Gtk::make_managed()) , _recolorButtonTriger_2(Gtk::make_managed()) , _recolorButtonTriger_3(Gtk::make_managed()) + , _recolorButtonTriger_4(Gtk::make_managed()) , _recolorPopOver_1(Gtk::make_managed()) , _recolorPopOver_2(Gtk::make_managed()) , _recolorPopOver_3(Gtk::make_managed()) + , _recolorPopOver_4(Gtk::make_managed()) { set_orientation(Gtk::Orientation::VERTICAL); @@ -222,6 +225,7 @@ PaintSelector::PaintSelector(FillOrStroke kind, std::shared_ptrsignal_clicked().connect([this]() { _recolorPopOver_1->popup(); @@ -238,6 +242,11 @@ PaintSelector::PaintSelector(FillOrStroke kind, std::shared_ptrperformUpdate(); }); + _recolorButtonTriger_4->signal_clicked().connect([this]() { + _recolorPopOver_4->popup(); + _recolorArtWdgt_4->performUpdate(); + }); + _frame->append(*_recolorButtonTriger_1); _recolorButtonTriger_1->hide(); } @@ -279,7 +288,7 @@ void PaintSelector::fillrule_toggled(FillRuleRadioButton *tb) void PaintSelector::setMode(Mode mode) { - if(_recolorPopOver_1->get_visible()||_recolorPopOver_2->get_visible()||_recolorPopOver_3->get_visible()) return; + if(_recolorPopOver_1->get_visible()||_recolorPopOver_2->get_visible()||_recolorPopOver_3->get_visible()||_recolorPopOver_4->get_visible()) return; set_mode_ex(mode, false); } @@ -1009,6 +1018,10 @@ void PaintSelector::set_mode_pattern(PaintSelector::Mode mode) _selector_pattern->signal_changed().connect([this](){ _signal_changed.emit(); }); _selector_pattern->signal_color_changed().connect([this](Colors::Color const &){ _signal_changed.emit(); }); _selector_pattern->signal_edit().connect([this](){ _signal_edit_pattern.emit(); }); + _selector_pattern->get_input_grid().attach(*_recolorButtonTriger_4,0,7); + _recolorButtonTriger_4->set_size_request(-1); + _recolorButtonTriger_4->set_label("Recolor Pattern"); + _recolorButtonTriger_4->hide(); _frame->append(*_selector_pattern); } @@ -1209,29 +1222,44 @@ void PaintSelector::onSelectionChanged(Inkscape::Selection *selection) auto group = dynamic_cast(selection->single()); auto use_group = dynamic_cast(selection->single()); auto item = dynamic_cast(selection->single()); + bool pattern_colors = false; SPMask *mask = nullptr; if (item) + { mask = dynamic_cast(item->getMaskObject()); - if (selection->size() > 1 || group || use_group || mask || _mode == MODE_GRADIENT_MESH) { + pattern_colors = has_colors_pattern(item); + } + if (selection->size() > 1 || group || use_group || mask || _mode == MODE_GRADIENT_MESH || pattern_colors) { if (_mode == MODE_MULTIPLE || _mode == MODE_UNSET || _mode == MODE_GRADIENT_MESH) { _recolorButtonTriger_1->show(); _recolorButtonTriger_2->hide(); _recolorButtonTriger_3->hide(); + _recolorButtonTriger_4->hide(); // std::cout<<"shoed 1 hide 2\n"; } else if (_mode == MODE_SOLID_COLOR) { _recolorButtonTriger_2->show(); _recolorButtonTriger_1->hide(); _recolorButtonTriger_3->hide(); + _recolorButtonTriger_4->hide(); // std::cout<<"shoed 2 hide 1\n"; } else if (_mode == MODE_GRADIENT_RADIAL || _mode == MODE_GRADIENT_LINEAR) { _recolorButtonTriger_1->hide(); _recolorButtonTriger_2->hide(); _recolorButtonTriger_3->show(); + _recolorButtonTriger_4->hide(); // std::cout<<"hide 1,2 selection size : "<size()<<" mode : "<<_mode<hide(); + _recolorButtonTriger_2->hide(); + _recolorButtonTriger_3->hide(); + _recolorButtonTriger_4->show(); + } + else { _recolorButtonTriger_1->hide(); _recolorButtonTriger_2->hide(); _recolorButtonTriger_3->hide(); + _recolorButtonTriger_4->hide(); // std::cout<<"hide 1,2 selection size : "<size()<<" mode : "<<_mode<hide(); _recolorButtonTriger_2->hide(); _recolorButtonTriger_3->hide(); + _recolorButtonTriger_4->hide(); // std::cout<<"hide 1,2\n"; } } @@ -1264,6 +1293,37 @@ void PaintSelector::set_change_selection(bool value) _change_sel = value; } +bool PaintSelector::has_colors_pattern(SPItem * item) +{ + std::setcolors; + SPPattern* patternstroke = nullptr; + SPPattern* patternfill = nullptr; + SPPattern* pattern = nullptr; + if(item && item->style) + { + patternstroke = dynamic_cast(item->style->getStrokePaintServer()); + patternfill = dynamic_cast(item->style->getFillPaintServer()); + if(patternstroke || patternfill)std::cout<<"pattern\n"; + } + if(patternstroke) pattern = patternstroke; + if(patternfill) pattern = patternfill; + if(!pattern) return false; + SPPattern *root = pattern->rootPattern(); + for (auto &child : root->children) { + auto item = cast(&child); + if (!item || !item->style) continue; + + if (item->style->fill.isColor()) { + std::string rgba = item->style->fill.getColor().toString(true); + colors.insert(rgba); + } + if (item->style->stroke.isColor()) { + std::string rgba = item->style->stroke.getColor().toString(true); + colors.insert(rgba); + } + } + return colors.size()>1; +} } // namespace Widget } // namespace UI diff --git a/src/ui/widget/paint-selector.h b/src/ui/widget/paint-selector.h index 9909a17add..94c4742b21 100644 --- a/src/ui/widget/paint-selector.h +++ b/src/ui/widget/paint-selector.h @@ -102,12 +102,15 @@ class PaintSelector : public Gtk::Box { UI::Widget::RecolorArt *_recolorArtWdgt_1 = nullptr; UI::Widget::RecolorArt *_recolorArtWdgt_2 = nullptr; UI::Widget::RecolorArt *_recolorArtWdgt_3 = nullptr; + UI::Widget::RecolorArt *_recolorArtWdgt_4 = nullptr; Gtk::Button *_recolorButtonTriger_1 = nullptr; Gtk::Button *_recolorButtonTriger_2 = nullptr; Gtk::Button *_recolorButtonTriger_3 = nullptr; + Gtk::Button *_recolorButtonTriger_4 = nullptr; Gtk::Popover* _recolorPopOver_1=nullptr; Gtk::Popover* _recolorPopOver_2=nullptr; Gtk::Popover* _recolorPopOver_3=nullptr; + Gtk::Popover* _recolorPopOver_4=nullptr; bool _change_sel=false; SPDesktop*_desktop=nullptr; void onSelectionChanged(Inkscape::Selection *selection); @@ -212,6 +215,7 @@ class PaintSelector : public Gtk::Box { Glib::ustring get_pattern_label(); bool is_pattern_scale_uniform(); void set_change_selection(bool value); + bool has_colors_pattern(SPItem * item); }; enum { diff --git a/src/ui/widget/pattern-editor.h b/src/ui/widget/pattern-editor.h index c1753c375d..a4e15902e0 100644 --- a/src/ui/widget/pattern-editor.h +++ b/src/ui/widget/pattern-editor.h @@ -68,6 +68,9 @@ public: // get pattern label Glib::ustring get_label(); + Gtk::Grid& get_input_grid(){return _input_grid;}; + + private: sigc::signal _signal_changed; sigc::signal _signal_color_changed; -- GitLab From 876d9d42e46bea9e48fab953badb618644d4b5a4 Mon Sep 17 00:00:00 2001 From: ftomara Date: Mon, 21 Jul 2025 08:32:50 +0300 Subject: [PATCH 066/122] added color collection and changing for groups objects inside patterns --- src/ui/widget/paint-selector.cpp | 16 ++++++++++++++++ src/ui/widget/recolor-art.cpp | 5 ++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index e98ab76301..0258040a58 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -1310,6 +1310,22 @@ bool PaintSelector::has_colors_pattern(SPItem * item) if(!pattern) return false; SPPattern *root = pattern->rootPattern(); for (auto &child : root->children) { + auto group = cast(&child); + if (group) { + std::cout<<"group pattern\n"; + for (auto &child : group->children) { + if (auto c = dynamic_cast(&child)) { + if (c->style->fill.isColor()) { + std::string rgba = c->style->fill.getColor().toString(true); + colors.insert(rgba); + } + if (c->style->stroke.isColor()) { + std::string rgba = c->style->stroke.getColor().toString(true); + colors.insert(rgba); + } + } + } + } auto item = cast(&child); if (!item || !item->style) continue; diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index e5a5e47cf0..8127964af0 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -363,7 +363,10 @@ void RecolorArt::extractPatternColors(SPPattern *pattern) { SPPattern *root = pattern->rootPattern(); for (auto &child : root->children) { - extractItemStyle(&child, "pattern"); + if (auto group = dynamic_cast(&child)) + extractItemColors(group, "pattern"); + else + extractItemStyle(&child, "pattern"); } } void RecolorArt::extractMarkerColors(Glib::ustring marker, SPObject *item) -- GitLab From e9f0df242fe43cb3b6ab6ab8f0974db0e966f04d Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 22 Jul 2025 13:35:54 +0300 Subject: [PATCH 067/122] made notebook and page refs instead of pointers --- src/ui/widget/recolor-art.cpp | 27 ++++++++++++++------------- src/ui/widget/recolor-art.h | 4 ++++ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 8127964af0..04c25ac7d2 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -61,24 +61,17 @@ RecolorArt::RecolorArt() : Gtk::Box() , _builder(create_builder("recolor-art.glade")) , _solid_colors(std::make_shared()) + , _notebook(*_builder->get_widget("list-wheel-box")) + , _color_wheel_page(*_builder->get_widget("color-wheel-page")) + , _color_wheel(new MultiMarkerWheel()) { set_name("RecolorArt"); append(get_widget(_builder, "recolor-art")); signal_unmap().connect([&]() { resetOpacity(); }); _solid_colors->set(Color(0x000000ff)); - - layoutColorPicker(); - _color_list = _builder->get_widget("colors-list"); - _live_preview = _builder->get_widget("liveP"); - _live_preview->signal_toggled().connect(sigc::mem_fun(*this, &RecolorArt::onLivePreviewToggled)); - _live_preview->set_active(true); - _reset = _builder->get_widget("reset"); - _reset->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::onResetClicked)); - - _notebook = _builder->get_widget("list-wheel-box"); - _color_wheel_page = _builder->get_widget("color-wheel-page"); - _notebook->signal_switch_page().connect([this](Gtk::Widget *page, guint page_num) { - int wheel_index = _notebook->page_num(*_color_wheel_page); + _color_wheel_page.append(*_color_wheel); + _notebook.signal_switch_page().connect([this](Gtk::Widget *page, guint page_num) { + int wheel_index = _notebook.page_num(_color_wheel_page); if (static_cast(page_num) == wheel_index) { _color_picker_wdgt->set_visible(false); @@ -89,6 +82,14 @@ RecolorArt::RecolorArt() } }); + layoutColorPicker(); + _color_list = _builder->get_widget("colors-list"); + _live_preview = _builder->get_widget("liveP"); + _live_preview->signal_toggled().connect(sigc::mem_fun(*this, &RecolorArt::onLivePreviewToggled)); + _live_preview->set_active(true); + _reset = _builder->get_widget("reset"); + _reset->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::onResetClicked)); + _list_view = _builder->get_widget("recolor-art-list"); _color_model = Gio::ListStore::create(); _selection_model = Gtk::SingleSelection::create(_color_model); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 069bec6c22..bce06e85b4 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -78,6 +78,10 @@ class RecolorArt : public Gtk::Box { private: SPDesktop *_desktop = nullptr; + Glib::RefPtr _builder; + Gtk::Notebook &_notebook; + Gtk::Box &_color_wheel_page; + PaintSelector *_paint_selector; std::shared_ptr _solid_colors; std::map, std::optional>> _selected_colors; Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr; -- GitLab From 15bed63c2c71ea4d40bc5df336961b16aa34885f Mon Sep 17 00:00:00 2001 From: ftomara Date: Wed, 23 Jul 2025 02:12:29 +0300 Subject: [PATCH 068/122] multimarker colorwheel basics --- src/ui/widget/ink-color-wheel.cpp | 417 ++++++++++++++++++++++++++++++ src/ui/widget/ink-color-wheel.h | 56 ++++ src/ui/widget/recolor-art.cpp | 17 ++ src/ui/widget/recolor-art.h | 9 +- 4 files changed, 495 insertions(+), 4 deletions(-) diff --git a/src/ui/widget/ink-color-wheel.cpp b/src/ui/widget/ink-color-wheel.cpp index 8561f92cab..adbcc14b99 100644 --- a/src/ui/widget/ink-color-wheel.cpp +++ b/src/ui/widget/ink-color-wheel.cpp @@ -761,6 +761,423 @@ bool ColorWheelHSLuv::setColor(Color const &color, } return false; } +/*multi marker color wheel*/ + +bool MultiMarkerWheel::setColor(Color const &color, bool const /*overrideHue*/, bool const emit) +{ + if (_values.set(color, true)) { + _values_vector.push_back(_values); + _marker_point.reset(); + if (emit) + color_changed(); + else + queue_drawing_area_draw(); + return true; + } + return false; +} + +bool MultiMarkerWheel::setColor(std::vector const &color, bool overrideHue, bool emit) +{ + return false; +} +void MultiMarkerWheel::update_ring_source() +{ + if (_radii && _source_ring) + return; + + auto const [width, height] = *_cache_size; + auto const cx = width / 2.0; + auto const cy = height / 2.0; + + auto const stride = Cairo::ImageSurface::format_stride_for_width(Cairo::Surface::Format::RGB24, width); + _source_ring.reset(); + _buffer_ring.resize(height * stride / 4); + + auto const &[r_min, r_max] = get_radii(); + double r2_max = (r_max + 2) * (r_max + 2); // Must expand a bit to avoid edge effects. + double r2_min = (r_min - 2) * (r_min - 2); // Must shrink a bit to avoid edge effects. + + for (int i = 0; i < height; ++i) { + auto p = _buffer_ring.data() + i * width; + double dy = (cy - i); + for (int j = 0; j < width; ++j) { + double dx = (j - cx); + double r2 = dx * dx + dy * dy; + if (r2 < r2_min || r2 > r2_max) { + *p++ = 0; // Save calculation time. + } else { + double angle = atan2(dy, dx); + if (angle < 0.0) { + angle += 2.0 * M_PI; + } + double hue = angle / (2.0 * M_PI); + + double saturation = sqrt(r2)/r_max; + saturation = std::clamp(saturation,0.0,1.0); + // double value = 1.0 - ((dy+(height/2.0))/height); + // value = std::clamp(value,0.0,1.0); + + *p++ = Color(Type::HSV, {hue, saturation,1.0}).toARGB(); + } + } + } + + auto const data = reinterpret_cast(_buffer_ring.data()); + _source_ring = Cairo::ImageSurface::create(data, Cairo::Surface::Format::RGB24, width, height, stride); +} + +void MultiMarkerWheel::on_drawing_area_size(int width, int height, int baseline) +{ + auto const size = Geom::IntPoint{width, height}; + if (size == _cache_size) + return; + _cache_size = size; + _radii.reset(); + _source_ring.reset(); +} + +void MultiMarkerWheel::on_drawing_area_draw(Cairo::RefPtr const &cr, int, int) +{ + + auto const [width, height] = *_cache_size; + auto const cx = width / 2.0; + auto const cy = height / 2.0; + + cr->set_antialias(Cairo::ANTIALIAS_SUBPIXEL); + + // Update caches + update_ring_source(); + auto const &[r_min, r_max] = get_radii(); + + // Paint with ring surface, clipping to ring. + cr->save(); + cr->set_source(_source_ring, 0, 0); + cr->set_line_width(r_max - r_min); + cr->begin_new_path(); + cr->arc(cx, cy, (r_max + r_min) / 2.0, 0, 2.0 * M_PI); + cr->stroke(); + cr->restore(); + // Paint line on ring + + auto color_on_ring = Color(Type::HSV, {_values[0], 1.0, 1.0}); + auto const &[mx, my] = get_marker_point(); + + double dy = my-cy; + double dx = mx-cx; + double len = std::sqrt(dx*dx+dy*dy); + + if(len > 1e-5) + { + dx /= len; + dy /= len; + } + + double tx = mx - dx * marker_radius; + double ty = my - dy * marker_radius; + + + double l = luminance(color_on_ring) < 0.5 ? 1.0 : 0.0; + cr->save(); + cr->set_source_rgb(l, l, l); + cr->move_to(cx + cos(_values[0] * M_PI * 2.0) * (r_min), + cy - sin(_values[0] * M_PI * 2.0) * (r_min)); + cr->line_to(tx,ty); + cr->set_dash(focus_dash, 0); + cr->set_line_width(1.0); + cr->stroke(); + cr->restore(); + + // Draw marker + double a = luminance(getColor()) < 0.5 ? 1.0 : 0.0; + cr->set_source_rgb(a, a, a); + cr->begin_new_path(); + cr->arc(mx, my, marker_radius, 0, 2 * M_PI); + cr->stroke(); + + // Draw focus + if (drawing_area_has_focus()) { + // The focus_dash width & alpha(foreground_color) are from GTK3 Adwaita. + cr->set_dash(focus_dash, 0); + cr->set_line_width(1.0); + + if (_focus_on_ring) { + auto const rgba = change_alpha(Widget::get_color(), 0.7); + Gdk::Cairo::set_source_rgba(cr, rgba); + cr->begin_new_path(); + cr->rectangle(0, 0, width, height); + } else { + cr->set_source_rgb(1 - a, 1 - a, 1 - a); + cr->begin_new_path(); + cr->arc(mx, my, marker_radius + focus_padding, 0, 2 * M_PI); + } + + cr->stroke(); + } +} + +std::optional MultiMarkerWheel::focus(Gtk::DirectionType const direction) +{ + // Any focus change must update focus indicators (add or remove). + queue_drawing_area_draw(); + + // In forward direction, focus passes from no focus to ring focus to triangle + // focus to no focus. + if (!drawing_area_has_focus()) { + _focus_on_ring = (direction == Gtk::DirectionType::TAB_FORWARD); + focus_drawing_area(); + return true; + } + + // Already have focus + bool keep_focus = true; + + switch (direction) { + case Gtk::DirectionType::TAB_BACKWARD: + if (!_focus_on_ring) { + _focus_on_ring = true; + } else { + keep_focus = false; + } + break; + + case Gtk::DirectionType::TAB_FORWARD: + if (_focus_on_ring) { + _focus_on_ring = false; + } else { + keep_focus = false; + } + } + + return keep_focus; +} + +bool MultiMarkerWheel::_set_from_xy(double const x, double const y) +{ + auto const [width, height] = *_cache_size; + double const cx = width / 2.0; + double const cy = height / 2.0; + + double const r = std::min(cx, cy) * (1 - _ring_width); + + // We calculate RGB value under the cursor by rotating the cursor + // and triangle by the hue value and looking at position in the + // now right pointing triangle. + double angle = _values[0] * 2 * M_PI; + double sin = std::sin(angle); + double cos = std::cos(angle); + double xp = ((x - cx) * cos - (y - cy) * sin) / r; + double yp = ((x - cx) * sin + (y - cy) * cos) / r; + + double xt = lerp(0.0, 1.0, -0.5, 1.0, xp); + xt = std::clamp(xt, 0.0, 1.0); + + double dy = (1 - xt) * std::cos(M_PI / 6.0); + double yt = lerp(0.0, 1.0, -dy, dy, yp); + yt = std::clamp(yt, 0.0, 1.0); + + ColorPoint c0(0, 0, Color(Type::RGB, {yt, yt, yt})); // Grey point along base. + ColorPoint c1(0, 0, Color(Type::HSV, {_values[0], 1, 1})); // Hue point at apex + ColorPoint c = lerp(c0, c1, 0, 1, xt); + c.color.setOpacity(_values.getOpacity()); // Remember opacity + return setColor(c.color, false); // Don't override previous hue. +} + +bool MultiMarkerWheel::set_from_xy_delta(double const dx, double const dy) +{ + auto [mx, my] = get_marker_point(); + mx += dx; + my += dy; + return _set_from_xy(mx, my); +} + +bool MultiMarkerWheel::_is_in_ring(double x, double y) +{ + std::cout<<"x: "< const &builder) + : ColorWheelBase(cobject, builder, Type::HSV, {0.5, 0.2, 0.7, 1}) +{} /** * Update the PickerGeometry structure owned by the instance. diff --git a/src/ui/widget/ink-color-wheel.h b/src/ui/widget/ink-color-wheel.h index 8169bd86b9..525ef45f6d 100644 --- a/src/ui/widget/ink-color-wheel.h +++ b/src/ui/widget/ink-color-wheel.h @@ -225,6 +225,62 @@ private: int _square_size = 1; }; +/** + * @class MultiMarkerWheel + */ +class MultiMarkerWheel + : public WidgetVfuncsClassInit + , public ColorWheelBase +{ +public: + MultiMarkerWheel(); + MultiMarkerWheel(BaseObjectType *cobject, Glib::RefPtr const &builder); + bool setColor(Colors::Color const &color, bool overrideHue = true, bool emit = true) override; + bool setColor(std::vector const &color, bool overrideHue = true, bool emit = true); + +private: + void on_drawing_area_size(int width, int height, int baseline) override; + void on_drawing_area_draw(Cairo::RefPtr const &cr, int, int) override; + std::optional focus(Gtk::DirectionType direction) override; + + bool _set_from_xy(double x, double y); + bool set_from_xy_delta(double dx, double dy); + bool _is_in_ring(double x, double y); + void _update_ring_color(double x, double y); + + enum class DragMode + { + NONE, + HUE, + SATURATION_VALUE + }; + + static constexpr double _ring_width = 1.0; + DragMode _mode = DragMode::NONE; + bool _focus_on_ring = true; + + Gtk::EventSequenceState on_click_pressed(Gtk::GestureClick const &controller, int n_press, double x, + double y) final; + Gtk::EventSequenceState on_click_released(int n_press, double x, double y) final; + void on_motion(Gtk::EventControllerMotion const &motion, double x, double y) final; + bool on_key_pressed(unsigned keyval, unsigned keycode, Gdk::ModifierType state) final; + + // caches to speed up drawing + using MinMax = std::array; + using MarkerPoints = std::vector; + std::vector _values_vector; + std::optional _cache_size; + std::optional _radii; + std::optional _marker_point; + std::optional _markers_points; + std::vector _buffer_ring; + Cairo::RefPtr _source_ring; + [[nodiscard]] MinMax const &get_radii(); + [[nodiscard]] Geom::Point const &get_marker_point(); + int _active_index = 0; + void update_ring_source(); +}; + } // namespace Inkscape::UI::Widget #endif // INK_COLORWHEEL_HSLUV_H diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 04c25ac7d2..22f73c9f8c 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -30,6 +30,7 @@ #include "document-undo.h" #include "document.h" #include "gradient-chemistry.h" +#include "ink-color-wheel.h" #include "inkscape.h" #include "object/sp-defs.h" #include "object/sp-gradient.h" @@ -64,12 +65,28 @@ RecolorArt::RecolorArt() , _notebook(*_builder->get_widget("list-wheel-box")) , _color_wheel_page(*_builder->get_widget("color-wheel-page")) , _color_wheel(new MultiMarkerWheel()) + , _dummie_color_wheel_button(Gtk::make_managed()) { set_name("RecolorArt"); append(get_widget(_builder, "recolor-art")); signal_unmap().connect([&]() { resetOpacity(); }); _solid_colors->set(Color(0x000000ff)); _color_wheel_page.append(*_color_wheel); + _color_wheel_page.append(*_dummie_color_wheel_button); + _color_wheel->connect_color_changed(static_cast>([this]() { + auto css_provider = Gtk::CssProvider::create(); + uint32_t cc = _color_wheel->getColor().toRGBA(); + Color c(cc,true); + std::string css = + "button.color-preview { background-color: " + c.toString(true) + "; background-image : none; }"; + + css_provider->load_from_data(css); + + auto context = _dummie_color_wheel_button->get_style_context(); + context->add_provider(css_provider, GTK_STYLE_PROVIDER_PRIORITY_USER); + context->add_class("color-preview"); + std::cout << "button color : " << c.toString(true) << std::endl; + })); _notebook.signal_switch_page().connect([this](Gtk::Widget *page, guint page_num) { int wheel_index = _notebook.page_num(_color_wheel_page); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index bce06e85b4..473665c59c 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -18,6 +18,7 @@ #include "style-internal.h" #include "style.h" #include "ui/widget/paint-selector.h" +#include "ui/widget/ink-color-wheel.h" using namespace Inkscape::Colors; @@ -100,13 +101,13 @@ private: std::map> _gradient_stops; - Gtk::Notebook *_notebook = nullptr; - Gtk::Box *_color_wheel_page = nullptr; - PaintSelector *_paint_selector = nullptr; + + MultiMarkerWheel *_color_wheel = nullptr; + + Gtk::Button* _dummie_color_wheel_button = nullptr; // Gtk::Button *_apply = nullptr; - Glib::RefPtr _builder; void populateMap(Color color, SPObject *style, std::string kind); void collectColors(std::vector items,std::string kind=""); void extractGradientStops(SPObject *item, bool isFill); -- GitLab From 927e00d4cb718052b616899bd06df70174821376 Mon Sep 17 00:00:00 2001 From: ftomara Date: Wed, 23 Jul 2025 11:35:17 +0300 Subject: [PATCH 069/122] made colors in ColorItem not optional --- src/ui/widget/recolor-art.cpp | 6 +++--- src/ui/widget/recolor-art.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 22f73c9f8c..1bfa48a899 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -182,9 +182,9 @@ RecolorArt::RecolorArt() auto recolored = dynamic_cast(box->get_last_child()); if (original && recolored) { - colorButtons(original, item->old_color.value(), true); - colorButtons(recolored, item->new_color.value()); - setUpTypeBox(static_cast(list_item->get_data("typebox")), item->old_color.value()); + colorButtons(original, item->old_color, true); + colorButtons(recolored, item->new_color); + setUpTypeBox(static_cast(list_item->get_data("typebox")), item->old_color); original->set_name("original"); recolored->set_name("recolored"); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 473665c59c..04ba550ff7 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -63,8 +63,8 @@ struct ColorPair struct ColorItem : public Glib::Object { Glib::ustring key; - std::optional old_color; - std::optional new_color; + Color old_color = Color(0x00000000); + Color new_color = Color(0x00000000); static Glib::RefPtr create(Glib::ustring const &k, Color const &old_c, Color const &new_c) { -- GitLab From d77eedebdefedb6a39081250cc0dbc4a09e58120 Mon Sep 17 00:00:00 2001 From: ftomara Date: Wed, 23 Jul 2025 11:39:42 +0300 Subject: [PATCH 070/122] passed objects vector by ref --- src/ui/widget/recolor-art.cpp | 2 +- src/ui/widget/recolor-art.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 1bfa48a899..449261fd70 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -244,7 +244,7 @@ void RecolorArt::setDesktop(SPDesktop *desktop) } g_message("setDesktop\n"); } -void RecolorArt::collectColors(std::vector items, std::string kind) +void RecolorArt::collectColors(std::vector&items, std::string kind) { for (auto item : items) { auto it = dynamic_cast(item); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 04ba550ff7..0090877076 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -109,7 +109,7 @@ private: // Gtk::Button *_apply = nullptr; void populateMap(Color color, SPObject *style, std::string kind); - void collectColors(std::vector items,std::string kind=""); + void collectColors(std::vector& items,std::string kind=""); void extractGradientStops(SPObject *item, bool isFill); void extractMeshStops(std::vector> mesh_nodes, SPObject *item, std::string kind); void extractItemColors(SPObject *item,std::string kind=""); -- GitLab From 6313ad4f76600796e7d1ac5e8ba8365746b6a2f9 Mon Sep 17 00:00:00 2001 From: ftomara Date: Wed, 23 Jul 2025 11:41:06 +0300 Subject: [PATCH 071/122] passed meshnodes by ref --- src/ui/widget/recolor-art.cpp | 2 +- src/ui/widget/recolor-art.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 449261fd70..67c3cb8975 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -308,7 +308,7 @@ void RecolorArt::extractGradientStops(SPObject *item, bool isFill) } } } -void RecolorArt::extractMeshStops(std::vector> mesh_nodes, SPObject *item, std::string kind) +void RecolorArt::extractMeshStops(std::vector>& mesh_nodes, SPObject *item, std::string kind) { for (auto nodes : mesh_nodes) { for (auto node : nodes) { diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 0090877076..35eaa37ac2 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -111,7 +111,7 @@ private: void populateMap(Color color, SPObject *style, std::string kind); void collectColors(std::vector& items,std::string kind=""); void extractGradientStops(SPObject *item, bool isFill); - void extractMeshStops(std::vector> mesh_nodes, SPObject *item, std::string kind); + void extractMeshStops(std::vector>& mesh_nodes, SPObject *item, std::string kind); void extractItemColors(SPObject *item,std::string kind=""); void extractItemStyle(SPObject *item ,std::string kind=""); void extractPatternColors(SPPattern *pattern); -- GitLab From b503dc1b725126a65023f1e71749dfb553afbe4a Mon Sep 17 00:00:00 2001 From: ftomara Date: Wed, 23 Jul 2025 11:46:50 +0300 Subject: [PATCH 072/122] intialized builder and solid colors in the header file --- src/ui/widget/recolor-art.cpp | 2 -- src/ui/widget/recolor-art.h | 5 +++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 67c3cb8975..29d903c866 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -60,8 +60,6 @@ namespace Widget { RecolorArt::RecolorArt() : Gtk::Box() - , _builder(create_builder("recolor-art.glade")) - , _solid_colors(std::make_shared()) , _notebook(*_builder->get_widget("list-wheel-box")) , _color_wheel_page(*_builder->get_widget("color-wheel-page")) , _color_wheel(new MultiMarkerWheel()) diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 35eaa37ac2..23389c9c66 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -13,6 +13,7 @@ #include #include #include +#include "ui/builder-utils.h" #include "canvas.h" #include "style-internal.h" @@ -79,11 +80,11 @@ class RecolorArt : public Gtk::Box { private: SPDesktop *_desktop = nullptr; - Glib::RefPtr _builder; + Glib::RefPtr _builder = create_builder("recolor-art.glade"); Gtk::Notebook &_notebook; Gtk::Box &_color_wheel_page; PaintSelector *_paint_selector; - std::shared_ptr _solid_colors; + std::shared_ptr _solid_colors = std::make_shared(); std::map, std::optional>> _selected_colors; Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr; Gtk::Box *_color_list = nullptr; -- GitLab From 24811737bca0f181354d3bc2416fb743b71ea676 Mon Sep 17 00:00:00 2001 From: ftomara Date: Wed, 23 Jul 2025 12:08:18 +0300 Subject: [PATCH 073/122] fixed solid colors signal connection redundancy --- src/ui/widget/recolor-art.cpp | 15 +++++++++++++-- src/ui/widget/recolor-art.h | 1 + 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 29d903c866..0f489a0f1c 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -233,7 +233,13 @@ RecolorArt::RecolorArt() // _apply = _builder->get_widget("apply"); // _apply->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::_onApplyButtonClicked)); } -RecolorArt::~RecolorArt() {} +RecolorArt::~RecolorArt() +{ + if(_solid_color_changed.connected()) + { + _solid_color_changed.disconnect(); + } +} void RecolorArt::setDesktop(SPDesktop *desktop) { @@ -421,7 +427,12 @@ void RecolorArt::layoutColorPicker(std::shared_ptr updated_col _color_picker_wdgt = Gtk::make_managed(_solid_colors); _color_picker_wdgt->set_visible(true); _color_picker_wdgt->set_label(_("Selected Color")); - _solid_colors->signal_changed.connect(sigc::mem_fun(*this, &RecolorArt::onColorPickerChanged)); + + if(_solid_color_changed.connected()) + { + _solid_color_changed.disconnect(); + } + _solid_color_changed = _solid_colors->signal_changed.connect(sigc::mem_fun(*this, &RecolorArt::onColorPickerChanged)); auto container = _builder->get_widget("color-picker"); if (container) { diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 23389c9c66..cc07d65497 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -85,6 +85,7 @@ private: Gtk::Box &_color_wheel_page; PaintSelector *_paint_selector; std::shared_ptr _solid_colors = std::make_shared(); + sigc::connection _solid_color_changed ; std::map, std::optional>> _selected_colors; Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr; Gtk::Box *_color_list = nullptr; -- GitLab From 040d1e12402d05a95cbc2f15a52a2f215b9c9c60 Mon Sep 17 00:00:00 2001 From: ftomara Date: Wed, 23 Jul 2025 12:19:20 +0300 Subject: [PATCH 074/122] made colorlist,reset,live preview refs instead of pointers --- src/ui/widget/recolor-art.cpp | 22 +++++++++++----------- src/ui/widget/recolor-art.h | 8 ++++---- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 0f489a0f1c..d0146045d8 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -63,6 +63,9 @@ RecolorArt::RecolorArt() , _notebook(*_builder->get_widget("list-wheel-box")) , _color_wheel_page(*_builder->get_widget("color-wheel-page")) , _color_wheel(new MultiMarkerWheel()) + ,_color_list(*_builder->get_widget("colors-list")) + ,_reset(*_builder->get_widget("reset")) + ,_live_preview(*_builder->get_widget("liveP")) , _dummie_color_wheel_button(Gtk::make_managed()) { set_name("RecolorArt"); @@ -98,12 +101,9 @@ RecolorArt::RecolorArt() }); layoutColorPicker(); - _color_list = _builder->get_widget("colors-list"); - _live_preview = _builder->get_widget("liveP"); - _live_preview->signal_toggled().connect(sigc::mem_fun(*this, &RecolorArt::onLivePreviewToggled)); - _live_preview->set_active(true); - _reset = _builder->get_widget("reset"); - _reset->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::onResetClicked)); + _live_preview.signal_toggled().connect(sigc::mem_fun(*this, &RecolorArt::onLivePreviewToggled)); + _live_preview.set_active(true); + _reset.signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::onResetClicked)); _list_view = _builder->get_widget("recolor-art-list"); _color_model = Gio::ListStore::create(); @@ -418,7 +418,7 @@ void RecolorArt::generateVisualList() auto new_color = value.second.value().new_color; _color_model->append(ColorItem::create(key, old_color, new_color)); } - _color_list->append(*_list_view); + _color_list.append(*_list_view); } void RecolorArt::layoutColorPicker(std::shared_ptr updated_color) { @@ -551,7 +551,7 @@ void RecolorArt::onColorPickerChanged() auto _selected = _selected_colors.find(_current_color_id); if (_selected != _selected_colors.end()) _selected->second.second.value().new_color = new_color.value(); - if (_live_preview && _live_preview->property_active()) { + if (_live_preview.property_active()) { lpChecked(); } guint index = _selection_model->get_selected(); @@ -712,7 +712,7 @@ void RecolorArt::resetOpacity() } void RecolorArt::onLivePreviewToggled() { - _is_preview = _live_preview->property_active(); + _is_preview = _live_preview.property_active(); if (_is_preview) { convertToRecoloredColors(); } else { @@ -735,8 +735,8 @@ void RecolorArt::setPaintSelector(PaintSelector *ps) void RecolorArt::performUpdate() { - for (auto child : _color_list->get_children()) { - _color_list->remove(*child); + for (auto child : _color_list.get_children()) { + _color_list.remove(*child); } buttons.clear(); _gradient_stops.clear(); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index cc07d65497..a52ab7a222 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -87,11 +87,11 @@ private: std::shared_ptr _solid_colors = std::make_shared(); sigc::connection _solid_color_changed ; std::map, std::optional>> _selected_colors; - Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr; - Gtk::Box *_color_list = nullptr; + Gtk::Box &_color_list ; + Gtk::Button &_reset; + Gtk::CheckButton &_live_preview; + Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr ; Gtk::ListView *_list_view = nullptr; - Gtk::Button *_reset = nullptr; - Gtk::CheckButton *_live_preview = nullptr; std::string _current_color_id; std::map> buttons; // color_id : {original , recolored} std::map _type_boxes; -- GitLab From c7ce1d60c50448fa8ec98b329ff3558ad2ed42e4 Mon Sep 17 00:00:00 2001 From: ftomara Date: Wed, 23 Jul 2025 18:58:02 +0300 Subject: [PATCH 075/122] visualized multiple colors on the wheel --- src/ui/widget/ink-color-wheel.cpp | 211 ++++++++++++++++++------------ src/ui/widget/ink-color-wheel.h | 22 +++- src/ui/widget/recolor-art.cpp | 6 +- src/ui/widget/recolor-art.h | 1 + 4 files changed, 151 insertions(+), 89 deletions(-) diff --git a/src/ui/widget/ink-color-wheel.cpp b/src/ui/widget/ink-color-wheel.cpp index adbcc14b99..43156a7945 100644 --- a/src/ui/widget/ink-color-wheel.cpp +++ b/src/ui/widget/ink-color-wheel.cpp @@ -767,7 +767,6 @@ bool MultiMarkerWheel::setColor(Color const &color, bool const /*overrideHue*/, { if (_values.set(color, true)) { _values_vector.push_back(_values); - _marker_point.reset(); if (emit) color_changed(); else @@ -777,9 +776,93 @@ bool MultiMarkerWheel::setColor(Color const &color, bool const /*overrideHue*/, return false; } -bool MultiMarkerWheel::setColor(std::vector const &color, bool overrideHue, bool emit) +bool MultiMarkerWheel::setColor(std::vector const &color) { - return false; + _values_vector.clear(); + _markers_points.clear(); + for (auto c : color) { + if(!setColor(c)) return false; + } + _markers_points.resize(_values_vector.size()); + _reset_markers(); + return true ; +} +void MultiMarkerWheel::_reset_markers() { + for(auto& _marker_point : _markers_points) + _marker_point.reset(); + _markers_points.resize(_values_vector.size()); +} +void MultiMarkerWheel::_draw_marker(Cairo::RefPtr const &cr , Colors::Color value , int index) +{ + auto const [width, height] = *_cache_size; + auto const cx = width / 2.0; + auto const cy = height / 2.0; + auto const &[mx, my] = get_marker_point(index); + + _draw_line_2_marker(cr,mx,my,cx,cy,value,index); + + auto color_on_ring = Color(Type::HSV, {value[0], 1.0, 1.0}); + double a = luminance(color_on_ring) < 0.5 ? 1.0 : 0.0; + cr->set_source_rgb(a, a, a); + cr->begin_new_path(); + cr->arc(mx, my, marker_radius, 0, 2 * M_PI); + cr->stroke(); + + // Draw focus + if (drawing_area_has_focus()) { + // The focus_dash width & alpha(foreground_color) are from GTK3 Adwaita. + if (index == _active_index) { + cr->set_dash(focus_dash, 0); + cr->set_line_width(1.0); + cr->set_source_rgb(1 - a, 1 - a, 1 - a); + cr->begin_new_path(); + cr->arc(mx, my, marker_radius + focus_padding, 0, 2 * M_PI); + } + + cr->stroke(); + } +} +int MultiMarkerWheel::_get_marker_position(double x, double y) +{ + for(int i =0 ; i<_values_vector.size();i++) + { + auto const& [mx,my] = get_marker_point(i); + double dx = x-mx; + double dy = y-my; + double distance = std::sqrt(dx*dx + dy*dy); + if(distance <= marker_radius + marker_click_tolerance) + return i; + } + return -1; +} +void MultiMarkerWheel::_draw_line_2_marker(Cairo::RefPtr const &cr, double mx, double my, double cx, + double cy, Colors::Color value , int index) +{ + + auto const &[r_min, r_max] = get_radii(); + auto color_on_ring = Color(Type::HSV, {value[0], 1.0, 1.0}); + double dy = my-cy; + double dx = mx-cx; + double len = std::sqrt(dx*dx+dy*dy); + if(len > 1e-5) + { + dx /= len; + dy /= len; + } + double tx = mx - dx * marker_radius; + double ty = my - dy * marker_radius; + double l = luminance(color_on_ring) < 0.5 ? 1.0 : 0.0; + cr->save(); + cr->set_source_rgb(l, l, l); + cr->move_to(cx + cos(value[0] * M_PI * 2.0) * (r_min), + cy - sin(value[0] * M_PI * 2.0) * (r_min)); + cr->line_to(tx,ty); + if (index != _active_index) { + cr->set_dash(focus_dash, 0); + cr->set_line_width(1.0); + } + cr->stroke(); + cr->restore(); } void MultiMarkerWheel::update_ring_source() { @@ -858,61 +941,13 @@ void MultiMarkerWheel::on_drawing_area_draw(Cairo::RefPtr const cr->arc(cx, cy, (r_max + r_min) / 2.0, 0, 2.0 * M_PI); cr->stroke(); cr->restore(); - // Paint line on ring - - auto color_on_ring = Color(Type::HSV, {_values[0], 1.0, 1.0}); - auto const &[mx, my] = get_marker_point(); - - double dy = my-cy; - double dx = mx-cx; - double len = std::sqrt(dx*dx+dy*dy); - - if(len > 1e-5) - { - dx /= len; - dy /= len; + // Paint line to markers and markers + if (_markers_points.size() != _values_vector.size()) { + _markers_points.resize(_values_vector.size()); } - double tx = mx - dx * marker_radius; - double ty = my - dy * marker_radius; - - - double l = luminance(color_on_ring) < 0.5 ? 1.0 : 0.0; - cr->save(); - cr->set_source_rgb(l, l, l); - cr->move_to(cx + cos(_values[0] * M_PI * 2.0) * (r_min), - cy - sin(_values[0] * M_PI * 2.0) * (r_min)); - cr->line_to(tx,ty); - cr->set_dash(focus_dash, 0); - cr->set_line_width(1.0); - cr->stroke(); - cr->restore(); - - // Draw marker - double a = luminance(getColor()) < 0.5 ? 1.0 : 0.0; - cr->set_source_rgb(a, a, a); - cr->begin_new_path(); - cr->arc(mx, my, marker_radius, 0, 2 * M_PI); - cr->stroke(); - - // Draw focus - if (drawing_area_has_focus()) { - // The focus_dash width & alpha(foreground_color) are from GTK3 Adwaita. - cr->set_dash(focus_dash, 0); - cr->set_line_width(1.0); - - if (_focus_on_ring) { - auto const rgba = change_alpha(Widget::get_color(), 0.7); - Gdk::Cairo::set_source_rgba(cr, rgba); - cr->begin_new_path(); - cr->rectangle(0, 0, width, height); - } else { - cr->set_source_rgb(1 - a, 1 - a, 1 - a); - cr->begin_new_path(); - cr->arc(mx, my, marker_radius + focus_padding, 0, 2 * M_PI); - } - - cr->stroke(); + for (int i = 0; i < _values_vector.size(); i++) { + _draw_marker(cr, _values_vector[i], i); } } @@ -983,13 +1018,13 @@ bool MultiMarkerWheel::_set_from_xy(double const x, double const y) return setColor(c.color, false); // Don't override previous hue. } -bool MultiMarkerWheel::set_from_xy_delta(double const dx, double const dy) -{ - auto [mx, my] = get_marker_point(); - mx += dx; - my += dy; - return _set_from_xy(mx, my); -} +// bool MultiMarkerWheel::set_from_xy_delta(double const dx, double const dy) +// { +// auto [mx, my] = get_marker_point(index); +// mx += dx; +// my += dy; +// return _set_from_xy(mx, my); +// } bool MultiMarkerWheel::_is_in_ring(double x, double y) { @@ -1009,7 +1044,7 @@ bool MultiMarkerWheel::_is_in_ring(double x, double y) return r2 < r2_max; } -void MultiMarkerWheel::_update_ring_color(double x, double y) +void MultiMarkerWheel::_update_ring_color(double x, double y , int index) { auto const [width, height] = *_cache_size; double cx = width / 2.0; @@ -1029,16 +1064,16 @@ void MultiMarkerWheel::_update_ring_color(double x, double y) bool changed = false; - if (_values.set(0, angle)) { + if (_values_vector[index].set(0, angle)) { changed = true; } - if (_values.set(1, saturation)) { + if (_values_vector[index].set(1, saturation)) { changed = true; } if (changed) { - _marker_point.reset(); + _markers_points[index].reset(); color_changed(); } } @@ -1047,12 +1082,14 @@ Gtk::EventSequenceState MultiMarkerWheel::on_click_pressed(Gtk::GestureClick con double x, double y) { if (_is_in_ring(x, y)) { - std::cout<<"in ring true \n"; _adjusting = true; _mode = DragMode::HUE; focus_drawing_area(); _focus_on_ring = true; - _update_ring_color(x, y); + int index = _get_marker_position(x,y); + if(index >= 0) + _active_index = index; + _update_ring_color(x, y,_active_index); return Gtk::EventSequenceState::CLAIMED; } @@ -1079,7 +1116,7 @@ void MultiMarkerWheel::on_motion(Gtk::EventControllerMotion const &motion, doubl } if (_mode == DragMode::HUE) { - _update_ring_color(x, y); + _update_ring_color(x, y , _active_index); } else if (_mode == DragMode::SATURATION_VALUE) { _set_from_xy(x, y); } @@ -1117,15 +1154,15 @@ bool MultiMarkerWheel::on_key_pressed(unsigned keyval, unsigned /*keycode*/, Gdk bool changed = false; if (_focus_on_ring) { - changed = _values.set(0, _values[0] - ((dx != 0 ? dx : dy) * delta_hue)); - changed = _values.set(1, _values[1] - ((dy != 0 ? dy : dx) * delta_sat)); + changed = _values_vector[_active_index].set(0, _values_vector[_active_index][0] - ((dx != 0 ? dx : dy) * delta_hue)); + changed = _values_vector[_active_index].set(1, _values_vector[_active_index][1] - ((dy != 0 ? dy : dx) * delta_sat)); } - _values.normalize(); + _values_vector[_active_index].normalize(); if (changed) { - _marker_point.reset(); + _markers_points[_active_index].reset(); color_changed(); } @@ -1148,25 +1185,33 @@ MultiMarkerWheel::MinMax const &MultiMarkerWheel::get_radii() return *_radii; } -Geom::Point const &MultiMarkerWheel::get_marker_point() +Geom::Point const &MultiMarkerWheel::get_marker_point(int index) { - if (_marker_point) - return *_marker_point; + if (index < 0 || index >= _values_vector.size()) { + static Geom::Point default_point{0, 0}; + return default_point; + } + + if (index >= _markers_points.size()) { + _markers_points.resize(_values_vector.size()); + } + + if (_markers_points[index]) + return *_markers_points[index]; auto const [width, height] = *_cache_size; auto const cx = width / 2.0; auto const cy = height / 2.0; auto const&[r_min,r_max] = get_radii(); - double hue = _values[0]; - double saturation = _values[1]; - + double hue = _values_vector[index][0]; + double saturation = _values_vector[index][1]; std::cout<<"hue : "< const &builder); bool setColor(Colors::Color const &color, bool overrideHue = true, bool emit = true) override; - bool setColor(std::vector const &color, bool overrideHue = true, bool emit = true); + bool setColor(std::vector const &color); + Colors::Color getColor() const override + { + if (!_values_vector.empty() && _active_index >= 0 && _active_index < _values_vector.size()) + return _values_vector[_active_index]; + else + return Colors::Color(0x00000000); + } private: void on_drawing_area_size(int width, int height, int baseline) override; @@ -246,7 +253,11 @@ private: bool _set_from_xy(double x, double y); bool set_from_xy_delta(double dx, double dy); bool _is_in_ring(double x, double y); - void _update_ring_color(double x, double y); + void _update_ring_color(double x, double y , int index); + void _reset_markers(); + void _draw_line_2_marker(Cairo::RefPtr const &cr , double mx, double my ,double cx, double cy , Colors::Color value , int index); + void _draw_marker(Cairo::RefPtr const &cr,Colors::Color value , int index); + int _get_marker_position(double x , double y); enum class DragMode { @@ -267,17 +278,18 @@ private: // caches to speed up drawing using MinMax = std::array; - using MarkerPoints = std::vector; + using MarkerPoints = std::vector>; std::vector _values_vector; std::optional _cache_size; std::optional _radii; std::optional _marker_point; - std::optional _markers_points; + MarkerPoints _markers_points; std::vector _buffer_ring; Cairo::RefPtr _source_ring; [[nodiscard]] MinMax const &get_radii(); - [[nodiscard]] Geom::Point const &get_marker_point(); + [[nodiscard]] Geom::Point const &get_marker_point(int index); int _active_index = 0; + static constexpr double marker_click_tolerance = 10.0; void update_ring_source(); }; diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index d0146045d8..f34e7879d1 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -62,7 +62,7 @@ RecolorArt::RecolorArt() : Gtk::Box() , _notebook(*_builder->get_widget("list-wheel-box")) , _color_wheel_page(*_builder->get_widget("color-wheel-page")) - , _color_wheel(new MultiMarkerWheel()) + , _color_wheel(Gtk::make_managed()) ,_color_list(*_builder->get_widget("colors-list")) ,_reset(*_builder->get_widget("reset")) ,_live_preview(*_builder->get_widget("liveP")) @@ -340,6 +340,7 @@ void RecolorArt::populateMap(Color color, SPObject *item, std::string kind) if (_selected_colors.count(color.toString())) { _selected_colors[color.toString(true)].first.push_back(ref); } else { + colors.push_back(color); _selected_colors.emplace(color.toString(), std::make_pair(std::vector{ref}, pair)); } } @@ -739,6 +740,7 @@ void RecolorArt::performUpdate() _color_list.remove(*child); } buttons.clear(); + colors.clear(); _gradient_stops.clear(); _selected_colors.clear(); _desktop = SP_ACTIVE_DESKTOP; @@ -751,6 +753,8 @@ void RecolorArt::performUpdate() _paint_selector->set_change_selection(false); std::vector vec(selection->items().begin(), selection->items().end()); collectColors(vec); + if(!colors.empty()) + _color_wheel->setColor(colors); if (!_selected_colors.empty()) { generateVisualList(); auto first_button_id = buttons.begin()->first; diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index a52ab7a222..cd732d9a58 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -105,6 +105,7 @@ private: MultiMarkerWheel *_color_wheel = nullptr; + std::vector colors; Gtk::Button* _dummie_color_wheel_button = nullptr; -- GitLab From 6898f9ba83b93f8f4f567a9767b7bcb2882c430e Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 24 Jul 2025 08:59:58 +0300 Subject: [PATCH 076/122] colorwheel changes objects colors --- src/ui/widget/ink-color-wheel.h | 7 +++++++ src/ui/widget/recolor-art.cpp | 25 +++++++++++++++++-------- src/ui/widget/recolor-art.h | 4 ++-- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/ui/widget/ink-color-wheel.h b/src/ui/widget/ink-color-wheel.h index 621bcd2b8e..d93d91f8f8 100644 --- a/src/ui/widget/ink-color-wheel.h +++ b/src/ui/widget/ink-color-wheel.h @@ -244,6 +244,13 @@ public: else return Colors::Color(0x00000000); } + int getActiveIndex() + { + if (!_values_vector.empty() && _active_index >= 0 && _active_index < _values_vector.size()) + return _active_index; + else + return -1; + } private: void on_drawing_area_size(int width, int height, int baseline) override; diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index f34e7879d1..f334ac5a43 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -87,6 +87,11 @@ RecolorArt::RecolorArt() context->add_provider(css_provider, GTK_STYLE_PROVIDER_PRIORITY_USER); context->add_class("color-preview"); std::cout << "button color : " << c.toString(true) << std::endl; + if (_color_wheel->getActiveIndex() != -1) { + int index = _color_wheel->getActiveIndex(); + _current_color_id = colors[index].toString(true); + onColorPickerChanged(c, true); + } })); _notebook.signal_switch_page().connect([this](Gtk::Widget *page, guint page_num) { int wheel_index = _notebook.page_num(_color_wheel_page); @@ -433,7 +438,8 @@ void RecolorArt::layoutColorPicker(std::shared_ptr updated_col { _solid_color_changed.disconnect(); } - _solid_color_changed = _solid_colors->signal_changed.connect(sigc::mem_fun(*this, &RecolorArt::onColorPickerChanged)); + _solid_color_changed = + _solid_colors->signal_changed.connect([this]() { onColorPickerChanged(); }); auto container = _builder->get_widget("color-picker"); if (container) { @@ -534,7 +540,7 @@ void RecolorArt::onOriginalColorClicked(std::string color_id) layoutColorPicker(updated_color); } } -void RecolorArt::onColorPickerChanged() +void RecolorArt::onColorPickerChanged(Color color, bool wheel) { auto it = buttons.find(_current_color_id); if (it == buttons.end()) { @@ -542,7 +548,7 @@ void RecolorArt::onColorPickerChanged() return; } Gtk::Box *_current_recolor_button = it->second.second; - std::optional new_color = _solid_colors->get(); + std::optional new_color = wheel ? color : _solid_colors->get(); if (!new_color.has_value()) { g_message("there is no color"); return; @@ -553,7 +559,10 @@ void RecolorArt::onColorPickerChanged() if (_selected != _selected_colors.end()) _selected->second.second.value().new_color = new_color.value(); if (_live_preview.property_active()) { - lpChecked(); + if (wheel) + lpChecked(color, wheel); + else + lpChecked(); } guint index = _selection_model->get_selected(); auto item = _color_model->get_item(index); @@ -561,10 +570,10 @@ void RecolorArt::onColorPickerChanged() color_item->new_color = new_color.value(); // g_message("color picker changed"); } -void RecolorArt::lpChecked() +void RecolorArt::lpChecked(Color color, bool wheel) { auto _selected = _selected_colors.find(_current_color_id); - std::optional new_color = _solid_colors->get(); + std::optional new_color = wheel ? color : _solid_colors->get(); if (!new_color.has_value()) { g_message("there is no color"); return; @@ -753,8 +762,8 @@ void RecolorArt::performUpdate() _paint_selector->set_change_selection(false); std::vector vec(selection->items().begin(), selection->items().end()); collectColors(vec); - if(!colors.empty()) - _color_wheel->setColor(colors); + if (!colors.empty()) + _color_wheel->setColor(colors); if (!_selected_colors.empty()) { generateVisualList(); auto first_button_id = buttons.begin()->first; diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index cd732d9a58..609cbb7512 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -127,9 +127,9 @@ private: // signals handelrs void onOriginalColorClicked(std::string color_id); void onResetClicked(); - void onColorPickerChanged(); + void onColorPickerChanged(Color color=Color(0x00000000) , bool wheel = false); void onLivePreviewToggled(); - void lpChecked(); + void lpChecked(Color color=Color(0x00000000) , bool wheel = false); void revertToOriginalColors(bool is_reset_clicked = false); void convertToRecoloredColors(); // void _onApplyButtonClicked(); -- GitLab From c6d1e902f9c0e1841e3ce3e96aad3ac10cb56c49 Mon Sep 17 00:00:00 2001 From: ftomara Date: Fri, 25 Jul 2025 17:05:11 +0300 Subject: [PATCH 077/122] added on hover effect to color wheel --- share/ui/recolor-art.glade | 10 ++----- src/ui/widget/ink-color-wheel.cpp | 47 +++++++++++++++++++++++++++---- src/ui/widget/ink-color-wheel.h | 15 ++++++++-- src/ui/widget/recolor-art.cpp | 13 +++++++++ 4 files changed, 71 insertions(+), 14 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 938809a7a8..2fa8149db5 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -22,6 +22,7 @@ original-reset-recolor 3 + none Original @@ -35,7 +36,7 @@ false false center - 18 + 32 reset-settings @@ -59,6 +60,7 @@ true never false + 240 colors-list @@ -108,12 +110,6 @@ vertical true true - - - - Color Wheel Content Goes Here - - diff --git a/src/ui/widget/ink-color-wheel.cpp b/src/ui/widget/ink-color-wheel.cpp index 43156a7945..82ae7649f1 100644 --- a/src/ui/widget/ink-color-wheel.cpp +++ b/src/ui/widget/ink-color-wheel.cpp @@ -27,6 +27,7 @@ #include "ui/widget/bin.h" #include "util/drawing-utils.h" #include "util/theme-utils.h" +#include "ink-color-wheel.h" using namespace Inkscape::Colors; using Inkscape::Colors::Space::Luv; @@ -805,7 +806,12 @@ void MultiMarkerWheel::_draw_marker(Cairo::RefPtr const &cr , Co double a = luminance(color_on_ring) < 0.5 ? 1.0 : 0.0; cr->set_source_rgb(a, a, a); cr->begin_new_path(); - cr->arc(mx, my, marker_radius, 0, 2 * M_PI); + if (index == _hover_index) { + cr->arc(mx, my, marker_radius+2, 0, 2 * M_PI); + } + else{ + cr->arc(mx, my, marker_radius, 0, 2 * M_PI); + } cr->stroke(); // Draw focus @@ -861,6 +867,9 @@ void MultiMarkerWheel::_draw_line_2_marker(Cairo::RefPtr const & cr->set_dash(focus_dash, 0); cr->set_line_width(1.0); } + if (index == _hover_index) { + cr->set_dash(std::valarray(), 0); + } cr->stroke(); cr->restore(); } @@ -1105,6 +1114,7 @@ Gtk::EventSequenceState MultiMarkerWheel::on_click_released(int /*n_press*/, dou void MultiMarkerWheel::on_motion(Gtk::EventControllerMotion const &motion, double x, double y) { + std::cout<<"on motion \n"; if (!_adjusting) return; auto state = motion.get_current_event_state(); @@ -1115,13 +1125,40 @@ void MultiMarkerWheel::on_motion(Gtk::EventControllerMotion const &motion, doubl return; } - if (_mode == DragMode::HUE) { - _update_ring_color(x, y , _active_index); - } else if (_mode == DragMode::SATURATION_VALUE) { - _set_from_xy(x, y); + if (_mode == DragMode::HUE || _mode == DragMode::SATURATION_VALUE) { + _update_ring_color(x, y, _active_index); } } +void MultiMarkerWheel::_on_motion(Gtk::EventControllerMotion const &motion, double x, double y) +{ + if (!_adjusting) { + int hover_index = _get_marker_position(x, y); + _signal_color_hovered.emit(); + if (_hover_index != hover_index) { + _hover_index = hover_index; + if (hover_index >= 0 && hover_index < _values_vector.size()) + { + std::cout << "hover color : " << _values_vector[hover_index].toString() << std::endl; + queue_drawing_area_draw(); + } + else + { + std::cout << "invalid index : " << hover_index << std::endl; + } + } + return; + } + + auto state = motion.get_current_event_state(); + if (!Controller::has_flag(state, Gdk::ModifierType::BUTTON1_MASK)) { + // lost button release event + on_click_released(0, x, y); + return; + } + + on_motion(motion, x, y); +} bool MultiMarkerWheel::on_key_pressed(unsigned keyval, unsigned /*keycode*/, Gdk::ModifierType state) { static constexpr double delta_hue = 2.0 / MAX_HUE; diff --git a/src/ui/widget/ink-color-wheel.h b/src/ui/widget/ink-color-wheel.h index d93d91f8f8..7a71625e97 100644 --- a/src/ui/widget/ink-color-wheel.h +++ b/src/ui/widget/ink-color-wheel.h @@ -113,7 +113,7 @@ private: virtual Gtk::EventSequenceState on_click_released(int n_press, double x, double y) = 0; virtual void on_motion(Gtk::EventControllerMotion const &motion, double x, double y) = 0; - void _on_motion(Gtk::EventControllerMotion const &motion, double x, double y); + virtual void _on_motion(Gtk::EventControllerMotion const &motion, double x, double y); virtual bool on_key_pressed(unsigned keyval, unsigned keycode, Gdk::ModifierType state) { @@ -251,6 +251,14 @@ public: else return -1; } + int getHoverIndex() + { + if (!_values_vector.empty() && _hover_index >= 0 && _hover_index < _values_vector.size()) + return _hover_index; + else + return -1; + } + sigc::connection connect_color_hovered(sigc::slot slot) { return _signal_color_hovered.connect(std::move(slot)); } private: void on_drawing_area_size(int width, int height, int baseline) override; @@ -281,6 +289,7 @@ private: double y) final; Gtk::EventSequenceState on_click_released(int n_press, double x, double y) final; void on_motion(Gtk::EventControllerMotion const &motion, double x, double y) final; + void _on_motion(Gtk::EventControllerMotion const &motion, double x, double y) override ; bool on_key_pressed(unsigned keyval, unsigned keycode, Gdk::ModifierType state) final; // caches to speed up drawing @@ -296,7 +305,9 @@ private: [[nodiscard]] MinMax const &get_radii(); [[nodiscard]] Geom::Point const &get_marker_point(int index); int _active_index = 0; - static constexpr double marker_click_tolerance = 10.0; + int _hover_index = -1; + static constexpr double marker_click_tolerance = 5.0; + sigc::signal _signal_color_hovered; void update_ring_source(); }; diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index f334ac5a43..b987efb4c7 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -93,6 +93,19 @@ RecolorArt::RecolorArt() onColorPickerChanged(c, true); } })); + + _color_wheel->connect_color_hovered(static_cast>([this]() { + uint32_t cc = _color_wheel->getColor().toRGBA(); + Color c(cc,true); + if (_color_wheel->getHoverIndex() != -1) { + int index = _color_wheel->getHoverIndex(); + _current_color_id = colors[index].toString(true); + getSelection(_current_color_id); + } + else + resetOpacity(); + })); + _notebook.signal_switch_page().connect([this](Gtk::Widget *page, guint page_num) { int wheel_index = _notebook.page_num(_color_wheel_page); -- GitLab From 0114174a9de735e88fed5a95f3598e6ae10e14f8 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sat, 26 Jul 2025 11:11:43 +0300 Subject: [PATCH 078/122] fixed onhover resetopacity on draging --- src/ui/widget/ink-color-wheel.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ui/widget/ink-color-wheel.cpp b/src/ui/widget/ink-color-wheel.cpp index 82ae7649f1..a56a332478 100644 --- a/src/ui/widget/ink-color-wheel.cpp +++ b/src/ui/widget/ink-color-wheel.cpp @@ -855,8 +855,9 @@ void MultiMarkerWheel::_draw_line_2_marker(Cairo::RefPtr const & dx /= len; dy /= len; } - double tx = mx - dx * marker_radius; - double ty = my - dy * marker_radius; + double mr = index == _hover_index ? marker_radius+2 : marker_radius; + double tx = mx - dx * mr; + double ty = my - dy * mr; double l = luminance(color_on_ring) < 0.5 ? 1.0 : 0.0; cr->save(); cr->set_source_rgb(l, l, l); @@ -1126,6 +1127,8 @@ void MultiMarkerWheel::on_motion(Gtk::EventControllerMotion const &motion, doubl } if (_mode == DragMode::HUE || _mode == DragMode::SATURATION_VALUE) { + _hover_index = -1; + _signal_color_hovered.emit(); _update_ring_color(x, y, _active_index); } } -- GitLab From ccd44a71381cc3ee4237f778be65be5a99b1f425 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 27 Jul 2025 13:14:01 +0300 Subject: [PATCH 079/122] managed coloing buttons with liststore instead of the buttons map approch --- src/ui/widget/color-preview.cpp | 5 ---- src/ui/widget/color-preview.h | 1 - src/ui/widget/recolor-art.cpp | 48 +++++++++------------------------ src/ui/widget/recolor-art.h | 5 ++-- 4 files changed, 14 insertions(+), 45 deletions(-) diff --git a/src/ui/widget/color-preview.cpp b/src/ui/widget/color-preview.cpp index 1eae4a0500..ecf80c0255 100644 --- a/src/ui/widget/color-preview.cpp +++ b/src/ui/widget/color-preview.cpp @@ -49,11 +49,6 @@ void ColorPreview::setRgba32(std::uint32_t const rgba) { _gradient.clear(); queue_draw(); } - -std::uint32_t ColorPreview::getRgba32() -{ - return _rgba; -} void ColorPreview::setPattern(Cairo::RefPtr pattern) { if (_pattern == pattern) return; diff --git a/src/ui/widget/color-preview.h b/src/ui/widget/color-preview.h index 88b561ca06..b8016aeca1 100644 --- a/src/ui/widget/color-preview.h +++ b/src/ui/widget/color-preview.h @@ -47,7 +47,6 @@ public: ColorPreview(BaseObjectType* cobject, const Glib::RefPtr& builder); // set preview color RGBA with opacity (alpha) void setRgba32(std::uint32_t rgba); - std::uint32_t getRgba32(); // set arbitrary pattern-based preview void setPattern(Cairo::RefPtr pattern); // simple color patch vs outlined color patch diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index b987efb4c7..a088445e1b 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -222,7 +222,6 @@ RecolorArt::RecolorArt() original->add_controller(original_click); recolored->add_controller(recolored_click); - buttons[item->key] = {original, recolored}; } }); @@ -431,7 +430,6 @@ void RecolorArt::extractMarkerColors(Glib::ustring marker, SPObject *item) void RecolorArt::generateVisualList() { _color_model->remove_all(); - buttons.clear(); for (auto &[key, value] : _selected_colors) { auto old_color = value.second.value().old_color; auto new_color = value.second.value().new_color; @@ -475,20 +473,6 @@ void RecolorArt::colorButtons(Gtk::Box *button, Color color, bool is_original) child->setRgba32(rgba); } } - // if (color.empty() || color.size() < 7 || color[0] != '#') { - // g_warning("Invalid color string: %s", color.c_str()); - // return; - // } - - // if (button) { - // auto css_provider = Gtk::CssProvider::create(); - // Glib::ustring css = "box { background-color: " + Glib::ustring(color) + "; background-image: none;}"; - // css_provider->load_from_data(css); - // auto style_context = button->get_style_context(); - // style_context->add_provider(css_provider, GTK_STYLE_PROVIDER_PRIORITY_USER); - // } else { - // g_message("button not found"); - // } } void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) { @@ -545,8 +529,7 @@ void RecolorArt::onOriginalColorClicked(std::string color_id) { _current_color_id = color_id; auto it = _selected_colors.find(color_id); - auto btns = buttons.find(color_id); - if (it != _selected_colors.end() && it->second.second.has_value() && btns != buttons.end()) { + if (it != _selected_colors.end() && it->second.second.has_value()) { Color color = it->second.second.value().new_color; std::shared_ptr updated_color = std::make_shared(); updated_color->set(color); @@ -555,19 +538,12 @@ void RecolorArt::onOriginalColorClicked(std::string color_id) } void RecolorArt::onColorPickerChanged(Color color, bool wheel) { - auto it = buttons.find(_current_color_id); - if (it == buttons.end()) { - g_message("couldn't find the color id \" %s \" ", _current_color_id.c_str()); - return; - } - Gtk::Box *_current_recolor_button = it->second.second; std::optional new_color = wheel ? color : _solid_colors->get(); if (!new_color.has_value()) { g_message("there is no color"); return; } std::string _color_string = new_color.value().toString(); - colorButtons(_current_recolor_button, new_color.value()); auto _selected = _selected_colors.find(_current_color_id); if (_selected != _selected_colors.end()) _selected->second.second.value().new_color = new_color.value(); @@ -579,8 +555,13 @@ void RecolorArt::onColorPickerChanged(Color color, bool wheel) } guint index = _selection_model->get_selected(); auto item = _color_model->get_item(index); + if (!item) { + g_message("ERROR: item is null"); + return; + } auto color_item = std::dynamic_pointer_cast(item); - color_item->new_color = new_color.value(); + auto new_item = ColorItem::create(color_item->key,color_item->old_color,new_color.value()); + _color_model->splice(index,1,{new_item}); // g_message("color picker changed"); } void RecolorArt::lpChecked(Color color, bool wheel) @@ -616,19 +597,14 @@ void RecolorArt::lpChecked(Color color, bool wheel) } void RecolorArt::onResetClicked() { - for (auto [key, btns] : buttons) { - std::uint32_t rgba = - dynamic_cast(dynamic_cast(btns.first->get_first_child())->get_child()) - ->getRgba32(); - Color color(rgba); - colorButtons(btns.second, color); - } - + std::vector>new_colors; for (auto i = 0; i < _color_model->get_n_items(); i++) { auto item = _color_model->get_item(i); auto color_item = std::dynamic_pointer_cast(item); - color_item->new_color = color_item->old_color; + auto new_item = ColorItem::create(color_item->key,color_item->old_color,color_item->old_color); + new_colors.push_back(new_item); } + _color_model->splice(0,_color_model->get_n_items(),new_colors); revertToOriginalColors(true); guint index = _selection_model->get_selected(); auto item = _color_model->get_item(index); @@ -779,7 +755,7 @@ void RecolorArt::performUpdate() _color_wheel->setColor(colors); if (!_selected_colors.empty()) { generateVisualList(); - auto first_button_id = buttons.begin()->first; + auto first_button_id = _selected_colors.begin()->first; onOriginalColorClicked(first_button_id); } g_message("Performing Update\n"); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 609cbb7512..9c03eb5542 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -63,11 +63,11 @@ struct ColorPair struct ColorItem : public Glib::Object { - Glib::ustring key; + std::string key; Color old_color = Color(0x00000000); Color new_color = Color(0x00000000); - static Glib::RefPtr create(Glib::ustring const &k, Color const &old_c, Color const &new_c) + static Glib::RefPtr create(std::string const& k, Color const& old_c, Color const& new_c) { auto item = Glib::make_refptr_for_instance(new ColorItem()); item->key = k; @@ -93,7 +93,6 @@ private: Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr ; Gtk::ListView *_list_view = nullptr; std::string _current_color_id; - std::map> buttons; // color_id : {original , recolored} std::map _type_boxes; bool _is_preview = false; -- GitLab From 6b5505d79fd7dd06ab88663220a8f29146bf9898 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 27 Jul 2025 14:46:37 +0300 Subject: [PATCH 080/122] synced wheel to list (not vice versa yet) --- src/ui/widget/recolor-art.cpp | 20 +++++++++++++++++++- src/ui/widget/recolor-art.h | 3 +++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index a088445e1b..3072934db1 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -525,6 +525,17 @@ void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) } } } +std::pair, guint> RecolorArt::findColorItemByKey(std::string const &key) +{ + for (auto i = 0; i < _color_model->get_n_items(); i++) { + auto item = _color_model->get_item(i); + auto color_item = std::dynamic_pointer_cast(item); + if (key == color_item->key) { + return {item, i}; + } + } + return {nullptr, -1}; +} void RecolorArt::onOriginalColorClicked(std::string color_id) { _current_color_id = color_id; @@ -554,7 +565,14 @@ void RecolorArt::onColorPickerChanged(Color color, bool wheel) lpChecked(); } guint index = _selection_model->get_selected(); - auto item = _color_model->get_item(index); + Glib::RefPtr item = nullptr; + if (!wheel) + item = _color_model->get_item(index); + else { + auto item_index = findColorItemByKey(_current_color_id); + item = item_index.first; + index = item_index.second; + } if (!item) { g_message("ERROR: item is null"); return; diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 9c03eb5542..18f7334745 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -141,6 +141,9 @@ private: void setUpTypeBox(Gtk::Box *box, Color color); + std::pair,guint> findColorItemByKey(const std::string& key); + + public: RecolorArt(); ~RecolorArt(); -- GitLab From 9e6707da6d10172a0ae3dfb0618bcb00d01eb9f0 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 27 Jul 2025 16:32:57 +0300 Subject: [PATCH 081/122] synced list to wheel and vice versa this time --- src/ui/widget/ink-color-wheel.cpp | 21 +++++++++++++++++++++ src/ui/widget/ink-color-wheel.h | 1 + src/ui/widget/recolor-art.cpp | 21 ++++++++++++++------- src/ui/widget/recolor-art.h | 3 +++ 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/ui/widget/ink-color-wheel.cpp b/src/ui/widget/ink-color-wheel.cpp index a56a332478..c04deb3bd7 100644 --- a/src/ui/widget/ink-color-wheel.cpp +++ b/src/ui/widget/ink-color-wheel.cpp @@ -920,6 +920,27 @@ void MultiMarkerWheel::update_ring_source() _source_ring = Cairo::ImageSurface::create(data, Cairo::Surface::Format::RGB24, width, height, stride); } +bool MultiMarkerWheel::changeColor(int index, Colors::Color& color) +{ + if(index >=0 && index < _values_vector.size()) + { + // std::cout<<" index : "< slot) { return _signal_color_hovered.connect(std::move(slot)); } private: diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 3072934db1..5452a5534d 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -75,6 +75,7 @@ RecolorArt::RecolorArt() _color_wheel_page.append(*_color_wheel); _color_wheel_page.append(*_dummie_color_wheel_button); _color_wheel->connect_color_changed(static_cast>([this]() { + if(_is_updating) return; auto css_provider = Gtk::CssProvider::create(); uint32_t cc = _color_wheel->getColor().toRGBA(); Color c(cc,true); @@ -354,11 +355,13 @@ void RecolorArt::populateMap(Color color, SPObject *item, std::string kind) color.addOpacity(); ColorRef ref = ColorRef(item, kind); ColorPair pair = ColorPair(color, color); - if (_selected_colors.count(color.toString())) { - _selected_colors[color.toString(true)].first.push_back(ref); + std::string color_string = color.toString(true); + if (_selected_colors.count(color_string)) { + _selected_colors[color_string].first.push_back(ref); } else { colors.push_back(color); - _selected_colors.emplace(color.toString(), std::make_pair(std::vector{ref}, pair)); + color_wheel_colors_map[color_string]=colors.size()-1; + _selected_colors.emplace(color_string, std::make_pair(std::vector{ref}, pair)); } } void RecolorArt::extractItemStyle(SPObject *item, std::string kind) @@ -566,8 +569,12 @@ void RecolorArt::onColorPickerChanged(Color color, bool wheel) } guint index = _selection_model->get_selected(); Glib::RefPtr item = nullptr; - if (!wheel) + if (!wheel){ item = _color_model->get_item(index); + int i = color_wheel_colors_map[_current_color_id]; + _is_updating = true; + _color_wheel->changeColor(i,new_color.value()); + } else { auto item_index = findColorItemByKey(_current_color_id); item = item_index.first; @@ -578,8 +585,9 @@ void RecolorArt::onColorPickerChanged(Color color, bool wheel) return; } auto color_item = std::dynamic_pointer_cast(item); - auto new_item = ColorItem::create(color_item->key,color_item->old_color,new_color.value()); - _color_model->splice(index,1,{new_item}); + auto new_item = ColorItem::create(color_item->key, color_item->old_color, new_color.value()); + _color_model->splice(index, 1, {new_item}); + _is_updating = false; // g_message("color picker changed"); } void RecolorArt::lpChecked(Color color, bool wheel) @@ -755,7 +763,6 @@ void RecolorArt::performUpdate() for (auto child : _color_list.get_children()) { _color_list.remove(*child); } - buttons.clear(); colors.clear(); _gradient_stops.clear(); _selected_colors.clear(); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 18f7334745..ae61b80dcd 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -105,6 +105,9 @@ private: MultiMarkerWheel *_color_wheel = nullptr; std::vector colors; + std::mapcolor_wheel_colors_map; + int colors_index=0; + bool _is_updating = false; Gtk::Button* _dummie_color_wheel_button = nullptr; -- GitLab From d99991b076372a9244908c069e7b9c4652b59463 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 27 Jul 2025 17:58:35 +0300 Subject: [PATCH 082/122] synced active index in wheel with selected raw in list --- src/ui/widget/ink-color-wheel.h | 8 ++++++++ src/ui/widget/recolor-art.cpp | 11 +++++++++-- src/ui/widget/recolor-art.h | 1 + 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/ui/widget/ink-color-wheel.h b/src/ui/widget/ink-color-wheel.h index bd3b6a4150..1a0bc0cc25 100644 --- a/src/ui/widget/ink-color-wheel.h +++ b/src/ui/widget/ink-color-wheel.h @@ -244,6 +244,14 @@ public: else return Colors::Color(0x00000000); } + bool setActiveIndex(int index) + { + if (!_values_vector.empty() && index >= 0 && index < _values_vector.size()) { + _active_index = index; + return true; + } else + return false; + } int getActiveIndex() { if (!_values_vector.empty() && _active_index >= 0 && _active_index < _values_vector.size()) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 5452a5534d..6049255641 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -92,6 +92,7 @@ RecolorArt::RecolorArt() int index = _color_wheel->getActiveIndex(); _current_color_id = colors[index].toString(true); onColorPickerChanged(c, true); + onOriginalColorClicked(_current_color_id); } })); @@ -111,11 +112,11 @@ RecolorArt::RecolorArt() int wheel_index = _notebook.page_num(_color_wheel_page); if (static_cast(page_num) == wheel_index) { + _is_wheel_page = true; _color_picker_wdgt->set_visible(false); - // std::cout << "Color Wheel tab is active.\n"; } else { + _is_wheel_page = false; _color_picker_wdgt->set_visible(true); - // std::cout << "Color Wheel tab is NOT active.\n"; } }); @@ -460,6 +461,10 @@ void RecolorArt::layoutColorPicker(std::shared_ptr updated_col for (auto child : container->get_children()) container->remove(*child); container->append(*_color_picker_wdgt); + if (_is_wheel_page) + _color_picker_wdgt->set_visible(false); + else + _color_picker_wdgt->set_visible(true); } else { g_warning("color picker not found"); } @@ -541,6 +546,8 @@ std::pair, guint> RecolorArt::findColorItemByKey(std::st } void RecolorArt::onOriginalColorClicked(std::string color_id) { + if (_color_wheel && !color_wheel_colors_map.empty()) + _color_wheel->setActiveIndex(color_wheel_colors_map[color_id]); _current_color_id = color_id; auto it = _selected_colors.find(color_id); if (it != _selected_colors.end() && it->second.second.has_value()) { diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index ae61b80dcd..843a79b5e2 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -108,6 +108,7 @@ private: std::mapcolor_wheel_colors_map; int colors_index=0; bool _is_updating = false; + bool _is_wheel_page = false; Gtk::Button* _dummie_color_wheel_button = nullptr; -- GitLab From 784a2d690c04a69c00593ff7bb5bf8a66965fed2 Mon Sep 17 00:00:00 2001 From: ftomara Date: Mon, 4 Aug 2025 19:20:28 +0300 Subject: [PATCH 083/122] added locking hue feature logic --- src/ui/widget/ink-color-wheel.cpp | 41 ++++++++++++++++++++++++++++--- src/ui/widget/ink-color-wheel.h | 9 ++++++- src/ui/widget/recolor-art.cpp | 29 +++++++++++++++++++++- src/ui/widget/recolor-art.h | 2 ++ 4 files changed, 76 insertions(+), 5 deletions(-) diff --git a/src/ui/widget/ink-color-wheel.cpp b/src/ui/widget/ink-color-wheel.cpp index c04deb3bd7..f83ad68e54 100644 --- a/src/ui/widget/ink-color-wheel.cpp +++ b/src/ui/widget/ink-color-wheel.cpp @@ -828,7 +828,7 @@ void MultiMarkerWheel::_draw_marker(Cairo::RefPtr const &cr , Co cr->stroke(); } } -int MultiMarkerWheel::_get_marker_position(double x, double y) +int MultiMarkerWheel::_get_marker_index(double x, double y) { for(int i =0 ; i<_values_vector.size();i++) { @@ -841,6 +841,24 @@ int MultiMarkerWheel::_get_marker_position(double x, double y) } return -1; } +void MultiMarkerWheel::_update_hue_lock_positions() +{ + if (_hue_lock) { + std::vector delat_angles; + auto active_hue = _values_vector[_active_index][0]; + for (int i = 0; i < _values_vector.size(); i++) { + if (i == _active_index) { + delat_angles.push_back(0.0); + continue; + } + auto delta_hue = _values_vector[i][0] - active_hue; + if (delta_hue > 0.5) delta_hue -= 1.0; + if (delta_hue < -0.5) delta_hue += 1.0; + delat_angles.push_back(delta_hue); + } + _relative_hue_angles = delat_angles; +} +} void MultiMarkerWheel::_draw_line_2_marker(Cairo::RefPtr const &cr, double mx, double my, double cx, double cy, Colors::Color value , int index) { @@ -1117,9 +1135,10 @@ Gtk::EventSequenceState MultiMarkerWheel::on_click_pressed(Gtk::GestureClick con _mode = DragMode::HUE; focus_drawing_area(); _focus_on_ring = true; - int index = _get_marker_position(x,y); + int index = _get_marker_index(x,y); if(index >= 0) _active_index = index; + _update_hue_lock_positions(); _update_ring_color(x, y,_active_index); return Gtk::EventSequenceState::CLAIMED; } @@ -1151,13 +1170,29 @@ void MultiMarkerWheel::on_motion(Gtk::EventControllerMotion const &motion, doubl _hover_index = -1; _signal_color_hovered.emit(); _update_ring_color(x, y, _active_index); + if (_hue_lock && !_relative_hue_angles.empty()) { + bool changed = false; + double hue = _values_vector[_active_index][0]; + for (int i = 0; i < _values_vector.size(); i++) { + if (i != _active_index) { + double new_hue = hue + _relative_hue_angles[i]; + new_hue = fmod(new_hue + 1.0, 1.0); + if (_values_vector[i].set(0, new_hue)) { + _markers_points[i].reset(); + changed = true; + std::cout<<"hue changed : "< slot) { return _signal_color_hovered.connect(std::move(slot)); } + void toggleHueLock(){_hue_lock = !_hue_lock ;} + bool getHueLock(){return _hue_lock;} + std::vector getColors(){return _values_vector ;} private: void on_drawing_area_size(int width, int height, int baseline) override; @@ -281,7 +284,9 @@ private: void _reset_markers(); void _draw_line_2_marker(Cairo::RefPtr const &cr , double mx, double my ,double cx, double cy , Colors::Color value , int index); void _draw_marker(Cairo::RefPtr const &cr,Colors::Color value , int index); - int _get_marker_position(double x , double y); + int _get_marker_index(double x , double y); + void _update_hue_lock_positions(); + enum class DragMode { @@ -315,6 +320,8 @@ private: [[nodiscard]] Geom::Point const &get_marker_point(int index); int _active_index = 0; int _hover_index = -1; + bool _hue_lock = 0; + std::vector_relative_hue_angles; static constexpr double marker_click_tolerance = 5.0; sigc::signal _signal_color_hovered; void update_ring_source(); diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 6049255641..90d686f412 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -67,12 +68,18 @@ RecolorArt::RecolorArt() ,_reset(*_builder->get_widget("reset")) ,_live_preview(*_builder->get_widget("liveP")) , _dummie_color_wheel_button(Gtk::make_managed()) + ,_hue_lock(*Gtk::make_managed()) { set_name("RecolorArt"); append(get_widget(_builder, "recolor-art")); signal_unmap().connect([&]() { resetOpacity(); }); _solid_colors->set(Color(0x000000ff)); + auto image = Gtk::make_managed(); + image->set_from_icon_name(INKSCAPE_ICON("shape-link")); + _hue_lock.set_child(*image); + _hue_lock.signal_toggled().connect([this](){_color_wheel->toggleHueLock();}); _color_wheel_page.append(*_color_wheel); + _color_wheel_page.append(_hue_lock); _color_wheel_page.append(*_dummie_color_wheel_button); _color_wheel->connect_color_changed(static_cast>([this]() { if(_is_updating) return; @@ -88,11 +95,31 @@ RecolorArt::RecolorArt() context->add_provider(css_provider, GTK_STYLE_PROVIDER_PRIORITY_USER); context->add_class("color-preview"); std::cout << "button color : " << c.toString(true) << std::endl; - if (_color_wheel->getActiveIndex() != -1) { + if(_color_wheel->getActiveIndex() != -1) { int index = _color_wheel->getActiveIndex(); _current_color_id = colors[index].toString(true); onColorPickerChanged(c, true); onOriginalColorClicked(_current_color_id); + if (_color_wheel->getHueLock()) { + if (_selected_colors.empty()) + return; + std::vector new_colors = _color_wheel->getColors(); + for(auto &[key,value] : _selected_colors) + { + int index = color_wheel_colors_map[key]; + value.second.value().new_color = new_colors[index]; + + } + std::vector>new_colors_buttons; + for (auto i = 0; i < _color_model->get_n_items(); i++) { + auto item = _color_model->get_item(i); + auto color_item = std::dynamic_pointer_cast(item); + auto new_item = ColorItem::create(color_item->key, color_item->old_color, new_colors[i]); + new_colors_buttons.push_back(new_item); + } + _color_model->splice(0, _color_model->get_n_items(), new_colors_buttons); + convertToRecoloredColors(); + } } })); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 843a79b5e2..b404a16ab1 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -89,6 +90,7 @@ private: std::map, std::optional>> _selected_colors; Gtk::Box &_color_list ; Gtk::Button &_reset; + Gtk::ToggleButton &_hue_lock; Gtk::CheckButton &_live_preview; Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr ; Gtk::ListView *_list_view = nullptr; -- GitLab From 5fcbc10b70e962bea068c582f7b871597c5f45bf Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 5 Aug 2025 13:49:07 +0300 Subject: [PATCH 084/122] refactored updating model colors , fixed reset syncing with the wheel --- src/ui/widget/recolor-art.cpp | 35 +++++++++++++++++------------------ src/ui/widget/recolor-art.h | 1 + 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 90d686f412..f81dfd0d76 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -107,17 +107,9 @@ RecolorArt::RecolorArt() for(auto &[key,value] : _selected_colors) { int index = color_wheel_colors_map[key]; - value.second.value().new_color = new_colors[index]; - + value.second.value().new_color = new_colors[index]; } - std::vector>new_colors_buttons; - for (auto i = 0; i < _color_model->get_n_items(); i++) { - auto item = _color_model->get_item(i); - auto color_item = std::dynamic_pointer_cast(item); - auto new_item = ColorItem::create(color_item->key, color_item->old_color, new_colors[i]); - new_colors_buttons.push_back(new_item); - } - _color_model->splice(0, _color_model->get_n_items(), new_colors_buttons); + updateColorModel(new_colors); convertToRecoloredColors(); } } @@ -657,14 +649,8 @@ void RecolorArt::lpChecked(Color color, bool wheel) } void RecolorArt::onResetClicked() { - std::vector>new_colors; - for (auto i = 0; i < _color_model->get_n_items(); i++) { - auto item = _color_model->get_item(i); - auto color_item = std::dynamic_pointer_cast(item); - auto new_item = ColorItem::create(color_item->key,color_item->old_color,color_item->old_color); - new_colors.push_back(new_item); - } - _color_model->splice(0,_color_model->get_n_items(),new_colors); + _color_wheel->setColor(colors); + updateColorModel(); revertToOriginalColors(true); guint index = _selection_model->get_selected(); auto item = _color_model->get_item(index); @@ -715,6 +701,19 @@ void RecolorArt::convertToRecoloredColors() } } } +void RecolorArt::updateColorModel(std::vector new_colors) +{ + std::vector> new_colors_buttons; + for (auto i = 0; i < _color_model->get_n_items(); i++) { + auto item = _color_model->get_item(i); + auto color_item = std::dynamic_pointer_cast(item); + int index = color_wheel_colors_map[color_item->key]; + auto new_item = ColorItem::create(color_item->key, color_item->old_color, + new_colors.empty() ? color_item->old_color : new_colors[index]); + new_colors_buttons.push_back(new_item); + } + _color_model->splice(0, _color_model->get_n_items(), new_colors_buttons); +} void RecolorArt::recolorStops(std::string old_color, Color new_color) { auto stops_vector = _gradient_stops.find(old_color); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index b404a16ab1..c473ca7f24 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -137,6 +137,7 @@ private: void lpChecked(Color color=Color(0x00000000) , bool wheel = false); void revertToOriginalColors(bool is_reset_clicked = false); void convertToRecoloredColors(); + void updateColorModel(std::vector new_colors = std::vector{}); // void _onApplyButtonClicked(); void populateStopsMap(SPStop *stop); -- GitLab From 5f3446384158914170063b20e5a82d9d886bb4fb Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 5 Aug 2025 13:59:00 +0300 Subject: [PATCH 085/122] fixed toggled huelock when reseting colors --- src/ui/widget/recolor-art.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index f81dfd0d76..0cf7c26931 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -649,6 +649,7 @@ void RecolorArt::lpChecked(Color color, bool wheel) } void RecolorArt::onResetClicked() { + if(!_color_wheel->getHueLock()) _color_wheel->toggleHueLock(); _color_wheel->setColor(colors); updateColorModel(); revertToOriginalColors(true); -- GitLab From b2362e82ce4316fce23f53fbad75bb2396b6bfd1 Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 5 Aug 2025 16:57:49 +0300 Subject: [PATCH 086/122] added almost correct lightness bar --- src/ui/widget/ink-color-wheel.cpp | 17 +++++++++++++++-- src/ui/widget/ink-color-wheel.h | 2 ++ src/ui/widget/recolor-art.cpp | 11 +++++++++++ src/ui/widget/recolor-art.h | 4 ++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/ui/widget/ink-color-wheel.cpp b/src/ui/widget/ink-color-wheel.cpp index f83ad68e54..d863cbdbdc 100644 --- a/src/ui/widget/ink-color-wheel.cpp +++ b/src/ui/widget/ink-color-wheel.cpp @@ -781,11 +781,13 @@ bool MultiMarkerWheel::setColor(std::vector const &color) { _values_vector.clear(); _markers_points.clear(); + _source_ring.reset(); for (auto c : color) { - if(!setColor(c)) return false; + if(!setColor(c,false,false)) return false; } _markers_points.resize(_values_vector.size()); _reset_markers(); + color_changed(); return true ; } void MultiMarkerWheel::_reset_markers() { @@ -929,7 +931,7 @@ void MultiMarkerWheel::update_ring_source() // double value = 1.0 - ((dy+(height/2.0))/height); // value = std::clamp(value,0.0,1.0); - *p++ = Color(Type::HSV, {hue, saturation,1.0}).toARGB(); + *p++ = Color(Type::HSV, {hue, saturation,lightness}).toARGB(); } } } @@ -959,6 +961,13 @@ bool MultiMarkerWheel::changeColor(int index, Colors::Color& color) return false; } +void MultiMarkerWheel::setLightness(double value) +{ + lightness = value/100.0; + _source_ring.reset(); + color_changed(); +} + void MultiMarkerWheel::on_drawing_area_size(int width, int height, int baseline) { auto const size = Geom::IntPoint{width, height}; @@ -1121,6 +1130,10 @@ void MultiMarkerWheel::_update_ring_color(double x, double y , int index) changed = true; } + if (_values_vector[index].set(2, lightness)) { + changed = true; + } + if (changed) { _markers_points[index].reset(); color_changed(); diff --git a/src/ui/widget/ink-color-wheel.h b/src/ui/widget/ink-color-wheel.h index 28d1d96e49..afad0b2e02 100644 --- a/src/ui/widget/ink-color-wheel.h +++ b/src/ui/widget/ink-color-wheel.h @@ -271,6 +271,7 @@ public: void toggleHueLock(){_hue_lock = !_hue_lock ;} bool getHueLock(){return _hue_lock;} std::vector getColors(){return _values_vector ;} + void setLightness(double value); private: void on_drawing_area_size(int width, int height, int baseline) override; @@ -324,6 +325,7 @@ private: std::vector_relative_hue_angles; static constexpr double marker_click_tolerance = 5.0; sigc::signal _signal_color_hovered; + double lightness = 1.0; void update_ring_source(); }; diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 0cf7c26931..620b1e988d 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -69,6 +69,7 @@ RecolorArt::RecolorArt() ,_live_preview(*_builder->get_widget("liveP")) , _dummie_color_wheel_button(Gtk::make_managed()) ,_hue_lock(*Gtk::make_managed()) + ,_lightness_bar(*Gtk::make_managed(adjustment,Gtk::Orientation::HORIZONTAL)) { set_name("RecolorArt"); append(get_widget(_builder, "recolor-art")); @@ -79,6 +80,15 @@ RecolorArt::RecolorArt() _hue_lock.set_child(*image); _hue_lock.signal_toggled().connect([this](){_color_wheel->toggleHueLock();}); _color_wheel_page.append(*_color_wheel); + + _lightness_bar.set_value_pos(Gtk::PositionType::RIGHT); // Show value to the right + _lightness_bar.set_draw_value(true); + _lightness_bar.signal_value_changed().connect([this](){ + double value = _lightness_bar.get_value(); + _color_wheel->setLightness(value); + }); + + _color_wheel_page.append(_lightness_bar); _color_wheel_page.append(_hue_lock); _color_wheel_page.append(*_dummie_color_wheel_button); _color_wheel->connect_color_changed(static_cast>([this]() { @@ -650,6 +660,7 @@ void RecolorArt::lpChecked(Color color, bool wheel) void RecolorArt::onResetClicked() { if(!_color_wheel->getHueLock()) _color_wheel->toggleHueLock(); + _color_wheel->setLightness(100.0); _color_wheel->setColor(colors); updateColorModel(); revertToOriginalColors(true); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index c473ca7f24..0d611d4690 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include #include @@ -111,6 +113,8 @@ private: int colors_index=0; bool _is_updating = false; bool _is_wheel_page = false; + Glib::RefPtr adjustment = Gtk::Adjustment::create(100.0, 0.0, 100.0, 1.0, 10.0); + Gtk::Scale& _lightness_bar; Gtk::Button* _dummie_color_wheel_button = nullptr; -- GitLab From 0995dadb684fbccaf2b6c15b9e5b9d7738e23aad Mon Sep 17 00:00:00 2001 From: ftomara Date: Wed, 6 Aug 2025 22:45:17 +0300 Subject: [PATCH 087/122] added swatches indicator to list --- src/ui/widget/recolor-art.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 620b1e988d..774bb08e16 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -348,8 +348,14 @@ void RecolorArt::extractGradientStops(SPObject *item, bool isFill) populateStopsMap(gradient->getFirstStop()); } } + bool is_swatch = gradient->getVector()->isSwatch(); std::string kind = ""; - if (is(gradient)) + if (is_swatch) + { kind = "swatch"; + // std::cout<<"swatches size : "<getGradientVector().stops.size()<(gradient)) kind = "linear"; else if (is(gradient)) kind = "ridal"; @@ -520,10 +526,6 @@ void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) auto it = _selected_colors.find(color_string); if (it != _selected_colors.end()) { std::string size = "" + std::to_string(it->second.first.size()) + ""; - Gtk::Label *label = Gtk::make_managed(); - label->set_use_markup(true); - label->set_markup(size); - box->append(*label); std::set kinds; for (auto item : it->second.first) { if (item.kind == "fill") { @@ -543,8 +545,17 @@ void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) } else if (item.kind.find("mask") != std::string::npos) { kinds.insert(INKSCAPE_ICON("overlay-mask")); } + else if (item.kind.find("swatch") != std::string::npos) { + size = "" + std::to_string(it->second.first.size()/2) + ""; + kinds.insert(INKSCAPE_ICON("paint-swatch")); + // std::cout<<"Swatch : "; + // std::cout<(); + label->set_use_markup(true); + label->set_markup(size); + box->append(*label); for (auto icon : kinds) { Gtk::Image *img = nullptr; img = Gtk::make_managed(); -- GitLab From 85f9dfe5bb0cfe78f8721a12fcd7675431340e2e Mon Sep 17 00:00:00 2001 From: ftomara Date: Fri, 8 Aug 2025 12:32:11 +0300 Subject: [PATCH 088/122] fixed bug recolor button shows on first run --- src/ui/widget/paint-selector.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index 0258040a58..91fe0f6bf6 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -249,6 +249,11 @@ PaintSelector::PaintSelector(FillOrStroke kind, std::shared_ptrappend(*_recolorButtonTriger_1); _recolorButtonTriger_1->hide(); + if (_desktop = SP_ACTIVE_DESKTOP) { + if (auto sel = _desktop->getSelection()) { + onSelectionChanged(sel); + } + } } StyleToggleButton *PaintSelector::style_button_add(gchar const *pixmap, PaintSelector::Mode mode, gchar const *tip) -- GitLab From 34c57aa99b3ee3e43aa9a6fbef357ee4b767a1b5 Mon Sep 17 00:00:00 2001 From: ftomara Date: Fri, 8 Aug 2025 14:33:54 +0300 Subject: [PATCH 089/122] added recolorbutton to markers combobox --- share/ui/marker-popup.glade | 14 ++++++++++++++ src/ui/widget/marker-combo-box.cpp | 24 +++++++++++++++++++++++- src/ui/widget/marker-combo-box.h | 26 +++++++++++++++++++++++++- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/share/ui/marker-popup.glade b/share/ui/marker-popup.glade index 5ffdb0d1a5..687bfeb746 100644 --- a/share/ui/marker-popup.glade +++ b/share/ui/marker-popup.glade @@ -358,6 +358,20 @@ + + + + Recolor Marker + False + True + center + + 0 + 9 + + + + % diff --git a/src/ui/widget/marker-combo-box.cpp b/src/ui/widget/marker-combo-box.cpp index c71602e3d2..530e1e8204 100644 --- a/src/ui/widget/marker-combo-box.cpp +++ b/src/ui/widget/marker-combo-box.cpp @@ -132,7 +132,10 @@ MarkerComboBox::MarkerComboBox(Glib::ustring id, int l) : _orient_angle(get_widget(_builder, "orient-angle")), _orient_flip_horz(get_widget(_builder, "btn-horz-flip")), _current_img(get_widget(_builder, "current-img")), - _edit_marker(get_widget(_builder, "edit-marker")) + _edit_marker(get_widget(_builder, "edit-marker")), + _recolorButtonTriger_1(&get_widget(_builder, "recolor-button")), + _recolorArtWdgt_1(Gtk::make_managed()), + _recolorPopOver_1(Gtk::make_managed()) { auto& input_grid = get_widget(_builder, "input-grid"); _widgets = reparent_properties(input_grid, _grid, true, false, 1); @@ -317,6 +320,13 @@ MarkerComboBox::MarkerComboBox(Glib::ustring id, int l) : update_scale_link(); _current_img.set_paintable(to_texture(g_image_none[_loc])); + + setupRecolorButton(_recolorButtonTriger_1, _recolorPopOver_1, _recolorArtWdgt_1); + + _recolorButtonTriger_1->signal_clicked().connect([this]() { + _recolorPopOver_1->popup(); + _recolorArtWdgt_1->performUpdate(); + }); set_visible(true); } @@ -830,6 +840,18 @@ void MarkerComboBox::preview_scale(double scale) { _preview_scale = scale; _current_img.set_size_request(static_cast(std::round(scale * ITEM_WIDTH)), static_cast(std::round(scale * ITEM_HEIGHT))); } +void MarkerComboBox::setupRecolorButton(Gtk::Button *recolorButtonTriger, Gtk::Popover *recolorPopOver , UI::Widget::RecolorArt *recolorArtWdgt) +{ + recolorButtonTriger->set_label("Recolor Selection"); + recolorButtonTriger->set_hexpand(false); + recolorButtonTriger->set_vexpand(false); + recolorButtonTriger->set_size_request(180); + recolorButtonTriger->set_halign(Gtk::Align::CENTER); + recolorButtonTriger->set_valign(Gtk::Align::START); + recolorPopOver->set_parent(*recolorButtonTriger); + recolorPopOver->set_child(*recolorArtWdgt); + recolorPopOver->set_position(Gtk::PositionType::LEFT); + recolorButtonTriger->set_margin_top(8); } } // namespace Inkscape::UI::Widget diff --git a/src/ui/widget/marker-combo-box.h b/src/ui/widget/marker-combo-box.h index 2db8fc1672..c814e7a166 100644 --- a/src/ui/widget/marker-combo-box.h +++ b/src/ui/widget/marker-combo-box.h @@ -17,6 +17,8 @@ #define SEEN_SP_MARKER_COMBO_BOX_H #include +#include +#include #include #include @@ -26,6 +28,7 @@ #include "ink-spin-button.h" #include "ui/operation-blocker.h" #include "ui/widget/widget-vfuncs-class-init.h" +#include "ui/widget/recolor-art.h" namespace Gtk { class Builder; @@ -134,8 +137,29 @@ private: std::unique_ptr _sandbox; InkPropertyGrid _grid; WidgetGroup _widgets; + Gtk::CellRendererPixbuf _image_renderer; + + UI::Widget::RecolorArt *_recolorArtWdgt_1 = nullptr; + Gtk::Button *_recolorButtonTriger_1 = nullptr; + Gtk::Popover* _recolorPopOver_1=nullptr; + class MarkerColumns : public Gtk::TreeModel::ColumnRecord { + public: + Gtk::TreeModelColumn label; + Gtk::TreeModelColumn marker; // ustring doesn't work here on windows due to unicode + Gtk::TreeModelColumn stock; + Gtk::TreeModelColumn> pixbuf; + Gtk::TreeModelColumn history; + Gtk::TreeModelColumn separator; + + MarkerColumns() { + add(label); add(stock); add(marker); add(history); add(separator); add(pixbuf); + } + }; + MarkerColumns marker_columns; - void update_ui(SPMarker* marker, bool select); + void setupRecolorButton(Gtk::Button *recolorButtonTriger, Gtk::Popover *recolorPopOver, + UI::Widget::RecolorArt *recolorArtWdgt); + void update_ui(SPMarker *marker, bool select); void update_widgets_from_marker(SPMarker* marker); void update_store(); Glib::RefPtr add_separator(bool filler); -- GitLab From 4a278f4a75114e341e33a907e1bc70d5fd8376e7 Mon Sep 17 00:00:00 2001 From: ftomara Date: Fri, 8 Aug 2025 14:35:12 +0300 Subject: [PATCH 090/122] added recolorbutton to swatches page --- src/ui/widget/paint-selector.cpp | 27 ++++++++++++++++++++++++++- src/ui/widget/paint-selector.h | 3 +++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index 91fe0f6bf6..de91b95838 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -130,14 +130,17 @@ PaintSelector::PaintSelector(FillOrStroke kind, std::shared_ptr()) , _recolorArtWdgt_3(Gtk::make_managed()) , _recolorArtWdgt_4(Gtk::make_managed()) + , _recolorArtWdgt_5(Gtk::make_managed()) , _recolorButtonTriger_1(Gtk::make_managed()) , _recolorButtonTriger_2(Gtk::make_managed()) , _recolorButtonTriger_3(Gtk::make_managed()) , _recolorButtonTriger_4(Gtk::make_managed()) + , _recolorButtonTriger_5(Gtk::make_managed()) , _recolorPopOver_1(Gtk::make_managed()) , _recolorPopOver_2(Gtk::make_managed()) , _recolorPopOver_3(Gtk::make_managed()) , _recolorPopOver_4(Gtk::make_managed()) + , _recolorPopOver_5(Gtk::make_managed()) { set_orientation(Gtk::Orientation::VERTICAL); @@ -226,6 +229,7 @@ PaintSelector::PaintSelector(FillOrStroke kind, std::shared_ptrsignal_clicked().connect([this]() { _recolorPopOver_1->popup(); @@ -247,6 +251,11 @@ PaintSelector::PaintSelector(FillOrStroke kind, std::shared_ptrperformUpdate(); }); + _recolorButtonTriger_5->signal_clicked().connect([this]() { + _recolorPopOver_5->popup(); + _recolorArtWdgt_5->performUpdate(); + }); + _frame->append(*_recolorButtonTriger_1); _recolorButtonTriger_1->hide(); if (_desktop = SP_ACTIVE_DESKTOP) { @@ -1154,6 +1163,8 @@ void PaintSelector::set_mode_swatch(PaintSelector::Mode mode) gsel->signal_released().connect(sigc::mem_fun(*this, &PaintSelector::gradient_released)); gsel->signal_changed().connect(sigc::mem_fun(*this, &PaintSelector::gradient_changed)); + _selector_swatch->append(*_recolorButtonTriger_5); + _recolorButtonTriger_5->hide(); // Pack everything to frame _frame->append(*_selector_swatch); } else { @@ -1240,18 +1251,21 @@ void PaintSelector::onSelectionChanged(Inkscape::Selection *selection) _recolorButtonTriger_2->hide(); _recolorButtonTriger_3->hide(); _recolorButtonTriger_4->hide(); + _recolorButtonTriger_5->hide(); // std::cout<<"shoed 1 hide 2\n"; } else if (_mode == MODE_SOLID_COLOR) { _recolorButtonTriger_2->show(); _recolorButtonTriger_1->hide(); _recolorButtonTriger_3->hide(); _recolorButtonTriger_4->hide(); + _recolorButtonTriger_5->hide(); // std::cout<<"shoed 2 hide 1\n"; } else if (_mode == MODE_GRADIENT_RADIAL || _mode == MODE_GRADIENT_LINEAR) { _recolorButtonTriger_1->hide(); _recolorButtonTriger_2->hide(); _recolorButtonTriger_3->show(); _recolorButtonTriger_4->hide(); + _recolorButtonTriger_5->hide(); // std::cout<<"hide 1,2 selection size : "<size()<<" mode : "<<_mode<hide(); _recolorButtonTriger_3->hide(); _recolorButtonTriger_4->show(); + _recolorButtonTriger_5->hide(); + } + else if(_mode == MODE_SWATCH) + { + _recolorButtonTriger_1->hide(); + _recolorButtonTriger_2->hide(); + _recolorButtonTriger_3->hide(); + _recolorButtonTriger_4->hide(); + _recolorButtonTriger_5->show(); } - else { + else { _recolorButtonTriger_1->hide(); _recolorButtonTriger_2->hide(); _recolorButtonTriger_3->hide(); _recolorButtonTriger_4->hide(); + _recolorButtonTriger_5->hide(); // std::cout<<"hide 1,2 selection size : "<size()<<" mode : "<<_mode<hide(); _recolorButtonTriger_3->hide(); _recolorButtonTriger_4->hide(); + _recolorButtonTriger_5->hide(); // std::cout<<"hide 1,2\n"; } } diff --git a/src/ui/widget/paint-selector.h b/src/ui/widget/paint-selector.h index 94c4742b21..97fe1a52ec 100644 --- a/src/ui/widget/paint-selector.h +++ b/src/ui/widget/paint-selector.h @@ -103,14 +103,17 @@ class PaintSelector : public Gtk::Box { UI::Widget::RecolorArt *_recolorArtWdgt_2 = nullptr; UI::Widget::RecolorArt *_recolorArtWdgt_3 = nullptr; UI::Widget::RecolorArt *_recolorArtWdgt_4 = nullptr; + UI::Widget::RecolorArt *_recolorArtWdgt_5 = nullptr; Gtk::Button *_recolorButtonTriger_1 = nullptr; Gtk::Button *_recolorButtonTriger_2 = nullptr; Gtk::Button *_recolorButtonTriger_3 = nullptr; Gtk::Button *_recolorButtonTriger_4 = nullptr; + Gtk::Button *_recolorButtonTriger_5 = nullptr; Gtk::Popover* _recolorPopOver_1=nullptr; Gtk::Popover* _recolorPopOver_2=nullptr; Gtk::Popover* _recolorPopOver_3=nullptr; Gtk::Popover* _recolorPopOver_4=nullptr; + Gtk::Popover* _recolorPopOver_5=nullptr; bool _change_sel=false; SPDesktop*_desktop=nullptr; void onSelectionChanged(Inkscape::Selection *selection); -- GitLab From 564a3c09036871a116eceec314c2fdde019656a7 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sat, 9 Aug 2025 15:00:42 +0300 Subject: [PATCH 091/122] fixed pattern and markers button not showing issues --- share/ui/marker-popup.glade | 14 -------------- src/ui/widget/marker-combo-box.cpp | 13 +++++++++---- src/ui/widget/paint-selector.cpp | 7 ++++--- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/share/ui/marker-popup.glade b/share/ui/marker-popup.glade index 687bfeb746..5ffdb0d1a5 100644 --- a/share/ui/marker-popup.glade +++ b/share/ui/marker-popup.glade @@ -358,20 +358,6 @@ - - - - Recolor Marker - False - True - center - - 0 - 9 - - - - % diff --git a/src/ui/widget/marker-combo-box.cpp b/src/ui/widget/marker-combo-box.cpp index 530e1e8204..62472141b7 100644 --- a/src/ui/widget/marker-combo-box.cpp +++ b/src/ui/widget/marker-combo-box.cpp @@ -133,7 +133,7 @@ MarkerComboBox::MarkerComboBox(Glib::ustring id, int l) : _orient_flip_horz(get_widget(_builder, "btn-horz-flip")), _current_img(get_widget(_builder, "current-img")), _edit_marker(get_widget(_builder, "edit-marker")), - _recolorButtonTriger_1(&get_widget(_builder, "recolor-button")), + _recolorButtonTriger_1(Gtk::make_managed()), _recolorArtWdgt_1(Gtk::make_managed()), _recolorPopOver_1(Gtk::make_managed()) { @@ -321,12 +321,13 @@ MarkerComboBox::MarkerComboBox(Glib::ustring id, int l) : update_scale_link(); _current_img.set_paintable(to_texture(g_image_none[_loc])); - setupRecolorButton(_recolorButtonTriger_1, _recolorPopOver_1, _recolorArtWdgt_1); - + setupRecolorButton(_recolorButtonTriger_1, _recolorPopOver_1, _recolorArtWdgt_1); + _grid.add_full_row(_recolorButtonTriger_1); _recolorButtonTriger_1->signal_clicked().connect([this]() { _recolorPopOver_1->popup(); _recolorArtWdgt_1->performUpdate(); }); + _recolorButtonTriger_1->hide(); set_visible(true); } @@ -361,7 +362,10 @@ void MarkerComboBox::update_widgets_from_marker(SPMarker* marker) { _orient_angle.set_active(); _angle_btn.set_sensitive(true); } - } + _recolorButtonTriger_1->show(); + + }else + _recolorButtonTriger_1->hide(); } void MarkerComboBox::update_scale_link() { @@ -840,6 +844,7 @@ void MarkerComboBox::preview_scale(double scale) { _preview_scale = scale; _current_img.set_size_request(static_cast(std::round(scale * ITEM_WIDTH)), static_cast(std::round(scale * ITEM_HEIGHT))); } +} void MarkerComboBox::setupRecolorButton(Gtk::Button *recolorButtonTriger, Gtk::Popover *recolorPopOver , UI::Widget::RecolorArt *recolorArtWdgt) { recolorButtonTriger->set_label("Recolor Selection"); diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index de91b95838..218b6a5769 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -1032,11 +1032,12 @@ void PaintSelector::set_mode_pattern(PaintSelector::Mode mode) _selector_pattern->signal_changed().connect([this](){ _signal_changed.emit(); }); _selector_pattern->signal_color_changed().connect([this](Colors::Color const &){ _signal_changed.emit(); }); _selector_pattern->signal_edit().connect([this](){ _signal_edit_pattern.emit(); }); - _selector_pattern->get_input_grid().attach(*_recolorButtonTriger_4,0,7); - _recolorButtonTriger_4->set_size_request(-1); + // _selector_pattern->get_input_grid().attach(*_recolorButtonTriger_4,0,10); + // _recolorButtonTriger_4->set_size_request(-1); _recolorButtonTriger_4->set_label("Recolor Pattern"); - _recolorButtonTriger_4->hide(); _frame->append(*_selector_pattern); + _frame->append(*_recolorButtonTriger_4); + _recolorButtonTriger_4->hide(); } SPDocument* document = SP_ACTIVE_DOCUMENT; -- GitLab From 0a8a30ca951861bbefb2797fd12465e709621fbd Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 10 Aug 2025 17:48:21 +0300 Subject: [PATCH 092/122] added tooltip to the type box on the original color button --- src/ui/widget/recolor-art.cpp | 44 ++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 774bb08e16..2334b876bf 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -526,28 +526,36 @@ void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) auto it = _selected_colors.find(color_string); if (it != _selected_colors.end()) { std::string size = "" + std::to_string(it->second.first.size()) + ""; - std::set kinds; + std::map> kinds; for (auto item : it->second.first) { if (item.kind == "fill") { - kinds.insert(INKSCAPE_ICON("object-fill")); + kinds[INKSCAPE_ICON("object-fill")].first++; + kinds[INKSCAPE_ICON("object-fill")].second = "fill"; } else if (item.kind == "stroke") { - kinds.insert(INKSCAPE_ICON("object-stroke")); + kinds[INKSCAPE_ICON("object-stroke")].first++; + kinds[INKSCAPE_ICON("object-stroke")].second = "stroke"; } else if (item.kind == "mesh") { - kinds.insert(INKSCAPE_ICON("paint-gradient-mesh")); + kinds[INKSCAPE_ICON("paint-gradient-mesh")].first++; + kinds[INKSCAPE_ICON("paint-gradient-mesh")].second = "mesh"; } else if (item.kind == "linear") { - kinds.insert(INKSCAPE_ICON("paint-gradient-linear")); + kinds[INKSCAPE_ICON("paint-gradient-linear")].first++; + kinds[INKSCAPE_ICON("paint-gradient-linear")].second = "linear gradient"; } else if (item.kind == "ridal") { - kinds.insert(INKSCAPE_ICON("paint-gradient-radial")); + kinds[INKSCAPE_ICON("paint-gradient-radial")].first++; + kinds[INKSCAPE_ICON("paint-gradient-radial")].second = "radial gradient"; } else if (item.kind.find("pattern") != std::string::npos) { - kinds.insert(INKSCAPE_ICON("paint-pattern")); + kinds[INKSCAPE_ICON("paint-pattern")].first++; + kinds[INKSCAPE_ICON("paint-pattern")].second = "pattern"; } else if (item.kind.find("marker") != std::string::npos) { - kinds.insert(INKSCAPE_ICON("markers")); + kinds[INKSCAPE_ICON("markers")].first++; + kinds[INKSCAPE_ICON("markers")].second = "marker"; } else if (item.kind.find("mask") != std::string::npos) { - kinds.insert(INKSCAPE_ICON("overlay-mask")); - } - else if (item.kind.find("swatch") != std::string::npos) { - size = "" + std::to_string(it->second.first.size()/2) + ""; - kinds.insert(INKSCAPE_ICON("paint-swatch")); + kinds[INKSCAPE_ICON("overlay-mask")].first++; + kinds[INKSCAPE_ICON("overlay-mask")].second = "mask"; + } else if (item.kind.find("swatch") != std::string::npos) { + size = "" + std::to_string(it->second.first.size() / 2) + ""; + kinds[INKSCAPE_ICON("paint-swatch")].first++; + kinds[INKSCAPE_ICON("paint-swatch")].second = "swatch"; // std::cout<<"Swatch : "; // std::cout<set_use_markup(true); label->set_markup(size); box->append(*label); - for (auto icon : kinds) { + std::string tooltip=""; + int sz = kinds.size() , s=0; + for (auto [icon,pair] : kinds) { Gtk::Image *img = nullptr; img = Gtk::make_managed(); img->set_from_icon_name(icon); @@ -569,8 +579,14 @@ void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) } else img->set_pixel_size(8); box->append(*img); + if(icon == INKSCAPE_ICON("paint-swatch")) pair.first/=2; + tooltip+=std::to_string(pair.first)+" x "+pair.second; + if(s!=sz-1)tooltip+="\n"; + } + s++; } + box->set_tooltip_text(tooltip); } } std::pair, guint> RecolorArt::findColorItemByKey(std::string const &key) -- GitLab From fdd8f2de0929b0784972cb59a19cd55595d0e448 Mon Sep 17 00:00:00 2001 From: ftomara Date: Mon, 11 Aug 2025 13:33:38 +0300 Subject: [PATCH 093/122] fixed colorwheel dropdown not staying dropped when selection different colors from the color list --- src/ui/widget/color-notebook.cpp | 8 ++++++++ src/ui/widget/color-notebook.h | 1 + src/ui/widget/color-page.h | 3 +++ src/ui/widget/recolor-art.cpp | 7 ++----- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/ui/widget/color-notebook.cpp b/src/ui/widget/color-notebook.cpp index ff6c53e5cb..b2ee1cbb6c 100644 --- a/src/ui/widget/color-notebook.cpp +++ b/src/ui/widget/color-notebook.cpp @@ -311,6 +311,14 @@ void ColorNotebook::_addPageForSpace(std::shared_ptr sp _visibility_observers.emplace_back(std::move(obs)); } +void ColorNotebook::setCurrentColor(std::shared_ptr colors) +{ + auto visible_child = _book->get_visible_child(); + if (auto current_page = dynamic_cast(visible_child)) { + current_page->setCurrentColor(colors); + } +} + } // namespace Inkscape::UI::Widget /* diff --git a/src/ui/widget/color-notebook.h b/src/ui/widget/color-notebook.h index 637379c716..d0d9e9cc97 100644 --- a/src/ui/widget/color-notebook.h +++ b/src/ui/widget/color-notebook.h @@ -39,6 +39,7 @@ public: ~ColorNotebook() override; void set_label(const Glib::ustring& label); + void setCurrentColor(std::shared_ptr colors); protected: void _initUI(); diff --git a/src/ui/widget/color-page.h b/src/ui/widget/color-page.h index 6a3a2377a1..6b3dd692ab 100644 --- a/src/ui/widget/color-page.h +++ b/src/ui/widget/color-page.h @@ -22,6 +22,8 @@ #include "color-slider.h" #include "color-preview.h" #include "ui/widget/color-slider.h" +#include "ui/widget/ink-color-wheel.h" + using namespace Inkscape::Colors; @@ -56,6 +58,7 @@ public: void attach_page(Glib::RefPtr first_column, Glib::RefPtr last_column); void detach_page(Glib::RefPtr first_column, Glib::RefPtr last_column); + void setCurrentColor(std::shared_ptr color){if(_color_wheel)_color_wheel->set_color(color->get().value());} protected: std::shared_ptr _space; std::shared_ptr _selected_colors; diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 2334b876bf..d27b77dffb 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -478,8 +478,6 @@ void RecolorArt::generateVisualList() } void RecolorArt::layoutColorPicker(std::shared_ptr updated_color) { - if (updated_color) - _solid_colors = updated_color; _color_picker_wdgt = Gtk::make_managed(_solid_colors); _color_picker_wdgt->set_visible(true); _color_picker_wdgt->set_label(_("Selected Color")); @@ -608,9 +606,8 @@ void RecolorArt::onOriginalColorClicked(std::string color_id) auto it = _selected_colors.find(color_id); if (it != _selected_colors.end() && it->second.second.has_value()) { Color color = it->second.second.value().new_color; - std::shared_ptr updated_color = std::make_shared(); - updated_color->set(color); - layoutColorPicker(updated_color); + _solid_colors->set(color); + _color_picker_wdgt->setCurrentColor(_solid_colors); } } void RecolorArt::onColorPickerChanged(Color color, bool wheel) -- GitLab From 48f8c08beeac36df5cbaa29e33a000657d65dce2 Mon Sep 17 00:00:00 2001 From: ftomara Date: Mon, 11 Aug 2025 14:01:50 +0300 Subject: [PATCH 094/122] fixed arrow turning white when selected in the light mode --- share/ui/style.css | 1 + 1 file changed, 1 insertion(+) diff --git a/share/ui/style.css b/share/ui/style.css index f37b11c129..22c21ca022 100644 --- a/share/ui/style.css +++ b/share/ui/style.css @@ -1702,4 +1702,5 @@ button.reduced-padding { background-color: transparent; border: 2px solid @theme_selected_bg_color; border-radius: 4px; + color: @theme_fg_color; } -- GitLab From 3c33350b198eb83a05765967dceab7b562f55d66 Mon Sep 17 00:00:00 2001 From: ftomara Date: Mon, 11 Aug 2025 16:10:18 +0300 Subject: [PATCH 095/122] fixed include compliation bug --- src/ui/widget/recolor-art.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 0d611d4690..d75e637eef 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -23,6 +23,7 @@ #include "style.h" #include "ui/widget/paint-selector.h" #include "ui/widget/ink-color-wheel.h" +#include "src/colors/color-set.h" using namespace Inkscape::Colors; -- GitLab From d8827981718dc1bcef216e3a94fac1658112fde5 Mon Sep 17 00:00:00 2001 From: ftomara Date: Mon, 11 Aug 2025 21:26:31 +0300 Subject: [PATCH 096/122] added recolor files to potfiles to fix translation issue --- po/POTFILES.src.in | 1 + po/POTFILES.ui.in | 1 + share/ui/recolor-art.glade | 10 +++++----- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/po/POTFILES.src.in b/po/POTFILES.src.in index b227ec488b..14f932d936 100644 --- a/po/POTFILES.src.in +++ b/po/POTFILES.src.in @@ -435,6 +435,7 @@ ${_build_dir}/share/templates/templates.h ../src/ui/widget/preferences-widget.cpp ../src/ui/widget/property-utils.cpp ../src/ui/widget/random.cpp +../src/ui/widget/recolor-art.cpp ../src/ui/widget/registered-widget.cpp ../src/ui/widget/rendering-options.cpp ../src/ui/widget/selected-style.cpp diff --git a/po/POTFILES.ui.in b/po/POTFILES.ui.in index 64483fff91..4d0449d38a 100644 --- a/po/POTFILES.ui.in +++ b/po/POTFILES.ui.in @@ -31,6 +31,7 @@ ../share/ui/object-attributes.glade ../share/ui/page-properties.glade ../share/ui/pattern-edit.glade +../share/ui/recolor-art.glade ../share/ui/align-and-distribute.ui ../share/ui/dash-selector.ui ../share/ui/dialog-measure-tool-settings.ui diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 2fa8149db5..deae04a4b3 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -25,7 +25,7 @@ none - Original + Original fill @@ -47,7 +47,7 @@ - New + New center @@ -96,7 +96,7 @@ - Color List + Color List center center @@ -127,7 +127,7 @@ - Color Wheel + Color Wheel center center @@ -153,7 +153,7 @@ liveP - Live Preview + Live Preview end start -- GitLab From a112453246594ffcd9faab3987c0ef208e5d7a87 Mon Sep 17 00:00:00 2001 From: ftomara Date: Mon, 11 Aug 2025 21:48:11 +0300 Subject: [PATCH 097/122] added missing icons to pass mediacheck test --- share/icons/Dash/symbolic/actions/reset-symbolic.svg | 5 +++++ .../hicolor/symbolic/actions/object-recolor-art-symbolic.svg | 5 +++++ share/icons/hicolor/symbolic/actions/reset-symbolic.svg | 5 +++++ 3 files changed, 15 insertions(+) create mode 100644 share/icons/Dash/symbolic/actions/reset-symbolic.svg create mode 100644 share/icons/hicolor/symbolic/actions/object-recolor-art-symbolic.svg create mode 100644 share/icons/hicolor/symbolic/actions/reset-symbolic.svg diff --git a/share/icons/Dash/symbolic/actions/reset-symbolic.svg b/share/icons/Dash/symbolic/actions/reset-symbolic.svg new file mode 100644 index 0000000000..09c40a1e30 --- /dev/null +++ b/share/icons/Dash/symbolic/actions/reset-symbolic.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/share/icons/hicolor/symbolic/actions/object-recolor-art-symbolic.svg b/share/icons/hicolor/symbolic/actions/object-recolor-art-symbolic.svg new file mode 100644 index 0000000000..b078cf421c --- /dev/null +++ b/share/icons/hicolor/symbolic/actions/object-recolor-art-symbolic.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/share/icons/hicolor/symbolic/actions/reset-symbolic.svg b/share/icons/hicolor/symbolic/actions/reset-symbolic.svg new file mode 100644 index 0000000000..09c40a1e30 --- /dev/null +++ b/share/icons/hicolor/symbolic/actions/reset-symbolic.svg @@ -0,0 +1,5 @@ + + + + + -- GitLab From 2626faabec810a2990db0fdd0854fa2dc50f0818 Mon Sep 17 00:00:00 2001 From: ftomara Date: Wed, 13 Aug 2025 17:24:55 +0300 Subject: [PATCH 098/122] hid selection boxes on recoloring widget shown --- src/desktop.cpp | 5 +++++ src/desktop.h | 1 + src/display/control/canvas-item-group.cpp | 15 +++++++++++++++ src/display/control/canvas-item-group.h | 1 + src/display/control/canvas-item.cpp | 1 + src/display/control/canvas-item.h | 4 +++- src/ui/widget/recolor-art.cpp | 10 ++++++++-- 7 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/desktop.cpp b/src/desktop.cpp index 7abd51c830..1e50f22c36 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -1124,6 +1124,11 @@ void SPDesktop::applyCurrentOrToolStyle(SPObject *obj, Glib::ustring const &tool } } +void SPDesktop::hideSelectionBoxes(bool hide) +{ + _canvas_group_controls->hide_selection_boxes(hide); +} + void SPDesktop::setToolboxFocusTo(char const * const label) { diff --git a/src/desktop.h b/src/desktop.h index 63c4c01064..190273222e 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -432,6 +432,7 @@ public: void applyCurrentOrToolStyle(SPObject *obj, Glib::ustring const &tool_path, bool with_text); + void hideSelectionBoxes(bool hide); private: SPDesktopWidget *_widget = nullptr; diff --git a/src/display/control/canvas-item-group.cpp b/src/display/control/canvas-item-group.cpp index ef02d4890d..ea468c4e29 100644 --- a/src/display/control/canvas-item-group.cpp +++ b/src/display/control/canvas-item-group.cpp @@ -15,6 +15,7 @@ #include #include "canvas-item-group.h" +#include "canvas-item-rect.h" constexpr bool DEBUG_LOGGING = false; @@ -111,6 +112,20 @@ CanvasItem *CanvasItemGroup::pick_item(Geom::Point const &p) return nullptr; } +void CanvasItemGroup::hide_selection_boxes(bool hide) +{ + for (auto &item : items) { + std::string name = item.get_name(); + if (dynamic_cast(&item)) { + item.set_visible(!hide); + item.set_force_hide(!hide); + } + } + + // _update(true); +} + + } // namespace Inkscape /* diff --git a/src/display/control/canvas-item-group.h b/src/display/control/canvas-item-group.h index 2bccdeab12..e8d9da5d7d 100644 --- a/src/display/control/canvas-item-group.h +++ b/src/display/control/canvas-item-group.h @@ -31,6 +31,7 @@ public: // Selection CanvasItem *pick_item(Geom::Point const &p); + void hide_selection_boxes(bool hide); protected: friend class CanvasItem; // access to items diff --git a/src/display/control/canvas-item.cpp b/src/display/control/canvas-item.cpp index 617903b92d..7640b5bff4 100644 --- a/src/display/control/canvas-item.cpp +++ b/src/display/control/canvas-item.cpp @@ -149,6 +149,7 @@ void CanvasItem::request_update() void CanvasItem::update(bool propagate) { + if(!_recolor_force_hide)return; if (!_visible) { _mark_net_invisible(); return; diff --git a/src/display/control/canvas-item.h b/src/display/control/canvas-item.h index 14d4c71d21..6f4320e4a4 100644 --- a/src/display/control/canvas-item.h +++ b/src/display/control/canvas-item.h @@ -110,7 +110,8 @@ public: // Recursively print CanvasItem tree. void canvas_item_print_tree(int level = 0, int zorder = 0) const; - + void set_force_hide(bool hide){_recolor_force_hide = hide;} + bool get_force_hide(){return _recolor_force_hide;} // Boost linked list member hook, speeds deletion. boost::intrusive::list_member_hook<> member_hook; @@ -134,6 +135,7 @@ protected: // Display bool _visible = true; + bool _recolor_force_hide = true; bool _net_visible = true; virtual void _render(Inkscape::CanvasItemBuffer &buf) const = 0; diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index d27b77dffb..ffdaf191f7 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -71,9 +71,14 @@ RecolorArt::RecolorArt() ,_hue_lock(*Gtk::make_managed()) ,_lightness_bar(*Gtk::make_managed(adjustment,Gtk::Orientation::HORIZONTAL)) { + _desktop = SP_ACTIVE_DESKTOP; set_name("RecolorArt"); append(get_widget(_builder, "recolor-art")); - signal_unmap().connect([&]() { resetOpacity(); }); + signal_unmap().connect([&]() { + resetOpacity(); + _desktop->hideSelectionBoxes(false); + }); + signal_map().connect([&]() { Glib::signal_idle().connect_once([this]() { _desktop->hideSelectionBoxes(true); }); }); _solid_colors->set(Color(0x000000ff)); auto image = Gtk::make_managed(); image->set_from_icon_name(INKSCAPE_ICON("shape-link")); @@ -361,6 +366,7 @@ void RecolorArt::extractGradientStops(SPObject *item, bool isFill) kind = "ridal"; for (auto stop : gradient->getGradientVector().stops) { if (stop.color.has_value()) { + // if(kind == "swatch") std::cout<<"swatch found : "<getSelection()) { if (_paint_selector) @@ -855,6 +860,7 @@ void RecolorArt::performUpdate() g_message("Performing Update\n"); } else g_message("Desktop is NULL in Performupdate in recolor widegt\n"); + } } // namespace Widget } // namespace UI -- GitLab From 7d8a19b69a06aedeeac4dd816808b1615dac7641 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 17 Aug 2025 02:17:35 +0300 Subject: [PATCH 099/122] set auto hide to false for popover to interact with canvas while open --- src/ui/widget/paint-selector.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index 218b6a5769..13d6fd522b 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -1315,6 +1315,7 @@ void PaintSelector::setupRecolorButton(Gtk::Button *recolorButtonTriger, Gtk::Po recolorButtonTriger->set_valign(Gtk::Align::START); recolorPopOver->set_parent(*recolorButtonTriger); recolorPopOver->set_child(*recolorArtWdgt); + recolorPopOver->set_autohide(false); recolorPopOver->set_position(Gtk::PositionType::LEFT); recolorButtonTriger->set_margin_top(8); } -- GitLab From 2b2290e9bb5f573b5fa6a182af544b62e18c8d27 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 17 Aug 2025 05:23:44 +0300 Subject: [PATCH 100/122] added multimarker color wheel page --- share/ui/recolor-art.glade | 45 ++++- share/ui/style.css | 16 +- src/ui/CMakeLists.txt | 3 +- src/ui/widget/multi-marker-color-plate.cpp | 206 +++++++++++++++++++++ src/ui/widget/multi-marker-color-plate.h | 119 ++++++++++++ src/ui/widget/recolor-art.cpp | 105 ++++------- src/ui/widget/recolor-art.h | 20 +- 7 files changed, 419 insertions(+), 95 deletions(-) create mode 100644 src/ui/widget/multi-marker-color-plate.cpp create mode 100644 src/ui/widget/multi-marker-color-plate.h diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index deae04a4b3..90674d0f91 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -80,6 +80,15 @@ + + + + vertical + true + + + + @@ -110,6 +119,36 @@ vertical true true + + + + true + true + true + never + false + 80 + + + colors-grid + vertical + true + fill + fill + 16 + + + false + fill + true + fill + + + + + + + @@ -138,12 +177,6 @@ - - - vertical - true - - diff --git a/share/ui/style.css b/share/ui/style.css index 22c21ca022..c0bf2e1265 100644 --- a/share/ui/style.css +++ b/share/ui/style.css @@ -1688,19 +1688,25 @@ button.reduced-padding { /* border: 2px solid transparent; */ } -/* #original-recolor-box #original:hover, -#recolored:hover { - border-color: @theme_fq_color; -} */ +#original-recolor-box{ +padding:0 1px; +} .type_box { background-color: alpha(@theme_bg_color,0.8); border-radius: 2px; padding-left: 2px; padding-right: 6px; } -#recolor-art listview row:selected { +#recolor-art listview row:selected{ background-color: transparent; border: 2px solid @theme_selected_bg_color; border-radius: 4px; color: @theme_fg_color; } + +#recolor-art gridview child:selected { + background-color: transparent; + border: 1px solid @theme_selected_bg_color; + border-radius: 1px; + color: @theme_fg_color; +} diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index ac483291ec..75a79574f9 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -299,7 +299,7 @@ set(ui_SRC widget/xml-treeview.cpp widget/property-utils.cpp widget/recolor-art.cpp - + widget/multi-marker-color-plate.cpp view/svg-view-widget.cpp # ------- @@ -627,6 +627,7 @@ set(ui_SRC widget/property-utils.h widget/recolor-art.h + widget/multi-marker-color-plate.h view/svg-view-widget.h ) diff --git a/src/ui/widget/multi-marker-color-plate.cpp b/src/ui/widget/multi-marker-color-plate.cpp new file mode 100644 index 0000000000..13f54f54c8 --- /dev/null +++ b/src/ui/widget/multi-marker-color-plate.cpp @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include +#include +#include + +#include "actions/actions-tools.h" +#include "canvas.h" +#include "color-notebook.h" +#include "colors/spaces/base.h" +#include "colors/spaces/enum.h" +#include "desktop-style.h" +#include "desktop.h" +#include "document-undo.h" +#include "document.h" +#include "gradient-chemistry.h" +#include "ink-color-wheel.h" +#include "inkscape.h" +#include "multi-marker-color-plate.h" +#include "object/sp-defs.h" +#include "object/sp-gradient.h" +#include "object/sp-linear-gradient.h" +#include "object/sp-marker.h" +#include "object/sp-mask.h" +#include "object/sp-mesh-gradient.h" +#include "object/sp-object.h" +#include "object/sp-pattern.h" +#include "object/sp-radial-gradient.h" +#include "object/sp-stop.h" +#include "object/sp-text.h" +#include "object/sp-use.h" +#include "pattern-manipulation.h" +#include "selection.h" +#include "style-internal.h" +#include "style.h" +#include "ui/builder-utils.h" +#include "ui/dialog/dialog-base.h" +#include "ui/icon-names.h" +#include "ui/pack.h" +#include "ui/widget/color-page.h" +#include "ui/widget/color-preview.h" +#include "ui/widget/color-slider.h" +#include "ui/widget/icon-combobox.h" +#include "ui/widget/ink-spin-button.h" +#include "xml/repr.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr colors) + : Gtk::Box(Gtk::Orientation::VERTICAL) + , _specific_colors(std::make_shared(manager->find(Space::Type::HSL), + colors->getAlphaConstraint().value_or(true))) + , _color_wheel(Gtk::make_managed()) + , _hue_lock(*Gtk::make_managed()) + , _lightness_bar(*Gtk::make_managed(adjustment, Gtk::Orientation::HORIZONTAL)) + , _color_wheel_preview(Gtk::make_managed()) + , _grid(Gtk::make_managed()) + , _spaces_combo(Gtk::make_managed()) + , _switcher(Gtk::make_managed()) + , _spaces_stack(Gtk::make_managed()) +{ + _specific_colors->set(Color(0xFF0000FF)); + + _switcher->set_stack(*_spaces_stack); + + _spaces_combo->add_css_class("regular"); + _spaces_combo->set_focusable(false); + _spaces_combo->set_tooltip_text(_("Choose style of color selection")); + _spaces_combo->set_hexpand(false); + _spaces_combo->set_halign(Gtk::Align::END); + _spaces_combo->set_margin_top(8); + + _spaces_combo->signal_changed().connect([this](int index) { + _specific_colors = _color_sets[index].second; + _spaces_stack->set_visible_child(_color_sets[index].first); + _specific_colors_changed.disconnect(); + _specific_colors_changed = _specific_colors->signal_changed.connect([this]() { + Color new_color = _specific_colors->get().value(); + if (_color_wheel->getActiveIndex() != -1) { + _color_wheel->changeColor(_color_wheel->getActiveIndex(), new_color); + _color_wheel_preview->setRgba32(new_color.toRGBA()); + } + }); + }); + + int index = 0; + for (auto &space : Colors::Manager::get().spaces(Space::Traits::Picker)) { + _createSlidersForSpace(space, _specific_colors, index); + _addPageForSpace(space, index++); + } + + _lightness_bar.set_value_pos(Gtk::PositionType::RIGHT); + _lightness_bar.set_hexpand(true); + _lightness_bar.set_draw_value(true); + _lightness_bar.signal_value_changed().connect([this]() { + double value = _lightness_bar.get_value(); + _color_wheel->setLightness(value); + }); + + _hue_lock_image = Gtk::make_managed(); + _hue_lock_image->set_from_icon_name(INKSCAPE_ICON("object-unlocked")); + _hue_lock.set_child(*_hue_lock_image); + _hue_lock.signal_toggled().connect([this]() { + _color_wheel->toggleHueLock(); + if (_hue_lock.get_active()) { + _hue_lock_image->set_from_icon_name(INKSCAPE_ICON("object-locked")); + _hue_lock.set_child(*_hue_lock_image); + } else { + _hue_lock_image->set_from_icon_name(INKSCAPE_ICON("object-unlocked")); + _hue_lock.set_child(*_hue_lock_image); + } + }); + _hue_lock.set_tooltip_text("lock hue angles for colors set"); + _hue_lock.set_hexpand(false); + _hue_lock.set_margin_top(8); + _hue_lock.set_halign(Gtk::Align::START); + + auto box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); + box->set_spacing(120); + box->append(_hue_lock); + box->append(*_spaces_combo); + + _lightness_box->append(*_lightness_label); + _lightness_box->append(_lightness_bar); + + _spaces_stack->set_visible_child("RGB"); + + _color_wheel_preview->set_hexpand(false); + _color_wheel_preview->set_size_request(35,35); + _color_wheel_preview->set_halign(Gtk::Align::START); + _color_wheel_preview->set_margin_top(8); + _color_wheel_preview->setStyle(_color_wheel_preview->Style::Outlined); + // _color_wheel_preview->set_margin_start(8); + + append(*box); + append(*_color_wheel_preview); + append(*_color_wheel); + append(*_lightness_box); + append(*_spaces_combo); + append(*_spaces_stack); +} + +MultiMarkerColorPlate::~MultiMarkerColorPlate() { + if(_specific_colors_changed.connected()) + { + _specific_colors_changed.disconnect(); + } +} + +void MultiMarkerColorPlate::_addPageForSpace(std::shared_ptr space, int page_num) +{ + auto mode_name = space->getName(); + if (mode_name == "RGB" || mode_name == "HSL") + _spaces_combo->add_row(space->getIcon(), mode_name, page_num); +} + +void MultiMarkerColorPlate::_createSlidersForSpace(std::shared_ptr space, + std::shared_ptr &colors, int index) +{ + auto mode_name = space->getName(); + if (mode_name != "RGB" && mode_name != "HSL") + return; + Gtk::Grid *_grid = Gtk::make_managed(); + auto new_colors = std::make_shared(space, colors->getAlphaConstraint().value_or(true)); + new_colors->set(colors->get().value()); + int row = 0; + for (auto &component : new_colors->getComponents()) { + auto label = Gtk::make_managed(); + auto slider = Gtk::make_managed(new_colors, component); + auto spin = Gtk::make_managed(); + spin->set_digits(component.id == "alpha" ? 0 : 1); + if (component.scale < 100) { + // for small values increase precision + spin->set_digits(2); + spin->get_adjustment()->set_step_increment(0.1); + } + _grid->attach(*label, 0, row); + _grid->attach(*slider, 1, row); + _grid->attach(*spin, 2, row++); + _channels.emplace_back(std::make_unique(new_colors, *label, *slider, *spin)); + } + _color_sets[index] = {mode_name, new_colors}; + _spaces_stack->add(*_grid, mode_name, mode_name); +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape diff --git a/src/ui/widget/multi-marker-color-plate.h b/src/ui/widget/multi-marker-color-plate.h new file mode 100644 index 0000000000..e49f9a995a --- /dev/null +++ b/src/ui/widget/multi-marker-color-plate.h @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#ifndef WIDGET_MULTI_MARKER_COLOR_PLATE_H +#define WIDGET_MULTI_MARKER_COLOR_PLATE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "canvas.h" +#include "src/colors/color-set.h" +#include "src/colors/manager.h" +#include "style-internal.h" +#include "style.h" +#include "ui/builder-utils.h" +#include "ui/widget/color-page.h" +#include "ui/widget/color-preview.h" +#include "ui/widget/icon-combobox.h" +#include "ui/widget/ink-color-wheel.h" +#include "ui/widget/paint-selector.h" + +using namespace Inkscape::Colors; + +namespace Inkscape::Colors { +class Color; +class ColorSet; +namespace Space { +class AnySpace; +} +} // namespace Inkscape::Colors + +namespace Gtk { +class Widget; +} // namespace Gtk + +class SPDesktop; + +namespace Inkscape { +namespace UI { +namespace Tools { +class ToolBase; +} + +namespace Widget { + +class MultiMarkerColorPlate : public Gtk::Box +{ +public: + MultiMarkerColorPlate(std::shared_ptr colors); + ~MultiMarkerColorPlate(); + void setColor(std::vector &colors) { _color_wheel->setColor(colors); } + void setLightness(double value) + { + _color_wheel->setLightness(value); + _lightness_bar.set_value(value); + } + Colors::Color getColor() { return _color_wheel->getColor(); } + std::vector getColors() { return _color_wheel->getColors(); } + bool getHueLock() { return _color_wheel->getHueLock(); } + void toggleHueLock() { _color_wheel->toggleHueLock(); } + int getActiveIndex() { return _color_wheel->getActiveIndex(); } + void setActiveIndex(int index) { _color_wheel->setActiveIndex(index); } + int getHoverIndex() { return _color_wheel->getHoverIndex(); } + sigc::connection connect_color_hovered(sigc::slot slot) + { + return _color_wheel->connect_color_hovered(slot); + } + sigc::connection connect_color_changed(sigc::slot slot) + { + return _color_wheel->connect_color_changed(slot); + } + void changeColor(int index, Color color) + { + _color_wheel->changeColor(index, color); + _color_wheel_preview->setRgba32(color.toRGBA()); + _specific_colors->set(color); + } + +private: + MultiMarkerWheel *_color_wheel = nullptr; + Gtk::Label *_lightness_label = Gtk::make_managed("Lightness : "); + Gtk::Box *_lightness_box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); + Glib::RefPtr adjustment = Gtk::Adjustment::create(100.0, 0.0, 100.0, 1.0, 10.0); + Gtk::Scale &_lightness_bar; + Gtk::ToggleButton &_hue_lock; + ColorPreview *_color_wheel_preview = nullptr; + Manager *manager = &Manager::get(); + Gtk::Grid *_grid = nullptr; + std::shared_ptr _specific_colors; + std::vector> _channels; + Gtk::Image *_hue_lock_image = nullptr; + IconComboBox *_spaces_combo = nullptr; + Gtk::Stack *_spaces_stack = nullptr; + Gtk::StackSwitcher *_switcher = nullptr; + std::map>> _color_sets; + sigc::connection _specific_colors_changed ; + void _addPageForSpace(std::shared_ptr space, int page_num); + void _createSlidersForSpace(std::shared_ptr space, + std::shared_ptr &colors, int index); +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // WIDGET_MULTI_MARKER_COLOR_PLATE_H diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index ffdaf191f7..035d02abce 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -63,13 +63,10 @@ RecolorArt::RecolorArt() : Gtk::Box() , _notebook(*_builder->get_widget("list-wheel-box")) , _color_wheel_page(*_builder->get_widget("color-wheel-page")) - , _color_wheel(Gtk::make_managed()) + , _color_wheel(Gtk::make_managed(std::make_shared())) ,_color_list(*_builder->get_widget("colors-list")) ,_reset(*_builder->get_widget("reset")) ,_live_preview(*_builder->get_widget("liveP")) - , _dummie_color_wheel_button(Gtk::make_managed()) - ,_hue_lock(*Gtk::make_managed()) - ,_lightness_bar(*Gtk::make_managed(adjustment,Gtk::Orientation::HORIZONTAL)) { _desktop = SP_ACTIVE_DESKTOP; set_name("RecolorArt"); @@ -80,39 +77,15 @@ RecolorArt::RecolorArt() }); signal_map().connect([&]() { Glib::signal_idle().connect_once([this]() { _desktop->hideSelectionBoxes(true); }); }); _solid_colors->set(Color(0x000000ff)); - auto image = Gtk::make_managed(); - image->set_from_icon_name(INKSCAPE_ICON("shape-link")); - _hue_lock.set_child(*image); - _hue_lock.signal_toggled().connect([this](){_color_wheel->toggleHueLock();}); - _color_wheel_page.append(*_color_wheel); - - _lightness_bar.set_value_pos(Gtk::PositionType::RIGHT); // Show value to the right - _lightness_bar.set_draw_value(true); - _lightness_bar.signal_value_changed().connect([this](){ - double value = _lightness_bar.get_value(); - _color_wheel->setLightness(value); - }); - - _color_wheel_page.append(_lightness_bar); - _color_wheel_page.append(_hue_lock); - _color_wheel_page.append(*_dummie_color_wheel_button); _color_wheel->connect_color_changed(static_cast>([this]() { if(_is_updating) return; - auto css_provider = Gtk::CssProvider::create(); uint32_t cc = _color_wheel->getColor().toRGBA(); Color c(cc,true); - std::string css = - "button.color-preview { background-color: " + c.toString(true) + "; background-image : none; }"; - - css_provider->load_from_data(css); - - auto context = _dummie_color_wheel_button->get_style_context(); - context->add_provider(css_provider, GTK_STYLE_PROVIDER_PRIORITY_USER); - context->add_class("color-preview"); - std::cout << "button color : " << c.toString(true) << std::endl; if(_color_wheel->getActiveIndex() != -1) { int index = _color_wheel->getActiveIndex(); _current_color_id = colors[index].toString(true); + auto idx = findColorItemByKey(_current_color_id); + _selection_model->set_selected(idx.second); onColorPickerChanged(c, true); onOriginalColorClicked(_current_color_id); if (_color_wheel->getHueLock()) { @@ -142,17 +115,7 @@ RecolorArt::RecolorArt() resetOpacity(); })); - _notebook.signal_switch_page().connect([this](Gtk::Widget *page, guint page_num) { - int wheel_index = _notebook.page_num(_color_wheel_page); - if (static_cast(page_num) == wheel_index) { - _is_wheel_page = true; - _color_picker_wdgt->set_visible(false); - } else { - _is_wheel_page = false; - _color_picker_wdgt->set_visible(true); - } - }); layoutColorPicker(); _live_preview.signal_toggled().connect(sigc::mem_fun(*this, &RecolorArt::onLivePreviewToggled)); @@ -160,9 +123,11 @@ RecolorArt::RecolorArt() _reset.signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::onResetClicked)); _list_view = _builder->get_widget("recolor-art-list"); + _grid_view = _builder->get_widget("recolor-art-grid"); _color_model = Gio::ListStore::create(); _selection_model = Gtk::SingleSelection::create(_color_model); _color_factory = Gtk::SignalListItemFactory::create(); + _color_squares_factory = Gtk::SignalListItemFactory::create(); _color_factory->signal_setup().connect([](Glib::RefPtr const &list_item) { auto box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); @@ -261,8 +226,35 @@ RecolorArt::RecolorArt() } }); + + _color_squares_factory->signal_setup().connect([](Glib::RefPtr const &list_item) { + auto color_preview = Gtk::make_managed(Color(0x00000000).toRGBA()); + color_preview->set_border_radius(2); + color_preview->setStyle(color_preview->Style::Outlined); + color_preview->set_size_request(20, 20); + list_item->set_child(*color_preview); + }); + + _color_squares_factory->signal_bind().connect([this](Glib::RefPtr const &list_item) { + auto item = std::dynamic_pointer_cast(list_item->get_item()); + if (!item) return; + auto preview = dynamic_cast(list_item->get_child()); + auto item_controller = Gtk::EventControllerMotion::create(); + item_controller->signal_enter().connect([preview, item, this](double x, double y) { getSelection(item->key); }); + item_controller->signal_leave().connect([preview, this]() { resetOpacity(); }); + preview->add_controller(item_controller); + auto rgba = item->new_color.toRGBA(); + preview->setRgba32(rgba); + + }); + + _list_view->set_model(_selection_model); _list_view->set_factory(_color_factory); + + _grid_view->set_model(_selection_model); + _grid_view->set_factory(_color_squares_factory); + auto lm = _list_view->get_layout_manager(); if (auto grid_layout = std::dynamic_pointer_cast(lm)) { grid_layout->set_row_spacing(0); @@ -283,6 +275,7 @@ RecolorArt::RecolorArt() onOriginalColorClicked(color_item->key); }); + _color_wheel_page.append(*_color_wheel); // _apply = _builder->get_widget("apply"); // _apply->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::_onApplyButtonClicked)); } @@ -500,10 +493,6 @@ void RecolorArt::layoutColorPicker(std::shared_ptr updated_col for (auto child : container->get_children()) container->remove(*child); container->append(*_color_picker_wdgt); - if (_is_wheel_page) - _color_picker_wdgt->set_visible(false); - else - _color_picker_wdgt->set_visible(true); } else { g_warning("color picker not found"); } @@ -864,30 +853,4 @@ void RecolorArt::performUpdate() } } // namespace Widget } // namespace UI -} // namespace Inkscape - -// void RecolorArt::_onApplyButtonClicked() -// { -// for (auto [key, items] : _selected_colors) { -// std::string _color_string = items.second.value().new_color.toString(); -// for (auto &item : items.first) { -// SPCSSAttr *css = sp_repr_css_attr_new(); -// sp_repr_css_set_property_string(css, item.kind.c_str(), _color_string); -// sp_desktop_apply_css_recursive(item.item, css, true); -// sp_repr_css_attr_unref(css); -// } -// } -// g_message("apply clicked"); -// } -// if (!_gradient_stops.empty()) { -// for (auto [key, value] : _gradient_stops) { -// std::cout << key << " : "; -// for (auto stop : value) -// std::cout << stop << " "; -// std::cout << std::endl; -// } -// g_message("filled stops map"); - -// } else { -// g_message("empty stops map"); -// } \ No newline at end of file +} // namespace Inkscape \ No newline at end of file diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index d75e637eef..d4bf70f595 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#ifndef SEEN_DIALOGS_SP_RECOLOR_ART_H -#define SEEN_DIALOGS_SP_RECOLOR_ART_H +#ifndef WIDGET_RECOLOR_ART_H +#define WIDGET_RECOLOR_ART_H #include #include @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,7 @@ #include "ui/widget/paint-selector.h" #include "ui/widget/ink-color-wheel.h" #include "src/colors/color-set.h" +#include "multi-marker-color-plate.h" using namespace Inkscape::Colors; @@ -93,33 +95,27 @@ private: std::map, std::optional>> _selected_colors; Gtk::Box &_color_list ; Gtk::Button &_reset; - Gtk::ToggleButton &_hue_lock; Gtk::CheckButton &_live_preview; Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr ; Gtk::ListView *_list_view = nullptr; + Gtk::GridView *_grid_view = nullptr; std::string _current_color_id; - std::map _type_boxes; bool _is_preview = false; Glib::RefPtr> _color_model; Glib::RefPtr _color_factory; + Glib::RefPtr _color_squares_factory; Glib::RefPtr _selection_model; std::map> _gradient_stops; - MultiMarkerWheel *_color_wheel = nullptr; + MultiMarkerColorPlate *_color_wheel = nullptr; std::vector colors; std::mapcolor_wheel_colors_map; int colors_index=0; bool _is_updating = false; bool _is_wheel_page = false; - Glib::RefPtr adjustment = Gtk::Adjustment::create(100.0, 0.0, 100.0, 1.0, 10.0); - Gtk::Scale& _lightness_bar; - - Gtk::Button* _dummie_color_wheel_button = nullptr; - - // Gtk::Button *_apply = nullptr; void populateMap(Color color, SPObject *style, std::string kind); void collectColors(std::vector& items,std::string kind=""); @@ -170,4 +166,4 @@ public: } // namespace UI } // namespace Inkscape -#endif // SEEN_DIALOGS_SP_RECOLOR_ART_H +#endif // WIDGET_RECOLOR_ART_H -- GitLab From 4d3f06b0b9ac620af102f83ace132fe59fdeebbf Mon Sep 17 00:00:00 2001 From: ftomara Date: Tue, 19 Aug 2025 13:43:52 +0300 Subject: [PATCH 101/122] removed grid and made some ui refinements --- share/ui/recolor-art.glade | 30 ---------------------- src/ui/widget/multi-marker-color-plate.cpp | 30 +++++++++++----------- src/ui/widget/recolor-art.cpp | 26 ------------------- src/ui/widget/recolor-art.h | 1 - 4 files changed, 15 insertions(+), 72 deletions(-) diff --git a/share/ui/recolor-art.glade b/share/ui/recolor-art.glade index 90674d0f91..4149daffe5 100644 --- a/share/ui/recolor-art.glade +++ b/share/ui/recolor-art.glade @@ -119,36 +119,6 @@ vertical true true - - - - true - true - true - never - false - 80 - - - colors-grid - vertical - true - fill - fill - 16 - - - false - fill - true - fill - - - - - - - diff --git a/src/ui/widget/multi-marker-color-plate.cpp b/src/ui/widget/multi-marker-color-plate.cpp index 13f54f54c8..9c6289fe74 100644 --- a/src/ui/widget/multi-marker-color-plate.cpp +++ b/src/ui/widget/multi-marker-color-plate.cpp @@ -86,7 +86,8 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c _spaces_combo->set_tooltip_text(_("Choose style of color selection")); _spaces_combo->set_hexpand(false); _spaces_combo->set_halign(Gtk::Align::END); - _spaces_combo->set_margin_top(8); + _spaces_combo->set_margin_top(4); + _spaces_combo->set_margin_bottom(8); _spaces_combo->signal_changed().connect([this](int index) { _specific_colors = _color_sets[index].second; @@ -131,27 +132,29 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c _hue_lock.set_tooltip_text("lock hue angles for colors set"); _hue_lock.set_hexpand(false); _hue_lock.set_margin_top(8); - _hue_lock.set_halign(Gtk::Align::START); + _hue_lock.set_halign(Gtk::Align::END); + + + _color_wheel_preview->set_hexpand(false); + _color_wheel_preview->set_can_focus(false); + _color_wheel_preview->set_size_request(35,35); + _color_wheel_preview->set_halign(Gtk::Align::START); + _color_wheel_preview->set_margin_top(8); + _color_wheel_preview->setStyle(_color_wheel_preview->Style::Outlined); auto box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); - box->set_spacing(120); + box->set_spacing(170); + box->append(*_color_wheel_preview); box->append(_hue_lock); - box->append(*_spaces_combo); _lightness_box->append(*_lightness_label); _lightness_box->append(_lightness_bar); _spaces_stack->set_visible_child("RGB"); - _color_wheel_preview->set_hexpand(false); - _color_wheel_preview->set_size_request(35,35); - _color_wheel_preview->set_halign(Gtk::Align::START); - _color_wheel_preview->set_margin_top(8); - _color_wheel_preview->setStyle(_color_wheel_preview->Style::Outlined); - // _color_wheel_preview->set_margin_start(8); + append(*box); - append(*_color_wheel_preview); append(*_color_wheel); append(*_lightness_box); append(*_spaces_combo); @@ -168,16 +171,13 @@ MultiMarkerColorPlate::~MultiMarkerColorPlate() { void MultiMarkerColorPlate::_addPageForSpace(std::shared_ptr space, int page_num) { auto mode_name = space->getName(); - if (mode_name == "RGB" || mode_name == "HSL") - _spaces_combo->add_row(space->getIcon(), mode_name, page_num); + _spaces_combo->add_row(space->getIcon(), mode_name, page_num); } void MultiMarkerColorPlate::_createSlidersForSpace(std::shared_ptr space, std::shared_ptr &colors, int index) { auto mode_name = space->getName(); - if (mode_name != "RGB" && mode_name != "HSL") - return; Gtk::Grid *_grid = Gtk::make_managed(); auto new_colors = std::make_shared(space, colors->getAlphaConstraint().value_or(true)); new_colors->set(colors->get().value()); diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 035d02abce..1fa21f4639 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -123,7 +123,6 @@ RecolorArt::RecolorArt() _reset.signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::onResetClicked)); _list_view = _builder->get_widget("recolor-art-list"); - _grid_view = _builder->get_widget("recolor-art-grid"); _color_model = Gio::ListStore::create(); _selection_model = Gtk::SingleSelection::create(_color_model); _color_factory = Gtk::SignalListItemFactory::create(); @@ -226,34 +225,9 @@ RecolorArt::RecolorArt() } }); - - _color_squares_factory->signal_setup().connect([](Glib::RefPtr const &list_item) { - auto color_preview = Gtk::make_managed(Color(0x00000000).toRGBA()); - color_preview->set_border_radius(2); - color_preview->setStyle(color_preview->Style::Outlined); - color_preview->set_size_request(20, 20); - list_item->set_child(*color_preview); - }); - - _color_squares_factory->signal_bind().connect([this](Glib::RefPtr const &list_item) { - auto item = std::dynamic_pointer_cast(list_item->get_item()); - if (!item) return; - auto preview = dynamic_cast(list_item->get_child()); - auto item_controller = Gtk::EventControllerMotion::create(); - item_controller->signal_enter().connect([preview, item, this](double x, double y) { getSelection(item->key); }); - item_controller->signal_leave().connect([preview, this]() { resetOpacity(); }); - preview->add_controller(item_controller); - auto rgba = item->new_color.toRGBA(); - preview->setRgba32(rgba); - - }); - - _list_view->set_model(_selection_model); _list_view->set_factory(_color_factory); - _grid_view->set_model(_selection_model); - _grid_view->set_factory(_color_squares_factory); auto lm = _list_view->get_layout_manager(); if (auto grid_layout = std::dynamic_pointer_cast(lm)) { diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index d4bf70f595..309e99815a 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -98,7 +98,6 @@ private: Gtk::CheckButton &_live_preview; Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr ; Gtk::ListView *_list_view = nullptr; - Gtk::GridView *_grid_view = nullptr; std::string _current_color_id; bool _is_preview = false; -- GitLab From 477a60c5fecce9db1ab9e0d4d55ed208265c32af Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 21 Aug 2025 21:54:12 +0300 Subject: [PATCH 102/122] fixed lightness & huelock logic --- src/ui/widget/ink-color-wheel.cpp | 23 ++++++++++++++++++++-- src/ui/widget/ink-color-wheel.h | 4 +++- src/ui/widget/multi-marker-color-plate.cpp | 2 +- src/ui/widget/multi-marker-color-plate.h | 3 ++- src/ui/widget/recolor-art.cpp | 2 +- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/ui/widget/ink-color-wheel.cpp b/src/ui/widget/ink-color-wheel.cpp index d863cbdbdc..28ca0ddcf9 100644 --- a/src/ui/widget/ink-color-wheel.cpp +++ b/src/ui/widget/ink-color-wheel.cpp @@ -963,9 +963,28 @@ bool MultiMarkerWheel::changeColor(int index, Colors::Color& color) void MultiMarkerWheel::setLightness(double value) { - lightness = value/100.0; + lightness = value / 100.0; _source_ring.reset(); - color_changed(); + if (_hue_lock) { + std::vector new_colors; + for (auto color : _values_vector) { + color.set(2, lightness); + new_colors.push_back(color); + } + if (!new_colors.empty()) { + setColor(new_colors); + } + } + else + { + int index = getActiveIndex(); + if(index>-1) + { + _values_vector[index].set(2,lightness); + color_changed(); + } + } + } void MultiMarkerWheel::on_drawing_area_size(int width, int height, int baseline) diff --git a/src/ui/widget/ink-color-wheel.h b/src/ui/widget/ink-color-wheel.h index afad0b2e02..636651976f 100644 --- a/src/ui/widget/ink-color-wheel.h +++ b/src/ui/widget/ink-color-wheel.h @@ -268,10 +268,11 @@ public: } bool changeColor(int index , Colors::Color& color); sigc::connection connect_color_hovered(sigc::slot slot) { return _signal_color_hovered.connect(std::move(slot)); } - void toggleHueLock(){_hue_lock = !_hue_lock ;} + void toggleHueLock(bool locked){_hue_lock = locked ;} bool getHueLock(){return _hue_lock;} std::vector getColors(){return _values_vector ;} void setLightness(double value); + // bool isLightnessChanged(){return _lightness_changed;} private: void on_drawing_area_size(int width, int height, int baseline) override; @@ -326,6 +327,7 @@ private: static constexpr double marker_click_tolerance = 5.0; sigc::signal _signal_color_hovered; double lightness = 1.0; + // bool _lightness_changed = false; void update_ring_source(); }; diff --git a/src/ui/widget/multi-marker-color-plate.cpp b/src/ui/widget/multi-marker-color-plate.cpp index 9c6289fe74..7c230ec253 100644 --- a/src/ui/widget/multi-marker-color-plate.cpp +++ b/src/ui/widget/multi-marker-color-plate.cpp @@ -120,7 +120,7 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c _hue_lock_image->set_from_icon_name(INKSCAPE_ICON("object-unlocked")); _hue_lock.set_child(*_hue_lock_image); _hue_lock.signal_toggled().connect([this]() { - _color_wheel->toggleHueLock(); + _color_wheel->toggleHueLock(_hue_lock.get_active()); if (_hue_lock.get_active()) { _hue_lock_image->set_from_icon_name(INKSCAPE_ICON("object-locked")); _hue_lock.set_child(*_hue_lock_image); diff --git a/src/ui/widget/multi-marker-color-plate.h b/src/ui/widget/multi-marker-color-plate.h index e49f9a995a..019338703b 100644 --- a/src/ui/widget/multi-marker-color-plate.h +++ b/src/ui/widget/multi-marker-color-plate.h @@ -70,10 +70,11 @@ public: Colors::Color getColor() { return _color_wheel->getColor(); } std::vector getColors() { return _color_wheel->getColors(); } bool getHueLock() { return _color_wheel->getHueLock(); } - void toggleHueLock() { _color_wheel->toggleHueLock(); } + void toggleHueLock(bool locked) { _color_wheel->toggleHueLock(locked); } int getActiveIndex() { return _color_wheel->getActiveIndex(); } void setActiveIndex(int index) { _color_wheel->setActiveIndex(index); } int getHoverIndex() { return _color_wheel->getHoverIndex(); } + // bool isLightnessChanged(){return _color_wheel->isLightnessChanged();} sigc::connection connect_color_hovered(sigc::slot slot) { return _color_wheel->connect_color_hovered(slot); diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 1fa21f4639..92178e28ea 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -652,7 +652,7 @@ void RecolorArt::lpChecked(Color color, bool wheel) } void RecolorArt::onResetClicked() { - if(!_color_wheel->getHueLock()) _color_wheel->toggleHueLock(); + _color_wheel->toggleHueLock(false); _color_wheel->setLightness(100.0); _color_wheel->setColor(colors); updateColorModel(); -- GitLab From efdff379e31d04d8cf19e43d312e6ad0fe85cd99 Mon Sep 17 00:00:00 2001 From: ftomara Date: Fri, 22 Aug 2025 01:27:32 +0300 Subject: [PATCH 103/122] added lightness icon to lightness scale --- .../symbolic/actions/lightness-symbolic.svg | 115 ++++++++++++++++++ .../symbolic/actions/lightness-symbolic.svg | 115 ++++++++++++++++++ .../symbolic/actions/lightness-symbolic.svg | 115 ++++++++++++++++++ src/ui/widget/multi-marker-color-plate.cpp | 4 +- src/ui/widget/multi-marker-color-plate.h | 3 +- 5 files changed, 350 insertions(+), 2 deletions(-) create mode 100644 share/icons/Dash/symbolic/actions/lightness-symbolic.svg create mode 100644 share/icons/hicolor/symbolic/actions/lightness-symbolic.svg create mode 100644 share/icons/multicolor/symbolic/actions/lightness-symbolic.svg diff --git a/share/icons/Dash/symbolic/actions/lightness-symbolic.svg b/share/icons/Dash/symbolic/actions/lightness-symbolic.svg new file mode 100644 index 0000000000..1e8d4bc38e --- /dev/null +++ b/share/icons/Dash/symbolic/actions/lightness-symbolic.svg @@ -0,0 +1,115 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/share/icons/hicolor/symbolic/actions/lightness-symbolic.svg b/share/icons/hicolor/symbolic/actions/lightness-symbolic.svg new file mode 100644 index 0000000000..1e8d4bc38e --- /dev/null +++ b/share/icons/hicolor/symbolic/actions/lightness-symbolic.svg @@ -0,0 +1,115 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/share/icons/multicolor/symbolic/actions/lightness-symbolic.svg b/share/icons/multicolor/symbolic/actions/lightness-symbolic.svg new file mode 100644 index 0000000000..1e8d4bc38e --- /dev/null +++ b/share/icons/multicolor/symbolic/actions/lightness-symbolic.svg @@ -0,0 +1,115 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/ui/widget/multi-marker-color-plate.cpp b/src/ui/widget/multi-marker-color-plate.cpp index 7c230ec253..45073a54db 100644 --- a/src/ui/widget/multi-marker-color-plate.cpp +++ b/src/ui/widget/multi-marker-color-plate.cpp @@ -108,6 +108,8 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c _addPageForSpace(space, index++); } + _lightness_icon->set_from_icon_name(INKSCAPE_ICON("lightness")); + _lightness_icon->set_tooltip_text("change lightness for all if hue lock is on"); _lightness_bar.set_value_pos(Gtk::PositionType::RIGHT); _lightness_bar.set_hexpand(true); _lightness_bar.set_draw_value(true); @@ -147,7 +149,7 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c box->append(*_color_wheel_preview); box->append(_hue_lock); - _lightness_box->append(*_lightness_label); + _lightness_box->append(*_lightness_icon); _lightness_box->append(_lightness_bar); _spaces_stack->set_visible_child("RGB"); diff --git a/src/ui/widget/multi-marker-color-plate.h b/src/ui/widget/multi-marker-color-plate.h index 019338703b..5d30f3f3a5 100644 --- a/src/ui/widget/multi-marker-color-plate.h +++ b/src/ui/widget/multi-marker-color-plate.h @@ -92,7 +92,8 @@ public: private: MultiMarkerWheel *_color_wheel = nullptr; - Gtk::Label *_lightness_label = Gtk::make_managed("Lightness : "); + Gtk::Image*_lightness_icon = Gtk::make_managed(); + // Gtk::Label *_lightness_label = Gtk::make_managed("Lightness : "); Gtk::Box *_lightness_box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); Glib::RefPtr adjustment = Gtk::Adjustment::create(100.0, 0.0, 100.0, 1.0, 10.0); Gtk::Scale &_lightness_bar; -- GitLab From 876d13abd5ad410d894eba9685c476cd9cbca321 Mon Sep 17 00:00:00 2001 From: ftomara Date: Fri, 22 Aug 2025 03:30:33 +0300 Subject: [PATCH 104/122] added saturation scale to colorWheel page --- .../symbolic/actions/saturation-symbolic.svg | 1 + .../symbolic/actions/saturation-symbolic.svg | 1 + .../symbolic/actions/saturation-symbolic.svg | 1 + src/ui/widget/ink-color-wheel.cpp | 26 +++++++++++++++++++ src/ui/widget/ink-color-wheel.h | 2 ++ src/ui/widget/multi-marker-color-plate.cpp | 18 ++++++++++++- src/ui/widget/multi-marker-color-plate.h | 13 ++++++++++ src/ui/widget/recolor-art.cpp | 1 + 8 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 share/icons/Dash/symbolic/actions/saturation-symbolic.svg create mode 100644 share/icons/hicolor/symbolic/actions/saturation-symbolic.svg create mode 100644 share/icons/multicolor/symbolic/actions/saturation-symbolic.svg diff --git a/share/icons/Dash/symbolic/actions/saturation-symbolic.svg b/share/icons/Dash/symbolic/actions/saturation-symbolic.svg new file mode 100644 index 0000000000..7f0b0fda5a --- /dev/null +++ b/share/icons/Dash/symbolic/actions/saturation-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/share/icons/hicolor/symbolic/actions/saturation-symbolic.svg b/share/icons/hicolor/symbolic/actions/saturation-symbolic.svg new file mode 100644 index 0000000000..7f0b0fda5a --- /dev/null +++ b/share/icons/hicolor/symbolic/actions/saturation-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/share/icons/multicolor/symbolic/actions/saturation-symbolic.svg b/share/icons/multicolor/symbolic/actions/saturation-symbolic.svg new file mode 100644 index 0000000000..7f0b0fda5a --- /dev/null +++ b/share/icons/multicolor/symbolic/actions/saturation-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/ui/widget/ink-color-wheel.cpp b/src/ui/widget/ink-color-wheel.cpp index 28ca0ddcf9..938576d117 100644 --- a/src/ui/widget/ink-color-wheel.cpp +++ b/src/ui/widget/ink-color-wheel.cpp @@ -987,6 +987,32 @@ void MultiMarkerWheel::setLightness(double value) } +void MultiMarkerWheel::setSaturation(double value) +{ + saturation = value / 100.0; + _source_ring.reset(); + if (_hue_lock) { + std::vector new_colors; + for (auto color : _values_vector) { + color.set(1, saturation); + new_colors.push_back(color); + } + if (!new_colors.empty()) { + setColor(new_colors); + } + } + else + { + int index = getActiveIndex(); + if(index>-1) + { + _values_vector[index].set(1,saturation); + color_changed(); + } + } + +} + void MultiMarkerWheel::on_drawing_area_size(int width, int height, int baseline) { auto const size = Geom::IntPoint{width, height}; diff --git a/src/ui/widget/ink-color-wheel.h b/src/ui/widget/ink-color-wheel.h index 636651976f..58018b7baf 100644 --- a/src/ui/widget/ink-color-wheel.h +++ b/src/ui/widget/ink-color-wheel.h @@ -272,6 +272,7 @@ public: bool getHueLock(){return _hue_lock;} std::vector getColors(){return _values_vector ;} void setLightness(double value); + void setSaturation(double value); // bool isLightnessChanged(){return _lightness_changed;} private: @@ -327,6 +328,7 @@ private: static constexpr double marker_click_tolerance = 5.0; sigc::signal _signal_color_hovered; double lightness = 1.0; + double saturation = 1.0; // bool _lightness_changed = false; void update_ring_source(); }; diff --git a/src/ui/widget/multi-marker-color-plate.cpp b/src/ui/widget/multi-marker-color-plate.cpp index 45073a54db..cc542d70fb 100644 --- a/src/ui/widget/multi-marker-color-plate.cpp +++ b/src/ui/widget/multi-marker-color-plate.cpp @@ -71,6 +71,7 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c , _color_wheel(Gtk::make_managed()) , _hue_lock(*Gtk::make_managed()) , _lightness_bar(*Gtk::make_managed(adjustment, Gtk::Orientation::HORIZONTAL)) + , _saturation_bar(*Gtk::make_managed(_saturation_adjustment, Gtk::Orientation::HORIZONTAL)) , _color_wheel_preview(Gtk::make_managed()) , _grid(Gtk::make_managed()) , _spaces_combo(Gtk::make_managed()) @@ -109,7 +110,7 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c } _lightness_icon->set_from_icon_name(INKSCAPE_ICON("lightness")); - _lightness_icon->set_tooltip_text("change lightness for all if hue lock is on"); + _lightness_icon->set_tooltip_text("change saturation for all if hue lock is on"); _lightness_bar.set_value_pos(Gtk::PositionType::RIGHT); _lightness_bar.set_hexpand(true); _lightness_bar.set_draw_value(true); @@ -118,6 +119,17 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c _color_wheel->setLightness(value); }); + + _saturation_icon->set_from_icon_name(INKSCAPE_ICON("saturation")); + _saturation_icon->set_tooltip_text("change saturation for all if hue lock is on"); + _saturation_bar.set_value_pos(Gtk::PositionType::RIGHT); + _saturation_bar.set_hexpand(true); + _saturation_bar.set_draw_value(true); + _saturation_bar.signal_value_changed().connect([this]() { + double value = _saturation_bar.get_value(); + _color_wheel->setSaturation(value); + }); + _hue_lock_image = Gtk::make_managed(); _hue_lock_image->set_from_icon_name(INKSCAPE_ICON("object-unlocked")); _hue_lock.set_child(*_hue_lock_image); @@ -152,6 +164,9 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c _lightness_box->append(*_lightness_icon); _lightness_box->append(_lightness_bar); + _saturation_box->append(*_saturation_icon); + _saturation_box->append(_saturation_bar); + _spaces_stack->set_visible_child("RGB"); @@ -159,6 +174,7 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c append(*box); append(*_color_wheel); append(*_lightness_box); + append(*_saturation_box); append(*_spaces_combo); append(*_spaces_stack); } diff --git a/src/ui/widget/multi-marker-color-plate.h b/src/ui/widget/multi-marker-color-plate.h index 5d30f3f3a5..f31ea51a2c 100644 --- a/src/ui/widget/multi-marker-color-plate.h +++ b/src/ui/widget/multi-marker-color-plate.h @@ -67,6 +67,13 @@ public: _color_wheel->setLightness(value); _lightness_bar.set_value(value); } + + void setSaturation(double value) + { + _color_wheel->setSaturation(value); + _saturation_bar.set_value(value); + } + Colors::Color getColor() { return _color_wheel->getColor(); } std::vector getColors() { return _color_wheel->getColors(); } bool getHueLock() { return _color_wheel->getHueLock(); } @@ -97,6 +104,12 @@ private: Gtk::Box *_lightness_box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); Glib::RefPtr adjustment = Gtk::Adjustment::create(100.0, 0.0, 100.0, 1.0, 10.0); Gtk::Scale &_lightness_bar; + + Gtk::Image*_saturation_icon = Gtk::make_managed(); + Gtk::Box *_saturation_box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); + Glib::RefPtr _saturation_adjustment = Gtk::Adjustment::create(100.0, 0.0, 100.0, 1.0, 10.0); + Gtk::Scale &_saturation_bar; + Gtk::ToggleButton &_hue_lock; ColorPreview *_color_wheel_preview = nullptr; Manager *manager = &Manager::get(); diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 92178e28ea..70a6c6e6ab 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -654,6 +654,7 @@ void RecolorArt::onResetClicked() { _color_wheel->toggleHueLock(false); _color_wheel->setLightness(100.0); + _color_wheel->setSaturation(100.0); _color_wheel->setColor(colors); updateColorModel(); revertToOriginalColors(true); -- GitLab From 7b3c77a33744cce46aaa5c1125931a83295d7d15 Mon Sep 17 00:00:00 2001 From: ftomara Date: Fri, 22 Aug 2025 20:25:08 +0300 Subject: [PATCH 105/122] fixed hue_lock button look when reseting --- src/ui/widget/multi-marker-color-plate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/widget/multi-marker-color-plate.h b/src/ui/widget/multi-marker-color-plate.h index f31ea51a2c..1dd17873db 100644 --- a/src/ui/widget/multi-marker-color-plate.h +++ b/src/ui/widget/multi-marker-color-plate.h @@ -77,7 +77,7 @@ public: Colors::Color getColor() { return _color_wheel->getColor(); } std::vector getColors() { return _color_wheel->getColors(); } bool getHueLock() { return _color_wheel->getHueLock(); } - void toggleHueLock(bool locked) { _color_wheel->toggleHueLock(locked); } + void toggleHueLock(bool locked) { _color_wheel->toggleHueLock(locked); _hue_lock.set_active(locked);} int getActiveIndex() { return _color_wheel->getActiveIndex(); } void setActiveIndex(int index) { _color_wheel->setActiveIndex(index); } int getHoverIndex() { return _color_wheel->getHoverIndex(); } -- GitLab From 833ddd33767558f57a13431e6199db18aabead9f Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 24 Aug 2025 02:16:15 +0300 Subject: [PATCH 106/122] documented recolor-art class and removed unneccessary code from it --- src/ui/widget/recolor-art.cpp | 371 ++++++++++++++++++++++++---------- src/ui/widget/recolor-art.h | 23 ++- 2 files changed, 278 insertions(+), 116 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 70a6c6e6ab..e14fe01767 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -58,7 +58,14 @@ namespace Inkscape { namespace UI { namespace Widget { - +/* +this class is showed by paint-selector class that has a button +to trigger the popover that has this widget as its child + +related classes : +1- ink-colorwheel for the multimarkercolorwheel in the colorwheel page +2- multi-marker-color-wheel-plate that manges the multimarkercolorwheel and sliders under it +*/ RecolorArt::RecolorArt() : Gtk::Box() , _notebook(*_builder->get_widget("list-wheel-box")) @@ -71,14 +78,17 @@ RecolorArt::RecolorArt() _desktop = SP_ACTIVE_DESKTOP; set_name("RecolorArt"); append(get_widget(_builder, "recolor-art")); + _solid_colors->set(Color(0x000000ff)); + // when recolor widget is closed it resets opacity to mitigate the effect of getSelection function + // and reshow selection boxes again signal_unmap().connect([&]() { resetOpacity(); _desktop->hideSelectionBoxes(false); }); + // hide selection boxes after widget gets mapped (this is why it connects to signal idle to activate after finishing mapping) signal_map().connect([&]() { Glib::signal_idle().connect_once([this]() { _desktop->hideSelectionBoxes(true); }); }); - _solid_colors->set(Color(0x000000ff)); _color_wheel->connect_color_changed(static_cast>([this]() { - if(_is_updating) return; + if(_is_updating) return; // to stop recuresive calling to signal if changed from the color list page uint32_t cc = _color_wheel->getColor().toRGBA(); Color c(cc,true); if(_color_wheel->getActiveIndex() != -1) { @@ -102,7 +112,7 @@ RecolorArt::RecolorArt() } } })); - + // add hover opacity effect when hovering over markers in the wheel _color_wheel->connect_color_hovered(static_cast>([this]() { uint32_t cc = _color_wheel->getColor().toRGBA(); Color c(cc,true); @@ -122,12 +132,13 @@ RecolorArt::RecolorArt() _live_preview.set_active(true); _reset.signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::onResetClicked)); + // setting up list view for the color list _list_view = _builder->get_widget("recolor-art-list"); _color_model = Gio::ListStore::create(); _selection_model = Gtk::SingleSelection::create(_color_model); _color_factory = Gtk::SignalListItemFactory::create(); - _color_squares_factory = Gtk::SignalListItemFactory::create(); + // setup how the list item should look _color_factory->signal_setup().connect([](Glib::RefPtr const &list_item) { auto box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); auto original = Gtk::make_managed(); @@ -179,6 +190,7 @@ RecolorArt::RecolorArt() list_item->set_child(*box); }); + // setup signals for the list item children after they are created _color_factory->signal_bind().connect([this](Glib::RefPtr const &list_item) { auto item = std::dynamic_pointer_cast(list_item->get_item()); if (!item) @@ -188,6 +200,7 @@ RecolorArt::RecolorArt() if (!box || box->get_first_child() == nullptr || box->get_last_child() == nullptr) return; + // for hover effect auto item_controller = Gtk::EventControllerMotion::create(); item_controller->signal_enter().connect([box, item, this](double x, double y) { getSelection(item->key); }); item_controller->signal_leave().connect([box, this]() { resetOpacity(); }); @@ -253,13 +266,7 @@ RecolorArt::RecolorArt() // _apply = _builder->get_widget("apply"); // _apply->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::_onApplyButtonClicked)); } -RecolorArt::~RecolorArt() -{ - if(_solid_color_changed.connected()) - { - _solid_color_changed.disconnect(); - } -} +RecolorArt::~RecolorArt() {} void RecolorArt::setDesktop(SPDesktop *desktop) { @@ -268,10 +275,17 @@ void RecolorArt::setDesktop(SPDesktop *desktop) } g_message("setDesktop\n"); } -void RecolorArt::collectColors(std::vector&items, std::string kind) + +/* +* loops over the vector of objects , firstly try to dynamically cast the spobject to spitem +* if it is casted check if it is a mask or not if mask extract the spobjects +* from it push into vector of spobjects then call collectColors recursivley with this vector +* after this it calls extractObjectColors on the object it self +*/ +void RecolorArt::collectColors(std::vector&objects, std::string kind) { - for (auto item : items) { - auto it = dynamic_cast(item); + for (auto object : objects) { + auto it = dynamic_cast(object); if (it) { auto mask = dynamic_cast(it->getMaskObject()); if (mask) { @@ -282,22 +296,84 @@ void RecolorArt::collectColors(std::vector&items, std::string kind) collectColors(children_vec, "mask"); } } - extractItemColors(item, kind); + extractObjectColors(object, kind); } } -void RecolorArt::extractItemColors(SPObject *item, std::string kind) + +/* +* checks if object is an spgroup if it is loop over group's children +* call extractObjectColors recursivley on group's children +* if it is not group call extractObjectStyle +*/ +void RecolorArt::extractObjectColors(SPObject *object, std::string kind) { - if (auto group = dynamic_cast(item)) { + if (auto group = dynamic_cast(object)) { for (SPObject &child : group->children) { - extractItemColors(&child, kind); + extractObjectColors(&child, kind); + } + } else if (object) { + extractObjectStyle(object, kind); + } +} + +/* +* firstly extract the objects markers value which has 3 markers per object (optional) +* check for fill types (flat fill ,pattern fill , gradient fill) to populate the _selected_colors map +* do same for stroke types +*/ +void RecolorArt::extractObjectStyle(SPObject *object, std::string kind) +{ + // check object style + if (!object || !object->style) + return; + SPStyle *style = object->style; + extractMarkerColors(style->marker_start.get_value(), object); + extractMarkerColors(style->marker_mid.get_value(), object); + extractMarkerColors(style->marker_end.get_value(), object); + + // get flat fills + if (style->fill.isColor()) { + auto color = style->fill.getColor(); + populateMap(color, object, (kind == "" ? "fill" : kind + "-fill")); + } + + // paint server can be pattern or gradient + // get gradient stops strokes + else if (style->fill.isPaintserver()) { + auto ps = style->getFillPaintServer(); + if (auto pattern = dynamic_cast(ps)) { + extractPatternColors(pattern); + std::cout << "pattern detected\n"; + } + extractGradientStops(object, true); + } + + if (style->stroke.isColor()) { + auto color = style->stroke.getColor(); + populateMap(color, object, (kind == "" ? "stroke" : kind + "-stroke")); + } + // get gradient stops strokes + else if (style->stroke.isPaintserver()) { + auto ps = style->getStrokePaintServer(); + if (auto pattern = dynamic_cast(ps)) { + extractPatternColors(pattern); } - } else if (item) { - extractItemStyle(item, kind); + extractGradientStops(object, false); } } -void RecolorArt::extractGradientStops(SPObject *item, bool isFill) + +/* +* check if paint server is spgradient then check if it has patches for extracting mesh gradient +* if it is mesh get its node array and pass it to extractMeshStops +* if not mesh we firstly fork the gradient so we unlink its shared stops with other similar gradients +* so change in selected one doesn't affect the unselected similar one (has same stops colors) +* then call populateStopsMap to save stops refrencess +* then call populateMap to save the spgradient object as a whole to have gradients colors in +* the color list +*/ +void RecolorArt::extractGradientStops(SPObject *object, bool isFill) { - SPPaintServer *paint_server = isFill ? item->style->getFillPaintServer() : item->style->getStrokePaintServer(); + SPPaintServer *paint_server = isFill ? object->style->getFillPaintServer() : object->style->getStrokePaintServer(); if (paint_server && dynamic_cast(paint_server)) { SPGradient *gradient = dynamic_cast(paint_server); if (!gradient) @@ -309,7 +385,7 @@ void RecolorArt::extractGradientStops(SPObject *item, bool isFill) std::unique_ptr nodeArray; if (auto mesh = dynamic_cast(gradient)) { nodeArray = std::make_unique(mesh); - extractMeshStops(nodeArray->nodes, item, "mesh"); + extractMeshStops(nodeArray->nodes, object, "mesh"); } } else { @@ -334,11 +410,16 @@ void RecolorArt::extractGradientStops(SPObject *item, bool isFill) for (auto stop : gradient->getGradientVector().stops) { if (stop.color.has_value()) { // if(kind == "swatch") std::cout<<"swatch found : "<>& mesh_nodes, SPObject *item, std::string kind) { for (auto nodes : mesh_nodes) { @@ -350,6 +431,51 @@ void RecolorArt::extractMeshStops(std::vector>& mesh_n } } } + +/* +* get root pattern then loop over its children and do the whole extraction process by calling +* extractObjectColors to check for spgroups in pattern children +* +*/ +void RecolorArt::extractPatternColors(SPPattern *pattern) +{ + SPPattern *root = pattern->rootPattern(); + for (auto &child : root->children) { + extractObjectColors(&child, "pattern"); + } +} + +/* +* extract marker id from marker to get it by herf from the xml tree +* then try to cast the result to spmarker +* loop over the spmarker children and do the extraction process on every child +* by calling extractObjectColors +*/ +void RecolorArt::extractMarkerColors(Glib::ustring marker, SPObject *object) +{ + // std::cout << "markerout : " << marker << std::endl; + if (marker.size() > 0 && object->document) { + // std::cout << "marker in : " << marker << std::endl; + std::string marker_id = std::string(marker.c_str() + 4, std::strlen(marker.c_str()) - 5); + // std::cout<<"marker id : "<document->getObjectByHref(marker_id); + if (!m) + std::cout << "m is null\n"; + if (auto marker_obj = dynamic_cast(m)) { + for (auto &child : marker_obj->item_list()) { + extractObjectColors(&*child, "marker"); + } + } + } else + return; +} + +/* +* loop over stops list and populate the _gradient_stops +* it has a different type of access than the _selected_colors map +* so it has a independent map as it stores just a part of the item not the whole item +* like _selected_colors map +*/ void RecolorArt::populateStopsMap(SPStop *stop) { g_message("populateStopsMap in"); @@ -359,86 +485,33 @@ void RecolorArt::populateStopsMap(SPStop *stop) stop = stop->getNextStop(); } } + +/* +* populate _selected_colors map with the color as a string key with vector of objects that +* have the same color and a pair of colors that has the old and new colors of type color +* to ensure easy access on both colors +* +*/ void RecolorArt::populateMap(Color color, SPObject *item, std::string kind) { color.addOpacity(); ColorRef ref = ColorRef(item, kind); ColorPair pair = ColorPair(color, color); std::string color_string = color.toString(true); + // search if key exist and just push the object to the objects vector if (_selected_colors.count(color_string)) { _selected_colors[color_string].first.push_back(ref); - } else { + } else { // create key and push the object and their color ref colors.push_back(color); color_wheel_colors_map[color_string]=colors.size()-1; _selected_colors.emplace(color_string, std::make_pair(std::vector{ref}, pair)); } } -void RecolorArt::extractItemStyle(SPObject *item, std::string kind) -{ - // check item style - if (!item || !item->style) - return; - SPStyle *style = item->style; - extractMarkerColors(style->marker_start.get_value(), item); - extractMarkerColors(style->marker_mid.get_value(), item); - extractMarkerColors(style->marker_end.get_value(), item); - // get flat fills - if (style->fill.isColor()) { - auto color = style->fill.getColor(); - populateMap(color, item, (kind == "" ? "fill" : kind + "-fill")); - } - // get gradient stops strokes - else if (style->fill.isPaintserver()) { - auto ps = style->getFillPaintServer(); - if (auto pattern = dynamic_cast(ps)) { - extractPatternColors(pattern); - std::cout << "pattern detected\n"; - } - extractGradientStops(item, true); - } - - if (style->stroke.isColor()) { - auto color = style->stroke.getColor(); - populateMap(color, item, (kind == "" ? "stroke" : kind + "-stroke")); - } - // get gradient stops strokes - else if (style->stroke.isPaintserver()) { - auto ps = style->getStrokePaintServer(); - if (auto pattern = dynamic_cast(ps)) { - extractPatternColors(pattern); - } - extractGradientStops(item, false); - } -} -void RecolorArt::extractPatternColors(SPPattern *pattern) -{ - SPPattern *root = pattern->rootPattern(); - for (auto &child : root->children) { - if (auto group = dynamic_cast(&child)) - extractItemColors(group, "pattern"); - else - extractItemStyle(&child, "pattern"); - } -} -void RecolorArt::extractMarkerColors(Glib::ustring marker, SPObject *item) -{ - // std::cout << "markerout : " << marker << std::endl; - if (marker.size() > 0 && item->document) { - // std::cout << "marker in : " << marker << std::endl; - std::string marker_id = std::string(marker.c_str() + 4, std::strlen(marker.c_str()) - 5); - // std::cout<<"marker id : "<document->getObjectByHref(marker_id); - if (!m) - std::cout << "m is null\n"; - if (auto marker_obj = dynamic_cast(m)) { - for (auto &child : marker_obj->item_list()) { - extractItemColors(&*child, "marker"); - } - } - } else - return; -} +/* +* prepare color model by creating color items and populate the color model +* then push the _list_view to color list page to show it in the ui +*/ void RecolorArt::generateVisualList() { _color_model->remove_all(); @@ -449,18 +522,18 @@ void RecolorArt::generateVisualList() } _color_list.append(*_list_view); } + +/* +* setup the layout of the colornotebook ui in the colorlist page +* connect _solid_colors to color changed signal and call the signal handler +*/ void RecolorArt::layoutColorPicker(std::shared_ptr updated_color) { _color_picker_wdgt = Gtk::make_managed(_solid_colors); _color_picker_wdgt->set_visible(true); _color_picker_wdgt->set_label(_("Selected Color")); - if(_solid_color_changed.connected()) - { - _solid_color_changed.disconnect(); - } - _solid_color_changed = - _solid_colors->signal_changed.connect([this]() { onColorPickerChanged(); }); + _solid_colors->signal_changed.connect([this]() { onColorPickerChanged(); }); auto container = _builder->get_widget("color-picker"); if (container) { @@ -471,6 +544,11 @@ void RecolorArt::layoutColorPicker(std::shared_ptr updated_col g_warning("color picker not found"); } } + +/* +* set colorpreview colors used in color factory signal bind +* +*/ void RecolorArt::colorButtons(Gtk::Box *button, Color color, bool is_original) { if (button) { @@ -484,6 +562,10 @@ void RecolorArt::colorButtons(Gtk::Box *button, Color color, bool is_original) } } } + +/* +* set up the type box which shows the color usage in what kind (fill,strok,pattern...etc) +*/ void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) { if (!box->get_children().empty()) @@ -556,6 +638,10 @@ void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) box->set_tooltip_text(tooltip); } } + +/* +* finding a color model item by key +*/ std::pair, guint> RecolorArt::findColorItemByKey(std::string const &key) { for (auto i = 0; i < _color_model->get_n_items(); i++) { @@ -567,6 +653,11 @@ std::pair, guint> RecolorArt::findColorItemByKey(std::st } return {nullptr, -1}; } + +/* +* signal handler to set solid colors(color notebook at color list page),_color_picker_wdgt and the active index in +* colorwheel page to the color of the colorpreview clicked +*/ void RecolorArt::onOriginalColorClicked(std::string color_id) { if (_color_wheel && !color_wheel_colors_map.empty()) @@ -575,10 +666,21 @@ void RecolorArt::onOriginalColorClicked(std::string color_id) auto it = _selected_colors.find(color_id); if (it != _selected_colors.end() && it->second.second.has_value()) { Color color = it->second.second.value().new_color; - _solid_colors->set(color); - _color_picker_wdgt->setCurrentColor(_solid_colors); + _solid_colors->set(color); // update sliders under the colorwheel in the colorlist page + _color_picker_wdgt->setCurrentColor(_solid_colors); /* solves the issue of needing to create new + colornotebook every time the _solid_colors changes because it only changes the sliders not the + color wheel it self in colornotebook */ } } + +/* +* this is a signal handler for when solid color changes either in the sliders or the color wheels in +* both notebook pages +* searches for the selected color items then change them through lpchecked() function and update the pair +* in _selected_colors map +* sync the change through notebook pages what happens in one get updated in the other +* update color model item to refresh the listview ui +*/ void RecolorArt::onColorPickerChanged(Color color, bool wheel) { std::optional new_color = wheel ? color : _solid_colors->get(); @@ -590,6 +692,7 @@ void RecolorArt::onColorPickerChanged(Color color, bool wheel) auto _selected = _selected_colors.find(_current_color_id); if (_selected != _selected_colors.end()) _selected->second.second.value().new_color = new_color.value(); + // apply changes to selected items if (_live_preview.property_active()) { if (wheel) lpChecked(color, wheel); @@ -598,13 +701,14 @@ void RecolorArt::onColorPickerChanged(Color color, bool wheel) } guint index = _selection_model->get_selected(); Glib::RefPtr item = nullptr; + // if change is coming from colorlist page sync that to colorwheel page if (!wheel){ item = _color_model->get_item(index); int i = color_wheel_colors_map[_current_color_id]; _is_updating = true; _color_wheel->changeColor(i,new_color.value()); } - else { + else { // if change is coming from colorwheel page sync that to colorlist page auto item_index = findColorItemByKey(_current_color_id); item = item_index.first; index = item_index.second; @@ -613,12 +717,19 @@ void RecolorArt::onColorPickerChanged(Color color, bool wheel) g_message("ERROR: item is null"); return; } + // update colormodel item to refresh listview ui auto color_item = std::dynamic_pointer_cast(item); auto new_item = ColorItem::create(color_item->key, color_item->old_color, new_color.value()); _color_model->splice(index, 1, {new_item}); _is_updating = false; // g_message("color picker changed"); } + +/* +* if LP is checked it searches for the items that has a key matching to the parameter color +* and loop on them to change their color lively +* put the recolor action into the undo stack as well +*/ void RecolorArt::lpChecked(Color color, bool wheel) { auto _selected = _selected_colors.find(_current_color_id); @@ -650,6 +761,11 @@ void RecolorArt::lpChecked(Color color, bool wheel) recolorStops(_selected->first, new_color.value()); DocumentUndo::done(_desktop->getDocument(), _("Recolored items"), INKSCAPE_ICON("object-recolor-art")); } + +/* +* signal function handler for reset button clicked +* that reset every thing to its original states +*/ void RecolorArt::onResetClicked() { _color_wheel->toggleHueLock(false); @@ -664,6 +780,11 @@ void RecolorArt::onResetClicked() onOriginalColorClicked(color_item->key); } + +/* +* reset selected object colors to their original colors all at once +* used when LP checkbox is unchecked +*/ void RecolorArt::revertToOriginalColors(bool is_reset_clicked) { for (auto &[key, items] : _selected_colors) { @@ -685,6 +806,11 @@ void RecolorArt::revertToOriginalColors(bool is_reset_clicked) recolorStops(key, items.second.value().old_color); } } + +/* +* convert selected object colors to the new choosen colors all at once +* used when LP checkbox is unchecked then checked again +*/ void RecolorArt::convertToRecoloredColors() { for (auto [key, items] : _selected_colors) { @@ -707,6 +833,10 @@ void RecolorArt::convertToRecoloredColors() } } } + +/* +* update color model to refresh the listview ui with the new chossen colors +*/ void RecolorArt::updateColorModel(std::vector new_colors) { std::vector> new_colors_buttons; @@ -720,6 +850,11 @@ void RecolorArt::updateColorModel(std::vector new_colors) } _color_model->splice(0, _color_model->get_n_items(), new_colors_buttons); } + +/* +* get stops vector from the _gradient_stops map and loop over it to +* set them to the new color +*/ void RecolorArt::recolorStops(std::string old_color, Color new_color) { auto stops_vector = _gradient_stops.find(old_color); @@ -729,6 +864,12 @@ void RecolorArt::recolorStops(std::string old_color, Color new_color) } } } + +/* +* loop over selection and lowers opacity for items with color +* that doesn't match the parameter color for when user hovers on +* any colorpreview in the list to highlight the hovered on colored objects +*/ void RecolorArt::getSelection(std::string color) { for (auto &[key, value] : _selected_colors) { @@ -754,6 +895,12 @@ void RecolorArt::getSelection(std::string color) } } } + +/* +* loop over selected objects and reset their opacity to 100 if the user isnt hovering over the +* color preview or the widget is closed +* it is the undo of the getSelection function +*/ void RecolorArt::resetOpacity() { for (auto &[key, value] : _selected_colors) { @@ -774,6 +921,11 @@ void RecolorArt::resetOpacity() recolorStops(key, value.second.value().new_color); } } + +/* +* apply recoloring when th LP check box is checked +* and get back to original colors when it is unchecked +*/ void RecolorArt::onLivePreviewToggled() { _is_preview = _live_preview.property_active(); @@ -785,18 +937,22 @@ void RecolorArt::onLivePreviewToggled() g_message(_is_preview ? "is true" : "is false"); g_message("LP toggled"); } -bool RecolorArt::selectionSize() -{ - if (_desktop && _desktop->getSelection()->size() > 1) { - return true; - } - return false; -} +/* +* set paint selector to avoid recuresive signals calling +*/ void RecolorArt::setPaintSelector(PaintSelector *ps) { _paint_selector = ps; } +/* +* main function that : +* 1- clears old data +* 2- get selection items from desktop +* 3- unlink selection items if there are clones +* 4- call collect colors func +* 5- put the generated list in the UI +*/ void RecolorArt::performUpdate() { for (auto child : _color_list.get_children()) { @@ -826,6 +982,7 @@ void RecolorArt::performUpdate() g_message("Desktop is NULL in Performupdate in recolor widegt\n"); } + } // namespace Widget } // namespace UI } // namespace Inkscape \ No newline at end of file diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 309e99815a..63e318fea3 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -2,7 +2,14 @@ #ifndef WIDGET_RECOLOR_ART_H #define WIDGET_RECOLOR_ART_H - +/* + * + * Authors: + * Fatma Omara + * + * Copyright (C) 2025 authors + * + */ #include #include #include @@ -103,7 +110,6 @@ private: Glib::RefPtr> _color_model; Glib::RefPtr _color_factory; - Glib::RefPtr _color_squares_factory; Glib::RefPtr _selection_model; std::map> _gradient_stops; @@ -117,13 +123,13 @@ private: bool _is_wheel_page = false; void populateMap(Color color, SPObject *style, std::string kind); - void collectColors(std::vector& items,std::string kind=""); - void extractGradientStops(SPObject *item, bool isFill); - void extractMeshStops(std::vector>& mesh_nodes, SPObject *item, std::string kind); - void extractItemColors(SPObject *item,std::string kind=""); - void extractItemStyle(SPObject *item ,std::string kind=""); + void collectColors(std::vector& objects,std::string kind=""); + void extractGradientStops(SPObject *object, bool isFill); + void extractMeshStops(std::vector>& mesh_nodes, SPObject *object, std::string kind); + void extractObjectColors(SPObject *object,std::string kind=""); + void extractObjectStyle(SPObject *object ,std::string kind=""); void extractPatternColors(SPPattern *pattern); - void extractMarkerColors(Glib::ustring marker, SPObject *item); + void extractMarkerColors(Glib::ustring marker, SPObject *object); void generateVisualList(); void layoutColorPicker(std::shared_ptr updated_color = nullptr); void colorButtons(Gtk::Box *button, Color color, bool is_original = false); @@ -157,7 +163,6 @@ public: void performUpdate(); bool isInPreviewMode() { return _is_preview; } void setDesktop(SPDesktop *desktop); - bool selectionSize(); void setPaintSelector(PaintSelector *ps); }; -- GitLab From fa55000d0905dbc2b07bff4e8a717c911097ad30 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 24 Aug 2025 15:54:44 +0300 Subject: [PATCH 107/122] fixed crash when lighness and saturation changed for all colors --- src/ui/widget/ink-color-wheel.cpp | 33 ++++++++++++++----------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/ui/widget/ink-color-wheel.cpp b/src/ui/widget/ink-color-wheel.cpp index 938576d117..59dec6ff0f 100644 --- a/src/ui/widget/ink-color-wheel.cpp +++ b/src/ui/widget/ink-color-wheel.cpp @@ -966,25 +966,22 @@ void MultiMarkerWheel::setLightness(double value) lightness = value / 100.0; _source_ring.reset(); if (_hue_lock) { - std::vector new_colors; - for (auto color : _values_vector) { - color.set(2, lightness); - new_colors.push_back(color); - } - if (!new_colors.empty()) { - setColor(new_colors); + for (size_t i = 0; i < _values_vector.size(); i++) { + _values_vector[i].set(2, lightness); + if (i < _markers_points.size()) { + _markers_points[i].reset(); + } } - } - else - { + color_changed(); + } else { int index = getActiveIndex(); if(index>-1) { _values_vector[index].set(2,lightness); + _markers_points[index].reset(); color_changed(); } } - } void MultiMarkerWheel::setSaturation(double value) @@ -992,14 +989,13 @@ void MultiMarkerWheel::setSaturation(double value) saturation = value / 100.0; _source_ring.reset(); if (_hue_lock) { - std::vector new_colors; - for (auto color : _values_vector) { - color.set(1, saturation); - new_colors.push_back(color); - } - if (!new_colors.empty()) { - setColor(new_colors); + for (size_t i = 0; i < _values_vector.size(); i++) { + _values_vector[i].set(1, saturation); + if (i < _markers_points.size()) { + _markers_points[i].reset(); + } } + color_changed(); } else { @@ -1007,6 +1003,7 @@ void MultiMarkerWheel::setSaturation(double value) if(index>-1) { _values_vector[index].set(1,saturation); + _markers_points[index].reset(); color_changed(); } } -- GitLab From 5ab5bf8e1c67bf23c4590c20d9eacdfb99254c2b Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 24 Aug 2025 23:06:13 +0300 Subject: [PATCH 108/122] removed unused functions and debugging prints --- src/ui/widget/ink-color-wheel.cpp | 59 ++++++------------------------- src/ui/widget/ink-color-wheel.h | 6 ---- 2 files changed, 10 insertions(+), 55 deletions(-) diff --git a/src/ui/widget/ink-color-wheel.cpp b/src/ui/widget/ink-color-wheel.cpp index 59dec6ff0f..ce7458001e 100644 --- a/src/ui/widget/ink-color-wheel.cpp +++ b/src/ui/widget/ink-color-wheel.cpp @@ -953,11 +953,11 @@ bool MultiMarkerWheel::changeColor(int index, Colors::Color& color) { _markers_points[index].reset(); color_changed(); - std::cout<<"changed color\n"; + // std::cout<<"changed color\n"; return true; } } - std::cout<<"changed color went bad\n"; + // std::cout<<"changed color went bad\n"; return false; } @@ -1087,50 +1087,11 @@ std::optional MultiMarkerWheel::focus(Gtk::DirectionType const direction) return keep_focus; } -bool MultiMarkerWheel::_set_from_xy(double const x, double const y) -{ - auto const [width, height] = *_cache_size; - double const cx = width / 2.0; - double const cy = height / 2.0; - - double const r = std::min(cx, cy) * (1 - _ring_width); - - // We calculate RGB value under the cursor by rotating the cursor - // and triangle by the hue value and looking at position in the - // now right pointing triangle. - double angle = _values[0] * 2 * M_PI; - double sin = std::sin(angle); - double cos = std::cos(angle); - double xp = ((x - cx) * cos - (y - cy) * sin) / r; - double yp = ((x - cx) * sin + (y - cy) * cos) / r; - - double xt = lerp(0.0, 1.0, -0.5, 1.0, xp); - xt = std::clamp(xt, 0.0, 1.0); - - double dy = (1 - xt) * std::cos(M_PI / 6.0); - double yt = lerp(0.0, 1.0, -dy, dy, yp); - yt = std::clamp(yt, 0.0, 1.0); - - ColorPoint c0(0, 0, Color(Type::RGB, {yt, yt, yt})); // Grey point along base. - ColorPoint c1(0, 0, Color(Type::HSV, {_values[0], 1, 1})); // Hue point at apex - ColorPoint c = lerp(c0, c1, 0, 1, xt); - c.color.setOpacity(_values.getOpacity()); // Remember opacity - return setColor(c.color, false); // Don't override previous hue. -} - -// bool MultiMarkerWheel::set_from_xy_delta(double const dx, double const dy) -// { -// auto [mx, my] = get_marker_point(index); -// mx += dx; -// my += dy; -// return _set_from_xy(mx, my); -// } - bool MultiMarkerWheel::_is_in_ring(double x, double y) { - std::cout<<"x: "<= 0 && hover_index < _values_vector.size()) { - std::cout << "hover color : " << _values_vector[hover_index].toString() << std::endl; + // std::cout << "hover color : " << _values_vector[hover_index].toString() << std::endl; queue_drawing_area_draw(); } else { - std::cout << "invalid index : " << hover_index << std::endl; + // std::cout << "invalid index : " << hover_index << std::endl; } } return; @@ -1332,7 +1293,7 @@ MultiMarkerWheel::MinMax const &MultiMarkerWheel::get_radii() auto const [width, height] = *_cache_size; r_max = std::min(width, height) / 2.0 - 2 * (focus_line_width + focus_padding); r_min = r_max * (1.0 - _ring_width); - std::cout<<"r max : "< getColors(){return _values_vector ;} void setLightness(double value); void setSaturation(double value); - // bool isLightnessChanged(){return _lightness_changed;} - private: void on_drawing_area_size(int width, int height, int baseline) override; void on_drawing_area_draw(Cairo::RefPtr const &cr, int, int) override; std::optional focus(Gtk::DirectionType direction) override; - - bool _set_from_xy(double x, double y); - bool set_from_xy_delta(double dx, double dy); bool _is_in_ring(double x, double y); void _update_ring_color(double x, double y , int index); void _reset_markers(); @@ -329,7 +324,6 @@ private: sigc::signal _signal_color_hovered; double lightness = 1.0; double saturation = 1.0; - // bool _lightness_changed = false; void update_ring_source(); }; -- GitLab From 86f326266c265136f92c8bf7bad570f7f195d038 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 24 Aug 2025 23:07:39 +0300 Subject: [PATCH 109/122] formatted function for better readability --- src/ui/widget/color-page.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ui/widget/color-page.h b/src/ui/widget/color-page.h index 6b3dd692ab..1eea249b7e 100644 --- a/src/ui/widget/color-page.h +++ b/src/ui/widget/color-page.h @@ -58,7 +58,12 @@ public: void attach_page(Glib::RefPtr first_column, Glib::RefPtr last_column); void detach_page(Glib::RefPtr first_column, Glib::RefPtr last_column); - void setCurrentColor(std::shared_ptr color){if(_color_wheel)_color_wheel->set_color(color->get().value());} + void setCurrentColor(std::shared_ptr color) + { + if (_color_wheel) + _color_wheel->set_color(color->get().value()); + } + protected: std::shared_ptr _space; std::shared_ptr _selected_colors; -- GitLab From 15c06fee876eb5ff51a7942118272ad6fe03d7ff Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 24 Aug 2025 23:24:11 +0300 Subject: [PATCH 110/122] changed ui builder file name from recolor-art.glade to widget-recolor.ui --- po/POTFILES.ui.in | 2 +- share/ui/{recolor-art.glade => widget-recolor.ui} | 0 src/ui/widget/recolor-art.h | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename share/ui/{recolor-art.glade => widget-recolor.ui} (100%) diff --git a/po/POTFILES.ui.in b/po/POTFILES.ui.in index 4d0449d38a..490decc106 100644 --- a/po/POTFILES.ui.in +++ b/po/POTFILES.ui.in @@ -31,7 +31,7 @@ ../share/ui/object-attributes.glade ../share/ui/page-properties.glade ../share/ui/pattern-edit.glade -../share/ui/recolor-art.glade +../share/ui/widget-recolor.ui ../share/ui/align-and-distribute.ui ../share/ui/dash-selector.ui ../share/ui/dialog-measure-tool-settings.ui diff --git a/share/ui/recolor-art.glade b/share/ui/widget-recolor.ui similarity index 100% rename from share/ui/recolor-art.glade rename to share/ui/widget-recolor.ui diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 63e318fea3..508b9e6c8e 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -93,7 +93,7 @@ class RecolorArt : public Gtk::Box { private: SPDesktop *_desktop = nullptr; - Glib::RefPtr _builder = create_builder("recolor-art.glade"); + Glib::RefPtr _builder = create_builder("widget-recolor.ui"); Gtk::Notebook &_notebook; Gtk::Box &_color_wheel_page; PaintSelector *_paint_selector; -- GitLab From ae1d1f25001313a8f87898f70242859b0d388527 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 24 Aug 2025 23:24:25 +0300 Subject: [PATCH 111/122] removed debugging prints --- src/ui/widget/recolor-art.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index e14fe01767..89049ade2c 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -273,7 +273,7 @@ void RecolorArt::setDesktop(SPDesktop *desktop) if (_desktop != desktop) { _desktop = desktop; } - g_message("setDesktop\n"); + // g_message("setDesktop\n"); } /* @@ -343,7 +343,7 @@ void RecolorArt::extractObjectStyle(SPObject *object, std::string kind) auto ps = style->getFillPaintServer(); if (auto pattern = dynamic_cast(ps)) { extractPatternColors(pattern); - std::cout << "pattern detected\n"; + // std::cout << "pattern detected\n"; } extractGradientStops(object, true); } @@ -460,7 +460,7 @@ void RecolorArt::extractMarkerColors(Glib::ustring marker, SPObject *object) // std::cout<<"marker id : "<document->getObjectByHref(marker_id); if (!m) - std::cout << "m is null\n"; + // std::cout << "m is null\n"; if (auto marker_obj = dynamic_cast(m)) { for (auto &child : marker_obj->item_list()) { extractObjectColors(&*child, "marker"); @@ -478,7 +478,7 @@ void RecolorArt::extractMarkerColors(Glib::ustring marker, SPObject *object) */ void RecolorArt::populateStopsMap(SPStop *stop) { - g_message("populateStopsMap in"); + // g_message("populateStopsMap in"); while (stop) { std::string color = stop->getColor().toString(); _gradient_stops[color].push_back(stop); @@ -685,7 +685,7 @@ void RecolorArt::onColorPickerChanged(Color color, bool wheel) { std::optional new_color = wheel ? color : _solid_colors->get(); if (!new_color.has_value()) { - g_message("there is no color"); + // g_message("there is no color"); return; } std::string _color_string = new_color.value().toString(); @@ -714,7 +714,7 @@ void RecolorArt::onColorPickerChanged(Color color, bool wheel) index = item_index.second; } if (!item) { - g_message("ERROR: item is null"); + // g_message("ERROR: item is null"); return; } // update colormodel item to refresh listview ui @@ -735,12 +735,12 @@ void RecolorArt::lpChecked(Color color, bool wheel) auto _selected = _selected_colors.find(_current_color_id); std::optional new_color = wheel ? color : _solid_colors->get(); if (!new_color.has_value()) { - g_message("there is no color"); + // g_message("there is no color"); return; } std::string _color_string = new_color.value().toString(); if (_selected == _selected_colors.end()) { - g_message("no items found"); + // g_message("no items found"); return; } _selected->second.second.value().new_color = new_color.value(); @@ -934,8 +934,8 @@ void RecolorArt::onLivePreviewToggled() } else { revertToOriginalColors(); } - g_message(_is_preview ? "is true" : "is false"); - g_message("LP toggled"); + // g_message(_is_preview ? "is true" : "is false"); + // g_message("LP toggled"); } /* * set paint selector to avoid recuresive signals calling @@ -977,7 +977,7 @@ void RecolorArt::performUpdate() auto first_button_id = _selected_colors.begin()->first; onOriginalColorClicked(first_button_id); } - g_message("Performing Update\n"); + // g_message("Performing Update\n"); } else g_message("Desktop is NULL in Performupdate in recolor widegt\n"); -- GitLab From 91fe316b381fc5604f649ff14a85b227c26d4f45 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 24 Aug 2025 23:38:26 +0300 Subject: [PATCH 112/122] marked tooltips as translatable --- src/ui/widget/multi-marker-color-plate.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ui/widget/multi-marker-color-plate.cpp b/src/ui/widget/multi-marker-color-plate.cpp index cc542d70fb..de8a80e559 100644 --- a/src/ui/widget/multi-marker-color-plate.cpp +++ b/src/ui/widget/multi-marker-color-plate.cpp @@ -110,7 +110,7 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c } _lightness_icon->set_from_icon_name(INKSCAPE_ICON("lightness")); - _lightness_icon->set_tooltip_text("change saturation for all if hue lock is on"); + _lightness_icon->set_tooltip_text(_("change saturation for all if hue lock is on")); _lightness_bar.set_value_pos(Gtk::PositionType::RIGHT); _lightness_bar.set_hexpand(true); _lightness_bar.set_draw_value(true); @@ -121,7 +121,7 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c _saturation_icon->set_from_icon_name(INKSCAPE_ICON("saturation")); - _saturation_icon->set_tooltip_text("change saturation for all if hue lock is on"); + _saturation_icon->set_tooltip_text(_("change saturation for all if hue lock is on")); _saturation_bar.set_value_pos(Gtk::PositionType::RIGHT); _saturation_bar.set_hexpand(true); _saturation_bar.set_draw_value(true); @@ -143,7 +143,7 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c _hue_lock.set_child(*_hue_lock_image); } }); - _hue_lock.set_tooltip_text("lock hue angles for colors set"); + _hue_lock.set_tooltip_text(_("lock hue angles for colors set")); _hue_lock.set_hexpand(false); _hue_lock.set_margin_top(8); _hue_lock.set_halign(Gtk::Align::END); -- GitLab From 8e059793736a9782ca8845db7109ae31324f3aba Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 24 Aug 2025 23:45:51 +0300 Subject: [PATCH 113/122] fixed reset button margin --- share/ui/widget-recolor.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/ui/widget-recolor.ui b/share/ui/widget-recolor.ui index 4149daffe5..e1ea7ca509 100644 --- a/share/ui/widget-recolor.ui +++ b/share/ui/widget-recolor.ui @@ -36,7 +36,7 @@ false false center - 32 + 16 reset-settings -- GitLab From dacc7e556ab52972e26abde6447ee0c1997045f3 Mon Sep 17 00:00:00 2001 From: ftomara Date: Sun, 24 Aug 2025 23:59:04 +0300 Subject: [PATCH 114/122] added to multi-marker-color-plate.cpp potfiles.src.in --- po/POTFILES.src.in | 1 + 1 file changed, 1 insertion(+) diff --git a/po/POTFILES.src.in b/po/POTFILES.src.in index 14f932d936..d9c3bdfbb1 100644 --- a/po/POTFILES.src.in +++ b/po/POTFILES.src.in @@ -425,6 +425,7 @@ ${_build_dir}/share/templates/templates.h ../src/ui/widget/memory.cpp ../src/ui/widget/mesh-editor.cpp ../src/ui/widget/messages.cpp +../src/ui/widget/multi-marker-color-plate.cpp ../src/ui/widget/object-composite-settings.cpp ../src/ui/widget/page-properties.cpp ../src/ui/widget/page-selector.cpp -- GitLab From 0b4dd1e52566991643ca7d86061e234a3c06b832 Mon Sep 17 00:00:00 2001 From: ftomara Date: Mon, 25 Aug 2025 00:14:26 +0300 Subject: [PATCH 115/122] put the file name in letters order --- po/POTFILES.ui.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/po/POTFILES.ui.in b/po/POTFILES.ui.in index 490decc106..26dd7fecf7 100644 --- a/po/POTFILES.ui.in +++ b/po/POTFILES.ui.in @@ -31,7 +31,6 @@ ../share/ui/object-attributes.glade ../share/ui/page-properties.glade ../share/ui/pattern-edit.glade -../share/ui/widget-recolor.ui ../share/ui/align-and-distribute.ui ../share/ui/dash-selector.ui ../share/ui/dialog-measure-tool-settings.ui @@ -73,3 +72,4 @@ ../share/ui/toolbar-tool-prefs.ui ../share/ui/toolbar-tweak.ui ../share/ui/toolbar-zoom.ui +../share/ui/widget-recolor.ui -- GitLab From e258b8bbc39b204eb837868c199166402c1d2f06 Mon Sep 17 00:00:00 2001 From: ftomara Date: Mon, 25 Aug 2025 02:18:23 +0300 Subject: [PATCH 116/122] added reset button to colorwheel page --- src/ui/widget/multi-marker-color-plate.cpp | 16 ++++++++++++++-- src/ui/widget/multi-marker-color-plate.h | 5 ++++- src/ui/widget/recolor-art.cpp | 2 ++ src/ui/widget/recolor-art.h | 4 ++-- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/ui/widget/multi-marker-color-plate.cpp b/src/ui/widget/multi-marker-color-plate.cpp index de8a80e559..5077b994b1 100644 --- a/src/ui/widget/multi-marker-color-plate.cpp +++ b/src/ui/widget/multi-marker-color-plate.cpp @@ -77,6 +77,7 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c , _spaces_combo(Gtk::make_managed()) , _switcher(Gtk::make_managed()) , _spaces_stack(Gtk::make_managed()) + , _reset(Gtk::make_managed()) { _specific_colors->set(Color(0xFF0000FF)); @@ -156,9 +157,20 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c _color_wheel_preview->set_margin_top(8); _color_wheel_preview->setStyle(_color_wheel_preview->Style::Outlined); + auto image = Gtk::make_managed(); + image->set_from_icon_name(INKSCAPE_ICON("reset-settings")); + _reset->set_child(*image); + _reset->set_margin_top(8); + _reset->signal_clicked().connect([this]() { + if (_ra) { + _ra->onResetClicked(); + } + }); + auto box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); - box->set_spacing(170); + box->set_spacing(64); box->append(*_color_wheel_preview); + box->append(*_reset); box->append(_hue_lock); _lightness_box->append(*_lightness_icon); @@ -169,7 +181,7 @@ MultiMarkerColorPlate::MultiMarkerColorPlate(std::shared_ptr c _spaces_stack->set_visible_child("RGB"); - + append(*box); append(*_color_wheel); diff --git a/src/ui/widget/multi-marker-color-plate.h b/src/ui/widget/multi-marker-color-plate.h index 1dd17873db..91ea86452b 100644 --- a/src/ui/widget/multi-marker-color-plate.h +++ b/src/ui/widget/multi-marker-color-plate.h @@ -31,6 +31,7 @@ #include "ui/widget/icon-combobox.h" #include "ui/widget/ink-color-wheel.h" #include "ui/widget/paint-selector.h" +#include "ui/widget/recolor-art.h" using namespace Inkscape::Colors; @@ -73,7 +74,7 @@ public: _color_wheel->setSaturation(value); _saturation_bar.set_value(value); } - + void setRecolorWidget(RecolorArt *ra) { _ra = ra; } Colors::Color getColor() { return _color_wheel->getColor(); } std::vector getColors() { return _color_wheel->getColors(); } bool getHueLock() { return _color_wheel->getHueLock(); } @@ -120,6 +121,8 @@ private: IconComboBox *_spaces_combo = nullptr; Gtk::Stack *_spaces_stack = nullptr; Gtk::StackSwitcher *_switcher = nullptr; + RecolorArt* _ra = nullptr; + Gtk::Button* _reset = nullptr; std::map>> _color_sets; sigc::connection _specific_colors_changed ; void _addPageForSpace(std::shared_ptr space, int page_num); diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 89049ade2c..3d64511c23 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -54,6 +54,7 @@ #include "ui/icon-names.h" #include "ui/widget/color-preview.h" #include "xml/repr.h" +#include "multi-marker-color-plate.h" namespace Inkscape { namespace UI { @@ -112,6 +113,7 @@ RecolorArt::RecolorArt() } } })); + _color_wheel->setRecolorWidget(this); // add hover opacity effect when hovering over markers in the wheel _color_wheel->connect_color_hovered(static_cast>([this]() { uint32_t cc = _color_wheel->getColor().toRGBA(); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 508b9e6c8e..bc7e8c69a9 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -32,7 +32,6 @@ #include "ui/widget/paint-selector.h" #include "ui/widget/ink-color-wheel.h" #include "src/colors/color-set.h" -#include "multi-marker-color-plate.h" using namespace Inkscape::Colors; @@ -61,6 +60,7 @@ class ToolBase; namespace Widget { class ColorNotebook; +class MultiMarkerColorPlate; struct ColorRef { @@ -137,7 +137,6 @@ private: // signals handelrs void onOriginalColorClicked(std::string color_id); - void onResetClicked(); void onColorPickerChanged(Color color=Color(0x00000000) , bool wheel = false); void onLivePreviewToggled(); void lpChecked(Color color=Color(0x00000000) , bool wheel = false); @@ -164,6 +163,7 @@ public: bool isInPreviewMode() { return _is_preview; } void setDesktop(SPDesktop *desktop); void setPaintSelector(PaintSelector *ps); + void onResetClicked(); }; } // namespace Widget -- GitLab From 03a5e1ff4540e06736cd358e4c9ab60b73ec1c98 Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 28 Aug 2025 00:20:07 +0300 Subject: [PATCH 117/122] fixed text color collection and recoloring bug --- src/ui/widget/recolor-art.cpp | 58 +++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 3d64511c23..35a1a4c078 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -43,6 +43,7 @@ #include "object/sp-pattern.h" #include "object/sp-radial-gradient.h" #include "object/sp-stop.h" +#include "object/sp-tspan.h" #include "object/sp-text.h" #include "object/sp-use.h" #include "pattern-manipulation.h" @@ -297,6 +298,27 @@ void RecolorArt::collectColors(std::vector&objects, std::string kind } collectColors(children_vec, "mask"); } + auto text = dynamic_cast(it); // handle text objects color collection by collecting the colors of its tspans children + if(text) + { + if(auto tspan = dynamic_cast(&text->children.front())) + { + std::vector children_vec; + bool noid=true; + for (auto &child : tspan->children) { + if (!child.getId() && noid) { + children_vec.push_back(&child); + noid = false; + } + else if (child.getId()) { + children_vec.push_back(&child); + } + } + collectColors(children_vec, kind); + continue; + } + + } } extractObjectColors(object, kind); } @@ -747,6 +769,8 @@ void RecolorArt::lpChecked(Color color, bool wheel) } _selected->second.second.value().new_color = new_color.value(); for (auto &item : _selected->second.first) { + // std::cout << *item.item << std::endl; + // std::cout << item.kind << std::endl; if (item.kind == "stop") continue; std::string k = (item.kind.find("fill") != std::string::npos) @@ -754,10 +778,16 @@ void RecolorArt::lpChecked(Color color, bool wheel) : (item.kind.find("stroke") != std::string::npos ? "stroke" : ""); if (k == "") continue; - + SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property_string(css, k.c_str(), _color_string); - sp_desktop_apply_css_recursive(item.item, css, true); + if(!item.item->getId()) // for handling text content that inheirts its style from parent + { + auto repr = item.item->parent->getRepr(); + sp_repr_css_change(repr, css, "style"); + } + else + sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } recolorStops(_selected->first, new_color.value()); @@ -802,7 +832,11 @@ void RecolorArt::revertToOriginalColors(bool is_reset_clicked) continue; SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property_string(css, k.c_str(), key); - sp_desktop_apply_css_recursive(item.item, css, true); + if (!item.item->getId()) { // for handling text content that inheirts its style from parent + auto repr = item.item->parent->getRepr(); + sp_repr_css_change(repr, css, "style"); + } else + sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } recolorStops(key, items.second.value().old_color); @@ -828,7 +862,11 @@ void RecolorArt::convertToRecoloredColors() continue; SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property_string(css, k.c_str(), new_color); - sp_desktop_apply_css_recursive(item.item, css, true); + if (!item.item->getId()) { // for handling text content that inheirts its style from parent + auto repr = item.item->parent->getRepr(); + sp_repr_css_change(repr, css, "style"); + } else + sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } recolorStops(key, items.second.value().new_color); @@ -888,7 +926,11 @@ void RecolorArt::getSelection(std::string color) continue; SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property_string(css, k.c_str(), new_color.toString()); - sp_desktop_apply_css_recursive(item.item, css, true); + if (!item.item->getId()) { // for handling text content that inheirts its style from parent + auto repr = item.item->parent->getRepr(); + sp_repr_css_change(repr, css, "style"); + } else + sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } } @@ -917,7 +959,11 @@ void RecolorArt::resetOpacity() continue; SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property_string(css, k.c_str(), new_color); - sp_desktop_apply_css_recursive(item.item, css, true); + if (!item.item->getId()) { // for handling text content that inheirts its style from parent + auto repr = item.item->parent->getRepr(); + sp_repr_css_change(repr, css, "style"); + } else + sp_desktop_apply_css_recursive(item.item, css, true); sp_repr_css_attr_unref(css); } recolorStops(key, value.second.value().new_color); -- GitLab From be93b7d4668f08de69447e7004f2b7da175f1089 Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 28 Aug 2025 03:02:48 +0300 Subject: [PATCH 118/122] changed ring to wheel and added some documentation --- src/ui/widget/ink-color-wheel.cpp | 198 ++++++++++++++++++++++-------- src/ui/widget/ink-color-wheel.h | 14 +-- 2 files changed, 156 insertions(+), 56 deletions(-) diff --git a/src/ui/widget/ink-color-wheel.cpp b/src/ui/widget/ink-color-wheel.cpp index ce7458001e..4ea25be746 100644 --- a/src/ui/widget/ink-color-wheel.cpp +++ b/src/ui/widget/ink-color-wheel.cpp @@ -764,6 +764,10 @@ bool ColorWheelHSLuv::setColor(Color const &color, } /*multi marker color wheel*/ +/** + * takes the color parameter and push it into the _values_vectors vector + * them if emit is true it calls the color_changed() to emit signal changed then queue redrae the area + */ bool MultiMarkerWheel::setColor(Color const &color, bool const /*overrideHue*/, bool const emit) { if (_values.set(color, true)) { @@ -776,12 +780,16 @@ bool MultiMarkerWheel::setColor(Color const &color, bool const /*overrideHue*/, } return false; } - +/** + * it takes a vector of colors then clears the current _values_vector and _markers_points + * and resets the color wheel then repopulates it with the new colors + * then emit the color changed signal + */ bool MultiMarkerWheel::setColor(std::vector const &color) { _values_vector.clear(); _markers_points.clear(); - _source_ring.reset(); + _source_wheel.reset(); for (auto c : color) { if(!setColor(c,false,false)) return false; } @@ -790,11 +798,20 @@ bool MultiMarkerWheel::setColor(std::vector const &color) color_changed(); return true ; } + void MultiMarkerWheel::_reset_markers() { for(auto& _marker_point : _markers_points) _marker_point.reset(); _markers_points.resize(_values_vector.size()); } +/** + * takes cairo context , color value and index of the color + * get the center of the colorwheel by dividing width and height by 2 + * get the center of the marker by passing the index to get_marker_point function + * then choose the color of the marker (black or white) based on its luminance + * then start start drawing with cairo , if the index == hover index just make the radius bigger + * then if the marker has foucs add focus dash to it + */ void MultiMarkerWheel::_draw_marker(Cairo::RefPtr const &cr , Colors::Color value , int index) { auto const [width, height] = *_cache_size; @@ -804,8 +821,8 @@ void MultiMarkerWheel::_draw_marker(Cairo::RefPtr const &cr , Co _draw_line_2_marker(cr,mx,my,cx,cy,value,index); - auto color_on_ring = Color(Type::HSV, {value[0], 1.0, 1.0}); - double a = luminance(color_on_ring) < 0.5 ? 1.0 : 0.0; + auto color_on_wheel = Color(Type::HSV, {value[0], 1.0, 1.0}); + double a = luminance(color_on_wheel) < 0.5 ? 1.0 : 0.0; cr->set_source_rgb(a, a, a); cr->begin_new_path(); if (index == _hover_index) { @@ -830,6 +847,13 @@ void MultiMarkerWheel::_draw_marker(Cairo::RefPtr const &cr , Co cr->stroke(); } } +/** + * try to get marker index from the input position (x,y) + * by getting the distance between the marker center and the point (x,y) + * if it is less than marker_radius + marker_click_tolerance it means that + * the point is inside the marker area then return its index + * if not found return -1 + */ int MultiMarkerWheel::_get_marker_index(double x, double y) { for(int i =0 ; i<_values_vector.size();i++) @@ -843,6 +867,21 @@ int MultiMarkerWheel::_get_marker_index(double x, double y) } return -1; } +/** + * If hue lock is enabled, this function calculates how far each marker's hue + * is from the active marker's hue. + * + * Because hue is a circle (0.0 and 1.0 are the same color), the raw difference + * can sometimes look too big (e.g. 0.9 - 0.1 = 0.8), even though the real + * distance around the circle is much smaller (0.2). + * + * To fix this, the delta is adjusted: + * - If delta > 0.5 → subtract 1.0 + * - If delta < -0.5 → add 1.0 + * + * This makes sure the difference is always the shortest distance on the color wheel, + * inside the range [-0.5, +0.5]. + */ void MultiMarkerWheel::_update_hue_lock_positions() { if (_hue_lock) { @@ -861,28 +900,39 @@ void MultiMarkerWheel::_update_hue_lock_positions() _relative_hue_angles = delat_angles; } } +/** + * function to draw line to the begining of the marker by calculating the distnace from the wheel center + * to makrer center + * normalize the differnces between centers by dividing them by the length of the line + * to be a unit vector between [-1,1] + * then calculate the end points ty,tx by subtracting the marker radius multiplied by the direction of the vector + * from the marker center , calculate the luminance of the line + * move the cairo context tot the center of the colorwheel by converting the polar coordinates to cartisain ones + * then draw the line to point (tx,ty) + */ void MultiMarkerWheel::_draw_line_2_marker(Cairo::RefPtr const &cr, double mx, double my, double cx, double cy, Colors::Color value , int index) { - auto const &[r_min, r_max] = get_radii(); - auto color_on_ring = Color(Type::HSV, {value[0], 1.0, 1.0}); + auto const &[r_min, r_max] = get_radii(); + auto color_on_wheel = Color(Type::HSV, {value[0], 1.0, 1.0}); double dy = my-cy; double dx = mx-cx; - double len = std::sqrt(dx*dx+dy*dy); + double len = std::sqrt(dx*dx+dy*dy); if(len > 1e-5) { dx /= len; dy /= len; } - double mr = index == _hover_index ? marker_radius+2 : marker_radius; + double mr = index == _hover_index ? marker_radius+2 : marker_radius; // bigger radius for on hover effect double tx = mx - dx * mr; double ty = my - dy * mr; - double l = luminance(color_on_ring) < 0.5 ? 1.0 : 0.0; + double l = luminance(color_on_wheel) < 0.5 ? 1.0 : 0.0; cr->save(); cr->set_source_rgb(l, l, l); cr->move_to(cx + cos(value[0] * M_PI * 2.0) * (r_min), - cy - sin(value[0] * M_PI * 2.0) * (r_min)); + cy - sin(value[0] * M_PI * 2.0) * (r_min)); // x = r*cos(angel) , y = r*sin(angel) + // adding cx and subtracting cy to start from wheel center not the origin (0,0) cr->line_to(tx,ty); if (index != _active_index) { cr->set_dash(focus_dash, 0); @@ -894,9 +944,12 @@ void MultiMarkerWheel::_draw_line_2_marker(Cairo::RefPtr const & cr->stroke(); cr->restore(); } -void MultiMarkerWheel::update_ring_source() +/** + * draw the colorwheel pixel by pixel + */ +void MultiMarkerWheel::update_wheel_source() { - if (_radii && _source_ring) + if (_radii && _source_wheel) return; auto const [width, height] = *_cache_size; @@ -904,15 +957,15 @@ void MultiMarkerWheel::update_ring_source() auto const cy = height / 2.0; auto const stride = Cairo::ImageSurface::format_stride_for_width(Cairo::Surface::Format::RGB24, width); - _source_ring.reset(); - _buffer_ring.resize(height * stride / 4); + _source_wheel.reset(); + _buffer_wheel.resize(height * stride / 4); auto const &[r_min, r_max] = get_radii(); double r2_max = (r_max + 2) * (r_max + 2); // Must expand a bit to avoid edge effects. double r2_min = (r_min - 2) * (r_min - 2); // Must shrink a bit to avoid edge effects. for (int i = 0; i < height; ++i) { - auto p = _buffer_ring.data() + i * width; + auto p = _buffer_wheel.data() + i * width; double dy = (cy - i); for (int j = 0; j < width; ++j) { double dx = (j - cx); @@ -936,10 +989,15 @@ void MultiMarkerWheel::update_ring_source() } } - auto const data = reinterpret_cast(_buffer_ring.data()); - _source_ring = Cairo::ImageSurface::create(data, Cairo::Surface::Format::RGB24, width, height, stride); + auto const data = reinterpret_cast(_buffer_wheel.data()); + _source_wheel = Cairo::ImageSurface::create(data, Cairo::Surface::Format::RGB24, width, height, stride); } - +/** + * takes index of the requested changed color and the new color + * change it in the _values_vector and reset its marker and emit color changed signal to update the widget + * and return true if succeeded + * used to sync wheel's colors if the color chnaged from the colorlist + */ bool MultiMarkerWheel::changeColor(int index, Colors::Color& color) { if(index >=0 && index < _values_vector.size()) @@ -960,11 +1018,14 @@ bool MultiMarkerWheel::changeColor(int index, Colors::Color& color) // std::cout<<"changed color went bad\n"; return false; } - +/** + * set lightness for all colors in the wheel when hue lock is on + * if it is off just changed lightness for the active color + */ void MultiMarkerWheel::setLightness(double value) { lightness = value / 100.0; - _source_ring.reset(); + _source_wheel.reset(); if (_hue_lock) { for (size_t i = 0; i < _values_vector.size(); i++) { _values_vector[i].set(2, lightness); @@ -983,11 +1044,14 @@ void MultiMarkerWheel::setLightness(double value) } } } - +/** + * set saturation for all colors in the wheel when hue lock is on + * if it is off just changed saturation for the active color + */ void MultiMarkerWheel::setSaturation(double value) { saturation = value / 100.0; - _source_ring.reset(); + // _source_wheel.reset(); if (_hue_lock) { for (size_t i = 0; i < _values_vector.size(); i++) { _values_vector[i].set(1, saturation); @@ -1017,9 +1081,11 @@ void MultiMarkerWheel::on_drawing_area_size(int width, int height, int baseline) return; _cache_size = size; _radii.reset(); - _source_ring.reset(); + _source_wheel.reset(); } - +/** + * main function for drawing the whole wheel and markers and lines + */ void MultiMarkerWheel::on_drawing_area_draw(Cairo::RefPtr const &cr, int, int) { @@ -1030,12 +1096,12 @@ void MultiMarkerWheel::on_drawing_area_draw(Cairo::RefPtr const cr->set_antialias(Cairo::ANTIALIAS_SUBPIXEL); // Update caches - update_ring_source(); + update_wheel_source(); auto const &[r_min, r_max] = get_radii(); // Paint with ring surface, clipping to ring. cr->save(); - cr->set_source(_source_ring, 0, 0); + cr->set_source(_source_wheel, 0, 0); cr->set_line_width(r_max - r_min); cr->begin_new_path(); cr->arc(cx, cy, (r_max + r_min) / 2.0, 0, 2.0 * M_PI); @@ -1059,7 +1125,7 @@ std::optional MultiMarkerWheel::focus(Gtk::DirectionType const direction) // In forward direction, focus passes from no focus to ring focus to triangle // focus to no focus. if (!drawing_area_has_focus()) { - _focus_on_ring = (direction == Gtk::DirectionType::TAB_FORWARD); + _focus_on_wheel = (direction == Gtk::DirectionType::TAB_FORWARD); focus_drawing_area(); return true; } @@ -1069,16 +1135,16 @@ std::optional MultiMarkerWheel::focus(Gtk::DirectionType const direction) switch (direction) { case Gtk::DirectionType::TAB_BACKWARD: - if (!_focus_on_ring) { - _focus_on_ring = true; + if (!_focus_on_wheel) { + _focus_on_wheel = true; } else { keep_focus = false; } break; case Gtk::DirectionType::TAB_FORWARD: - if (_focus_on_ring) { - _focus_on_ring = false; + if (_focus_on_wheel) { + _focus_on_wheel = false; } else { keep_focus = false; } @@ -1086,8 +1152,11 @@ std::optional MultiMarkerWheel::focus(Gtk::DirectionType const direction) return keep_focus; } - -bool MultiMarkerWheel::_is_in_ring(double x, double y) +/** + * checks whether the point is inside the wheel or not + * by checking if the distance is less than the wheel radius + */ +bool MultiMarkerWheel::_is_in_wheel(double x, double y) { // std::cout<<"x: "<= 0) _active_index = index; _update_hue_lock_positions(); - _update_ring_color(x, y,_active_index); + _update_wheel_color(x, y,_active_index); return Gtk::EventSequenceState::CLAIMED; } @@ -1168,7 +1248,11 @@ Gtk::EventSequenceState MultiMarkerWheel::on_click_released(int /*n_press*/, dou _adjusting = false; return Gtk::EventSequenceState::CLAIMED; } - +/** + * a part of _on_motion signal handler that handels the marker movement and emits _signal_color_hovered + * with -1 _hover_index to cancel the hover effect when start moving the marker + * also checks for the _hue_lock to change reset of the markers accordingly if it is on + */ void MultiMarkerWheel::on_motion(Gtk::EventControllerMotion const &motion, double x, double y) { // std::cout<<"on motion \n"; @@ -1185,7 +1269,7 @@ void MultiMarkerWheel::on_motion(Gtk::EventControllerMotion const &motion, doubl if (_mode == DragMode::HUE || _mode == DragMode::SATURATION_VALUE) { _hover_index = -1; _signal_color_hovered.emit(); - _update_ring_color(x, y, _active_index); + _update_wheel_color(x, y, _active_index); if (_hue_lock && !_relative_hue_angles.empty()) { bool changed = false; double hue = _values_vector[_active_index][0]; @@ -1204,7 +1288,12 @@ void MultiMarkerWheel::on_motion(Gtk::EventControllerMotion const &motion, doubl } } } - +/** + * the main signal handler for on motion on the whole colorwheel if not adusting a marker + * it detects if the point is on or near some marker gets its index and emits _signal_color_hovered + * so the marker gets redrawed with a bigger radius and call for any action related to hover + * (e.g. highlighting objects that has the hovered marker color) + */ void MultiMarkerWheel::_on_motion(Gtk::EventControllerMotion const &motion, double x, double y) { if (!_adjusting) { @@ -1234,6 +1323,10 @@ void MultiMarkerWheel::_on_motion(Gtk::EventControllerMotion const &motion, doub on_motion(motion, x, y); } +/** + * signal handler function that handels keyboard adjustments to the wheel on hue and saturation values + * same as the one in ColorWheelHSL too + */ bool MultiMarkerWheel::on_key_pressed(unsigned keyval, unsigned /*keycode*/, Gdk::ModifierType state) { static constexpr double delta_hue = 2.0 / MAX_HUE; @@ -1265,7 +1358,7 @@ bool MultiMarkerWheel::on_key_pressed(unsigned keyval, unsigned /*keycode*/, Gdk return false; bool changed = false; - if (_focus_on_ring) { + if (_focus_on_wheel) { changed = _values_vector[_active_index].set(0, _values_vector[_active_index][0] - ((dx != 0 ? dx : dy) * delta_hue)); changed = _values_vector[_active_index].set(1, _values_vector[_active_index][1] - ((dy != 0 ? dy : dx) * delta_sat)); } @@ -1280,7 +1373,11 @@ bool MultiMarkerWheel::on_key_pressed(unsigned keyval, unsigned /*keycode*/, Gdk return changed; } - +/** + * that is the same as get radii in the ColorWheelHSL i didn't change any thing even + * though it has only one radius (r_max = r_min) now as a whole circle not a ring but i dare not change a working function + * (and i am lazy too) + */ MultiMarkerWheel::MinMax const &MultiMarkerWheel::get_radii() { if (_radii) @@ -1292,11 +1389,14 @@ MultiMarkerWheel::MinMax const &MultiMarkerWheel::get_radii() auto &[r_min, r_max] = *_radii; auto const [width, height] = *_cache_size; r_max = std::min(width, height) / 2.0 - 2 * (focus_line_width + focus_padding); - r_min = r_max * (1.0 - _ring_width); + r_min = r_max * (1.0 - _wheel_width); // std::cout<<"r max : "<= _values_vector.size()) { @@ -1321,7 +1421,7 @@ Geom::Point const &MultiMarkerWheel::get_marker_point(int index) double angle = (1.0 - hue) * 2 * M_PI; _markers_points[index].emplace(); auto &[mx, my] = *_markers_points[index]; - mx = cx + r_max * saturation * cos(angle); + mx = cx + r_max * saturation * cos(angle); // polar cooordinates to cartisian coordinates calculation my = cy + r_max * saturation * sin(angle); return *_markers_points[index]; } @@ -1329,11 +1429,11 @@ Geom::Point const &MultiMarkerWheel::get_marker_point(int index) MultiMarkerWheel::MultiMarkerWheel() : Glib::ObjectBase{"MultiMarkerWheel"} , WidgetVfuncsClassInit{} // All the calculations are based on HSV, not HSL - , ColorWheelBase(Type::HSV, {0.5, 0.2, 0.7, 1}) + , ColorWheelBase(Type::HSV, {0.5, 0.2, 0.7, 1}) // redundant values nothing important {} MultiMarkerWheel::MultiMarkerWheel(BaseObjectType *cobject, Glib::RefPtr const &builder) - : ColorWheelBase(cobject, builder, Type::HSV, {0.5, 0.2, 0.7, 1}) + : ColorWheelBase(cobject, builder, Type::HSV, {0.5, 0.2, 0.7, 1}) // redundant values nothing important {} /** diff --git a/src/ui/widget/ink-color-wheel.h b/src/ui/widget/ink-color-wheel.h index 6345bbd689..918bc5a12e 100644 --- a/src/ui/widget/ink-color-wheel.h +++ b/src/ui/widget/ink-color-wheel.h @@ -277,8 +277,8 @@ private: void on_drawing_area_size(int width, int height, int baseline) override; void on_drawing_area_draw(Cairo::RefPtr const &cr, int, int) override; std::optional focus(Gtk::DirectionType direction) override; - bool _is_in_ring(double x, double y); - void _update_ring_color(double x, double y , int index); + bool _is_in_wheel(double x, double y); + void _update_wheel_color(double x, double y , int index); void _reset_markers(); void _draw_line_2_marker(Cairo::RefPtr const &cr , double mx, double my ,double cx, double cy , Colors::Color value , int index); void _draw_marker(Cairo::RefPtr const &cr,Colors::Color value , int index); @@ -293,9 +293,9 @@ private: SATURATION_VALUE }; - static constexpr double _ring_width = 1.0; + static constexpr double _wheel_width = 1.0; DragMode _mode = DragMode::NONE; - bool _focus_on_ring = true; + bool _focus_on_wheel = true; Gtk::EventSequenceState on_click_pressed(Gtk::GestureClick const &controller, int n_press, double x, double y) final; @@ -312,8 +312,8 @@ private: std::optional _radii; std::optional _marker_point; MarkerPoints _markers_points; - std::vector _buffer_ring; - Cairo::RefPtr _source_ring; + std::vector _buffer_wheel; + Cairo::RefPtr _source_wheel; [[nodiscard]] MinMax const &get_radii(); [[nodiscard]] Geom::Point const &get_marker_point(int index); int _active_index = 0; @@ -324,7 +324,7 @@ private: sigc::signal _signal_color_hovered; double lightness = 1.0; double saturation = 1.0; - void update_ring_source(); + void update_wheel_source(); }; } // namespace Inkscape::UI::Widget -- GitLab From 5f2014b1d378a0fb5f2f12e5be00c2e45515a947 Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 28 Aug 2025 16:26:03 +0300 Subject: [PATCH 119/122] switched map to unordered map for fast processing --- src/ui/widget/recolor-art.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index bc7e8c69a9..6dc814b830 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -99,7 +99,7 @@ private: PaintSelector *_paint_selector; std::shared_ptr _solid_colors = std::make_shared(); sigc::connection _solid_color_changed ; - std::map, std::optional>> _selected_colors; + std::unordered_map, std::optional>> _selected_colors; Gtk::Box &_color_list ; Gtk::Button &_reset; Gtk::CheckButton &_live_preview; @@ -112,12 +112,12 @@ private: Glib::RefPtr _color_factory; Glib::RefPtr _selection_model; - std::map> _gradient_stops; + std::unordered_map> _gradient_stops; MultiMarkerColorPlate *_color_wheel = nullptr; std::vector colors; - std::mapcolor_wheel_colors_map; + std::unordered_mapcolor_wheel_colors_map; int colors_index=0; bool _is_updating = false; bool _is_wheel_page = false; -- GitLab From 9e6a4cbde0d916bc89faf0148c863160b2dc33c2 Mon Sep 17 00:00:00 2001 From: ftomara Date: Thu, 28 Aug 2025 17:49:43 +0300 Subject: [PATCH 120/122] fixed adding selection when the popover is open upadating the widget with new colors added --- src/ui/widget/paint-selector.cpp | 37 +++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp index 13d6fd522b..a3bf6d7189 100644 --- a/src/ui/widget/paint-selector.cpp +++ b/src/ui/widget/paint-selector.cpp @@ -1231,7 +1231,6 @@ PaintSelector::Mode PaintSelector::getModeForStyle(SPStyle const &style, FillOrS } void PaintSelector::onSelectionChanged(Inkscape::Selection *selection) { - if (_change_sel) { std::cout << "return\n"; return; @@ -1302,6 +1301,42 @@ void PaintSelector::onSelectionChanged(Inkscape::Selection *selection) _recolorButtonTriger_5->hide(); // std::cout<<"hide 1,2\n"; } + + if (_recolorPopOver_1->get_visible()) { + if (!_change_sel) { + _change_sel = true; + _recolorArtWdgt_1->performUpdate(); + _change_sel = false; + } + return; + } + + if (_recolorPopOver_2->get_visible()) { + if (!_change_sel) { + _change_sel = true; + _recolorArtWdgt_2->performUpdate(); + _change_sel = false; + } + return; + } + + if (_recolorPopOver_3->get_visible()) { + if (!_change_sel) { + _change_sel = true; + _recolorArtWdgt_3->performUpdate(); + _change_sel = false; + } + return; + } + + if (_recolorPopOver_4->get_visible()) { + if (!_change_sel) { + _change_sel = true; + _recolorArtWdgt_4->performUpdate(); + _change_sel = false; + } + return; + } } void PaintSelector::setupRecolorButton(Gtk::Button *recolorButtonTriger, Gtk::Popover *recolorPopOver , UI::Widget::RecolorArt *recolorArtWdgt) -- GitLab From 3db65819937e02ea04a525c649f4dfa536ef1f07 Mon Sep 17 00:00:00 2001 From: ftomara Date: Fri, 29 Aug 2025 06:53:10 +0300 Subject: [PATCH 121/122] refactored code and sperated functionality between extraction logic , data manpulation and gui managing --- src/ui/widget/recolor-art.cpp | 1044 ++++++++++++++++----------------- src/ui/widget/recolor-art.h | 90 ++- 2 files changed, 583 insertions(+), 551 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index 35a1a4c078..b6cfa2e163 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -68,216 +68,7 @@ related classes : 1- ink-colorwheel for the multimarkercolorwheel in the colorwheel page 2- multi-marker-color-wheel-plate that manges the multimarkercolorwheel and sliders under it */ -RecolorArt::RecolorArt() - : Gtk::Box() - , _notebook(*_builder->get_widget("list-wheel-box")) - , _color_wheel_page(*_builder->get_widget("color-wheel-page")) - , _color_wheel(Gtk::make_managed(std::make_shared())) - ,_color_list(*_builder->get_widget("colors-list")) - ,_reset(*_builder->get_widget("reset")) - ,_live_preview(*_builder->get_widget("liveP")) -{ - _desktop = SP_ACTIVE_DESKTOP; - set_name("RecolorArt"); - append(get_widget(_builder, "recolor-art")); - _solid_colors->set(Color(0x000000ff)); - // when recolor widget is closed it resets opacity to mitigate the effect of getSelection function - // and reshow selection boxes again - signal_unmap().connect([&]() { - resetOpacity(); - _desktop->hideSelectionBoxes(false); - }); - // hide selection boxes after widget gets mapped (this is why it connects to signal idle to activate after finishing mapping) - signal_map().connect([&]() { Glib::signal_idle().connect_once([this]() { _desktop->hideSelectionBoxes(true); }); }); - _color_wheel->connect_color_changed(static_cast>([this]() { - if(_is_updating) return; // to stop recuresive calling to signal if changed from the color list page - uint32_t cc = _color_wheel->getColor().toRGBA(); - Color c(cc,true); - if(_color_wheel->getActiveIndex() != -1) { - int index = _color_wheel->getActiveIndex(); - _current_color_id = colors[index].toString(true); - auto idx = findColorItemByKey(_current_color_id); - _selection_model->set_selected(idx.second); - onColorPickerChanged(c, true); - onOriginalColorClicked(_current_color_id); - if (_color_wheel->getHueLock()) { - if (_selected_colors.empty()) - return; - std::vector new_colors = _color_wheel->getColors(); - for(auto &[key,value] : _selected_colors) - { - int index = color_wheel_colors_map[key]; - value.second.value().new_color = new_colors[index]; - } - updateColorModel(new_colors); - convertToRecoloredColors(); - } - } - })); - _color_wheel->setRecolorWidget(this); - // add hover opacity effect when hovering over markers in the wheel - _color_wheel->connect_color_hovered(static_cast>([this]() { - uint32_t cc = _color_wheel->getColor().toRGBA(); - Color c(cc,true); - if (_color_wheel->getHoverIndex() != -1) { - int index = _color_wheel->getHoverIndex(); - _current_color_id = colors[index].toString(true); - getSelection(_current_color_id); - } - else - resetOpacity(); - })); - - - - layoutColorPicker(); - _live_preview.signal_toggled().connect(sigc::mem_fun(*this, &RecolorArt::onLivePreviewToggled)); - _live_preview.set_active(true); - _reset.signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::onResetClicked)); - - // setting up list view for the color list - _list_view = _builder->get_widget("recolor-art-list"); - _color_model = Gio::ListStore::create(); - _selection_model = Gtk::SingleSelection::create(_color_model); - _color_factory = Gtk::SignalListItemFactory::create(); - - // setup how the list item should look - _color_factory->signal_setup().connect([](Glib::RefPtr const &list_item) { - auto box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); - auto original = Gtk::make_managed(); - auto arrow = Gtk::make_managed(); - auto recolored = Gtk::make_managed(); - - auto original_preview = Gtk::make_managed(Color(0x00000000).toRGBA()); - auto recolored_preview = Gtk::make_managed(Color(0x00000000).toRGBA()); - - auto type_box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); - type_box->set_spacing(2); - type_box->set_margin_start(4); - type_box->set_hexpand(false); - type_box->set_vexpand(false); - type_box->set_halign(Gtk::Align::START); - type_box->set_valign(Gtk::Align::CENTER); - type_box->get_style_context()->add_class("type_box"); - - original_preview->set_hexpand(true); - recolored_preview->set_hexpand(true); - - original_preview->set_vexpand(true); - recolored_preview->set_vexpand(true); - - auto original_overlay = Gtk::make_managed(); - - original_overlay->set_child(*original_preview); - original_overlay->add_overlay(*type_box); - - original->append(*original_overlay); - recolored->append(*recolored_preview); - - original->set_hexpand(true); - - recolored->set_hexpand(true); - - arrow->set_from_icon_name(INKSCAPE_ICON("go-right")); - arrow->set_halign(Gtk::Align::CENTER); - arrow->set_valign(Gtk::Align::CENTER); - arrow->set_margin_top(3); - arrow->set_margin_start(6); - arrow->set_margin_end(6); - box->set_name("original-recolor-box"); - box->append(*original); - box->append(*arrow); - box->append(*recolored); - list_item->set_data("typebox", type_box); - list_item->set_child(*box); - }); - - // setup signals for the list item children after they are created - _color_factory->signal_bind().connect([this](Glib::RefPtr const &list_item) { - auto item = std::dynamic_pointer_cast(list_item->get_item()); - if (!item) - return; - - auto box = dynamic_cast(list_item->get_child()); - if (!box || box->get_first_child() == nullptr || box->get_last_child() == nullptr) - return; - - // for hover effect - auto item_controller = Gtk::EventControllerMotion::create(); - item_controller->signal_enter().connect([box, item, this](double x, double y) { getSelection(item->key); }); - item_controller->signal_leave().connect([box, this]() { resetOpacity(); }); - - box->add_controller(item_controller); - - auto original = dynamic_cast(box->get_first_child()); - auto recolored = dynamic_cast(box->get_last_child()); - - if (original && recolored) { - colorButtons(original, item->old_color, true); - colorButtons(recolored, item->new_color); - setUpTypeBox(static_cast(list_item->get_data("typebox")), item->old_color); - - original->set_name("original"); - recolored->set_name("recolored"); - - auto original_click = Gtk::GestureClick::create(); - auto recolored_click = Gtk::GestureClick::create(); - - original_click->signal_pressed().connect( - [this, item, index = list_item->get_position()](gint n_press, gdouble x, gdouble y) { - _selection_model->set_selected(index); - onOriginalColorClicked(item->key); - }); - - recolored_click->signal_pressed().connect( - [this, item, index = list_item->get_position()](gint n_press, gdouble x, gdouble y) { - _selection_model->set_selected(index); - onOriginalColorClicked(item->key); - }); - - original->add_controller(original_click); - recolored->add_controller(recolored_click); - } - }); - - _list_view->set_model(_selection_model); - _list_view->set_factory(_color_factory); - - - auto lm = _list_view->get_layout_manager(); - if (auto grid_layout = std::dynamic_pointer_cast(lm)) { - grid_layout->set_row_spacing(0); - } - _list_view->set_hexpand(false); - _list_view->set_vexpand(false); - - _selection_model->signal_selection_changed().connect([this](guint pos, guint n_items) { - int index = _selection_model->get_selected(); - if (index < 0) - return; - - auto item = _color_model->get_item(index); - auto color_item = std::dynamic_pointer_cast(item); - if (!color_item) - return; - - onOriginalColorClicked(color_item->key); - }); - - _color_wheel_page.append(*_color_wheel); - // _apply = _builder->get_widget("apply"); - // _apply->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::_onApplyButtonClicked)); -} -RecolorArt::~RecolorArt() {} - -void RecolorArt::setDesktop(SPDesktop *desktop) -{ - if (_desktop != desktop) { - _desktop = desktop; - } - // g_message("setDesktop\n"); -} /* * loops over the vector of objects , firstly try to dynamically cast the spobject to spitem @@ -285,7 +76,7 @@ void RecolorArt::setDesktop(SPDesktop *desktop) * from it push into vector of spobjects then call collectColors recursivley with this vector * after this it calls extractObjectColors on the object it self */ -void RecolorArt::collectColors(std::vector&objects, std::string kind) +void ColorsExtractor::collectColors(std::vectorobjects, std::string kind) { for (auto object : objects) { auto it = dynamic_cast(object); @@ -329,7 +120,7 @@ void RecolorArt::collectColors(std::vector&objects, std::string kind * call extractObjectColors recursivley on group's children * if it is not group call extractObjectStyle */ -void RecolorArt::extractObjectColors(SPObject *object, std::string kind) +void ColorsExtractor::extractObjectColors(SPObject *object, std::string kind) { if (auto group = dynamic_cast(object)) { for (SPObject &child : group->children) { @@ -345,7 +136,7 @@ void RecolorArt::extractObjectColors(SPObject *object, std::string kind) * check for fill types (flat fill ,pattern fill , gradient fill) to populate the _selected_colors map * do same for stroke types */ -void RecolorArt::extractObjectStyle(SPObject *object, std::string kind) +void ColorsExtractor::extractObjectStyle(SPObject *object, std::string kind) { // check object style if (!object || !object->style) @@ -358,7 +149,7 @@ void RecolorArt::extractObjectStyle(SPObject *object, std::string kind) // get flat fills if (style->fill.isColor()) { auto color = style->fill.getColor(); - populateMap(color, object, (kind == "" ? "fill" : kind + "-fill")); + manager->populateMap(color, object, (kind == "" ? "fill" : kind + "-fill"));//DataManager } // paint server can be pattern or gradient @@ -374,7 +165,7 @@ void RecolorArt::extractObjectStyle(SPObject *object, std::string kind) if (style->stroke.isColor()) { auto color = style->stroke.getColor(); - populateMap(color, object, (kind == "" ? "stroke" : kind + "-stroke")); + manager->populateMap(color, object, (kind == "" ? "stroke" : kind + "-stroke"));//DataManager } // get gradient stops strokes else if (style->stroke.isPaintserver()) { @@ -395,7 +186,7 @@ void RecolorArt::extractObjectStyle(SPObject *object, std::string kind) * then call populateMap to save the spgradient object as a whole to have gradients colors in * the color list */ -void RecolorArt::extractGradientStops(SPObject *object, bool isFill) +void ColorsExtractor::extractGradientStops(SPObject *object, bool isFill) { SPPaintServer *paint_server = isFill ? object->style->getFillPaintServer() : object->style->getStrokePaintServer(); if (paint_server && dynamic_cast(paint_server)) { @@ -417,7 +208,7 @@ void RecolorArt::extractGradientStops(SPObject *object, bool isFill) if (!gradient) return; gradient->ensureVector(); - populateStopsMap(gradient->getFirstStop()); + manager->populateStopsMap(gradient->getFirstStop());//DataManager } } bool is_swatch = gradient->getVector()->isSwatch(); @@ -434,7 +225,7 @@ void RecolorArt::extractGradientStops(SPObject *object, bool isFill) for (auto stop : gradient->getGradientVector().stops) { if (stop.color.has_value()) { // if(kind == "swatch") std::cout<<"swatch found : "<populateMap(stop.color.value(), object, kind);//DataManager } } } @@ -444,92 +235,451 @@ void RecolorArt::extractGradientStops(SPObject *object, bool isFill) * mesh_nodes is a vector of vector of stops so we loop over it normally * call populateStopsMap and populateMap to populate both maps */ -void RecolorArt::extractMeshStops(std::vector>& mesh_nodes, SPObject *item, std::string kind) +void ColorsExtractor::extractMeshStops(std::vector>& mesh_nodes, SPObject *item, std::string kind) { for (auto nodes : mesh_nodes) { for (auto node : nodes) { - populateStopsMap(node->stop); + manager->populateStopsMap(node->stop);//DataManager if (node->color.has_value()) { - populateMap(node->color.value(), item, kind); + manager->populateMap(node->color.value(), item, kind);//DataManager + } + } + } +} + +/* +* get root pattern then loop over its children and do the whole extraction process by calling +* extractObjectColors to check for spgroups in pattern children +* +*/ +void ColorsExtractor::extractPatternColors(SPPattern *pattern) +{ + SPPattern *root = pattern->rootPattern(); + for (auto &child : root->children) { + extractObjectColors(&child, "pattern"); + } +} + +/* +* extract marker id from marker to get it by herf from the xml tree +* then try to cast the result to spmarker +* loop over the spmarker children and do the extraction process on every child +* by calling extractObjectColors +*/ +void ColorsExtractor::extractMarkerColors(Glib::ustring marker, SPObject *object) +{ + if (marker.size() > 0 && object->document) { + std::string marker_id = std::string(marker.c_str() + 4, std::strlen(marker.c_str()) - 5); + SPObject *m = object->document->getObjectByHref(marker_id); + if (!m) return; + if (auto marker_obj = dynamic_cast(m)) { + for (auto &child : marker_obj->item_list()) { + extractObjectColors(&*child, "marker"); + } + } + } else + return; +} + +/* +* reset selected object colors to their original colors all at once +* used when LP checkbox is unchecked +*/ +void DataManager::revertToOriginalColors(bool is_reset_clicked) +{ + for (auto &[key, items] : _selected_colors) { + if (is_reset_clicked) + items.second.value().new_color = items.second.value().old_color; + for (auto &item : items.first) { + changeObjectColor(item,key); + } + recolorStops(key, items.second.value().old_color); + } +} + +/* +* convert selected object colors to the new choosen colors all at once +* used when LP checkbox is unchecked then checked again +*/ +void DataManager::convertToRecoloredColors() +{ + for (auto [key, items] : _selected_colors) { + if (items.second.has_value()) { + std::string new_color = items.second.value().new_color.toString(); + for (auto &item : items.first) { + changeObjectColor(item,new_color); } + recolorStops(key, items.second.value().new_color); + } + } +} + +/* +* loop over selection and lowers opacity for items with color +* that doesn't match the parameter color for when user hovers on +* any colorpreview in the list to highlight the hovered on colored objects +*/ +void DataManager::changeOpacity(bool change_opacity , std::string color) +{ + for (auto &[key, value] : _selected_colors) { + Color new_color = value.second.value().new_color; + if(change_opacity && key != color) + new_color.setOpacity(0.05); + for (auto &item : value.first) { + changeObjectColor(item, new_color.toString()); + } + recolorStops(key, new_color); + } +} + +/* +* get stops vector from the _gradient_stops map and loop over it to +* set them to the new color +*/ +void DataManager::recolorStops(std::string old_color, Color new_color) +{ + auto stops_vector = _gradient_stops.find(old_color); + if (stops_vector != _gradient_stops.end()) { + for (auto &stop : stops_vector->second) { + stop->setColor(new_color); } } } -/* -* get root pattern then loop over its children and do the whole extraction process by calling -* extractObjectColors to check for spgroups in pattern children -* -*/ -void RecolorArt::extractPatternColors(SPPattern *pattern) -{ - SPPattern *root = pattern->rootPattern(); - for (auto &child : root->children) { - extractObjectColors(&child, "pattern"); - } -} +/* +* loop over stops list and populate the _gradient_stops +* it has a different type of access than the _selected_colors map +* so it has a independent map as it stores just a part of the item not the whole item +* like _selected_colors map +*/ +void DataManager::populateStopsMap(SPStop *stop) +{ + // g_message("populateStopsMap in"); + while (stop) { + std::string color = stop->getColor().toString(); + _gradient_stops[color].push_back(stop); + stop = stop->getNextStop(); + } +} + +/* +* populate _selected_colors map with the color as a string key with vector of objects that +* have the same color and a pair of colors that has the old and new colors of type color +* to ensure easy access on both colors +* +*/ +void DataManager::populateMap(Color color, SPObject *item, std::string kind) +{ + color.addOpacity(); + ColorRef ref {item, kind}; + ColorPair pair {color, color}; + std::string color_string = color.toString(true); + // search if key exist and just push the object to the objects vector + if (_selected_colors.count(color_string)) { + _selected_colors[color_string].first.push_back(ref); + } else { // create key and push the object and their color ref + colors.push_back(color); + color_wheel_colors_map[color_string]=colors.size()-1; + _selected_colors.emplace(color_string, std::make_pair(std::vector{ref}, pair)); + } +} + + + +void DataManager::changeObjectColor(const ColorRef& item, std::string color) +{ + if (item.kind == "stop") + return; + std::string k = (item.kind.find("fill") != std::string::npos) + ? "fill" + : (item.kind.find("stroke") != std::string::npos ? "stroke" : ""); + if (k == "") + return; + + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property_string(css, k.c_str(), color); + if (!item.item->getId()) // for handling text content that inheirts its style from parent + { + auto repr = item.item->parent->getRepr(); + sp_repr_css_change(repr, css, "style"); + } else + sp_desktop_apply_css_recursive(item.item, css, true); + sp_repr_css_attr_unref(css); +} + + + +bool DataManager::findSelectedColor(std::string key_color) +{ + auto _selected = _selected_colors.find(key_color); + if (_selected == _selected_colors.end()) + return false; + else + return true; +} + +void DataManager::clearData() +{ + colors.clear(); + _gradient_stops.clear(); + _selected_colors.clear(); + color_wheel_colors_map.clear(); +} + +void DataManager::setSelectedNewColor(std::vector &new_colors) +{ + for (auto &[key, value] : _selected_colors) { + int index = color_wheel_colors_map[key]; + value.second.value().new_color = new_colors[index]; + } +} + +const std::vector& DataManager::getSelectedItems(std::string key_color) +{ + if(findSelectedColor(key_color)) + return _selected_colors[key_color].first; + return {}; +} + +int DataManager::getColorIndex(std::string key_color) +{ + if (color_wheel_colors_map.find(key_color) != color_wheel_colors_map.end()) + return color_wheel_colors_map[key_color]; + return -1; +} + + +std::optional DataManager::getColor(int index) +{ + if (index < 0 || index >= colors.size()) + return std::nullopt; + + return colors[index]; +} + +void DataManager::setSelectedNewColor(std::string key_color , Color new_color) +{ + _selected_colors[key_color].second.value().new_color = new_color; +} + +std::optional DataManager::getSelectedNewColor(std::string key_color) +{ + if (findSelectedColor(key_color)) + return _selected_colors[key_color].second.value().new_color; + return std::nullopt; +} + +RecolorArt::RecolorArt() + : Gtk::Box() + ,_notebook(*_builder->get_widget("list-wheel-box")) + ,_color_wheel_page(*_builder->get_widget("color-wheel-page")) + ,_color_wheel(Gtk::make_managed(std::make_shared())) + ,_color_list(*_builder->get_widget("colors-list")) + ,_reset(*_builder->get_widget("reset")) + ,_live_preview(*_builder->get_widget("liveP")) +{ + _desktop = SP_ACTIVE_DESKTOP; + set_name("RecolorArt"); + append(get_widget(_builder, "recolor-art")); + _solid_colors->set(Color(0x000000ff)); + // when recolor widget is closed it resets opacity to mitigate the effect of getSelection function + // and reshow selection boxes again + signal_unmap().connect([&]() { + if (_manager) + _manager->changeOpacity(); + if (_desktop) + _desktop->hideSelectionBoxes(false); + }); + // hide selection boxes after widget gets mapped (this is why it connects to signal idle to activate after finishing mapping) + signal_map().connect([&]() { Glib::signal_idle().connect_once([this]() { if (_desktop) _desktop->hideSelectionBoxes(true); }); }); + _color_wheel->connect_color_changed(static_cast>([this]() { + if(_is_updating) return; // to stop recuresive calling to signal if changed from the color list page + uint32_t cc = _color_wheel->getColor().toRGBA(); + Color c(cc,true); + if(_color_wheel->getActiveIndex() != -1) { + int index = _color_wheel->getActiveIndex(); + if (!_manager->getColor(index).has_value()) + return; + _current_color_id = _manager->getColor(index).value().toString(true); + auto idx = findColorItemByKey(_current_color_id); + _selection_model->set_selected(idx.second); + onColorPickerChanged(c, true); + onOriginalColorClicked(_current_color_id); + if (_color_wheel->getHueLock()) { + if (_manager->isSelectedColorsEmpty()) + return; + std::vector new_colors = _color_wheel->getColors(); + _manager->setSelectedNewColor(new_colors); + updateColorModel(new_colors); + _manager->convertToRecoloredColors(); + } + } + })); + _color_wheel->setRecolorWidget(this); + // add hover opacity effect when hovering over markers in the wheel + _color_wheel->connect_color_hovered(static_cast>([this]() { + uint32_t cc = _color_wheel->getColor().toRGBA(); + Color c(cc,true); + if (_color_wheel->getHoverIndex() != -1) { + int index = _color_wheel->getHoverIndex(); + if (!_manager->getColor(index).has_value()) + return; + _current_color_id = _manager->getColor(index).value().toString(true); + _manager->changeOpacity(true , _current_color_id); + } + else + _manager->changeOpacity(); + })); + + + + layoutColorPicker(); + _live_preview.signal_toggled().connect(sigc::mem_fun(*this, &RecolorArt::onLivePreviewToggled)); + _live_preview.set_active(true); + _reset.signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::onResetClicked)); + + // setting up list view for the color list + _list_view = _builder->get_widget("recolor-art-list"); + _color_model = Gio::ListStore::create(); + _selection_model = Gtk::SingleSelection::create(_color_model); + _color_factory = Gtk::SignalListItemFactory::create(); + + // setup how the list item should look + _color_factory->signal_setup().connect([](Glib::RefPtr const &list_item) { + auto box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); + auto original = Gtk::make_managed(); + auto arrow = Gtk::make_managed(); + auto recolored = Gtk::make_managed(); + + auto original_preview = Gtk::make_managed(Color(0x00000000).toRGBA()); + auto recolored_preview = Gtk::make_managed(Color(0x00000000).toRGBA()); + + auto type_box = Gtk::make_managed(Gtk::Orientation::HORIZONTAL); + type_box->set_spacing(2); + type_box->set_margin_start(4); + type_box->set_hexpand(false); + type_box->set_vexpand(false); + type_box->set_halign(Gtk::Align::START); + type_box->set_valign(Gtk::Align::CENTER); + type_box->get_style_context()->add_class("type_box"); + + original_preview->set_hexpand(true); + recolored_preview->set_hexpand(true); + + original_preview->set_vexpand(true); + recolored_preview->set_vexpand(true); + + auto original_overlay = Gtk::make_managed(); + + original_overlay->set_child(*original_preview); + original_overlay->add_overlay(*type_box); + + original->append(*original_overlay); + recolored->append(*recolored_preview); + + original->set_hexpand(true); + + recolored->set_hexpand(true); + + arrow->set_from_icon_name(INKSCAPE_ICON("go-right")); + arrow->set_halign(Gtk::Align::CENTER); + arrow->set_valign(Gtk::Align::CENTER); + arrow->set_margin_top(3); + arrow->set_margin_start(6); + arrow->set_margin_end(6); + + box->set_name("original-recolor-box"); + box->append(*original); + box->append(*arrow); + box->append(*recolored); + list_item->set_data("typebox", type_box); + list_item->set_child(*box); + }); + + // setup signals for the list item children after they are created + _color_factory->signal_bind().connect([this](Glib::RefPtr const &list_item) { + auto item = std::dynamic_pointer_cast(list_item->get_item()); + if (!item) + return; + + auto box = dynamic_cast(list_item->get_child()); + if (!box || box->get_first_child() == nullptr || box->get_last_child() == nullptr) + return; + + // for hover effect + auto item_controller = Gtk::EventControllerMotion::create(); + item_controller->signal_enter().connect([box, item, this](double x, double y) { _manager->changeOpacity(true,item->key);}); + item_controller->signal_leave().connect([box, this]() { _manager->changeOpacity(); }); + + box->add_controller(item_controller); + + auto original = dynamic_cast(box->get_first_child()); + auto recolored = dynamic_cast(box->get_last_child()); + + if (original && recolored) { + colorButtons(original, item->old_color, true); + colorButtons(recolored, item->new_color); + setUpTypeBox(static_cast(list_item->get_data("typebox")), item->old_color); + + original->set_name("original"); + recolored->set_name("recolored"); + + auto original_click = Gtk::GestureClick::create(); + auto recolored_click = Gtk::GestureClick::create(); + + original_click->signal_pressed().connect( + [this, item, index = list_item->get_position()](gint n_press, gdouble x, gdouble y) { + _selection_model->set_selected(index); + onOriginalColorClicked(item->key); + }); + + recolored_click->signal_pressed().connect( + [this, item, index = list_item->get_position()](gint n_press, gdouble x, gdouble y) { + _selection_model->set_selected(index); + onOriginalColorClicked(item->key); + }); -/* -* extract marker id from marker to get it by herf from the xml tree -* then try to cast the result to spmarker -* loop over the spmarker children and do the extraction process on every child -* by calling extractObjectColors -*/ -void RecolorArt::extractMarkerColors(Glib::ustring marker, SPObject *object) -{ - // std::cout << "markerout : " << marker << std::endl; - if (marker.size() > 0 && object->document) { - // std::cout << "marker in : " << marker << std::endl; - std::string marker_id = std::string(marker.c_str() + 4, std::strlen(marker.c_str()) - 5); - // std::cout<<"marker id : "<document->getObjectByHref(marker_id); - if (!m) - // std::cout << "m is null\n"; - if (auto marker_obj = dynamic_cast(m)) { - for (auto &child : marker_obj->item_list()) { - extractObjectColors(&*child, "marker"); - } + original->add_controller(original_click); + recolored->add_controller(recolored_click); } - } else - return; -} + }); -/* -* loop over stops list and populate the _gradient_stops -* it has a different type of access than the _selected_colors map -* so it has a independent map as it stores just a part of the item not the whole item -* like _selected_colors map -*/ -void RecolorArt::populateStopsMap(SPStop *stop) -{ - // g_message("populateStopsMap in"); - while (stop) { - std::string color = stop->getColor().toString(); - _gradient_stops[color].push_back(stop); - stop = stop->getNextStop(); + _list_view->set_model(_selection_model); + _list_view->set_factory(_color_factory); + + + auto lm = _list_view->get_layout_manager(); + if (auto grid_layout = std::dynamic_pointer_cast(lm)) { + grid_layout->set_row_spacing(0); } + _list_view->set_hexpand(false); + _list_view->set_vexpand(false); + + _selection_model->signal_selection_changed().connect([this](guint pos, guint n_items) { + int index = _selection_model->get_selected(); + if (index < 0) + return; + + auto item = _color_model->get_item(index); + auto color_item = std::dynamic_pointer_cast(item); + if (!color_item) + return; + + onOriginalColorClicked(color_item->key); + }); + + _color_wheel_page.append(*_color_wheel); + // _apply = _builder->get_widget("apply"); + // _apply->signal_clicked().connect(sigc::mem_fun(*this, &RecolorArt::_onApplyButtonClicked)); } +RecolorArt::~RecolorArt() {} -/* -* populate _selected_colors map with the color as a string key with vector of objects that -* have the same color and a pair of colors that has the old and new colors of type color -* to ensure easy access on both colors -* -*/ -void RecolorArt::populateMap(Color color, SPObject *item, std::string kind) +void RecolorArt::setDesktop(SPDesktop *desktop) { - color.addOpacity(); - ColorRef ref = ColorRef(item, kind); - ColorPair pair = ColorPair(color, color); - std::string color_string = color.toString(true); - // search if key exist and just push the object to the objects vector - if (_selected_colors.count(color_string)) { - _selected_colors[color_string].first.push_back(ref); - } else { // create key and push the object and their color ref - colors.push_back(color); - color_wheel_colors_map[color_string]=colors.size()-1; - _selected_colors.emplace(color_string, std::make_pair(std::vector{ref}, pair)); + if (_desktop != desktop) { + _desktop = desktop; } + // g_message("setDesktop\n"); } /* @@ -539,12 +689,15 @@ void RecolorArt::populateMap(Color color, SPObject *item, std::string kind) void RecolorArt::generateVisualList() { _color_model->remove_all(); - for (auto &[key, value] : _selected_colors) { + for (auto &[key, value] : _manager->getSelectedColorsMap()) { auto old_color = value.second.value().old_color; auto new_color = value.second.value().new_color; _color_model->append(ColorItem::create(key, old_color, new_color)); } _color_list.append(*_list_view); + if (_color_model->get_n_items() > 0) { + _selection_model->set_selected(0); + } } /* @@ -595,12 +748,11 @@ void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) if (!box->get_children().empty()) return; - std::string color_string = color.toString(); - auto it = _selected_colors.find(color_string); - if (it != _selected_colors.end()) { - std::string size = "" + std::to_string(it->second.first.size()) + ""; + auto items = _manager->getSelectedItems(color.toString()); + if (!items.empty()) { + std::string size = "" + std::to_string(items.size()) + ""; std::map> kinds; - for (auto item : it->second.first) { + for (auto item : items) { if (item.kind == "fill") { kinds[INKSCAPE_ICON("object-fill")].first++; kinds[INKSCAPE_ICON("object-fill")].second = "fill"; @@ -626,7 +778,7 @@ void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) kinds[INKSCAPE_ICON("overlay-mask")].first++; kinds[INKSCAPE_ICON("overlay-mask")].second = "mask"; } else if (item.kind.find("swatch") != std::string::npos) { - size = "" + std::to_string(it->second.first.size() / 2) + ""; + size = "" + std::to_string(items.size() / 2) + ""; kinds[INKSCAPE_ICON("paint-swatch")].first++; kinds[INKSCAPE_ICON("paint-swatch")].second = "swatch"; // std::cout<<"Swatch : "; @@ -663,20 +815,7 @@ void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) } } -/* -* finding a color model item by key -*/ -std::pair, guint> RecolorArt::findColorItemByKey(std::string const &key) -{ - for (auto i = 0; i < _color_model->get_n_items(); i++) { - auto item = _color_model->get_item(i); - auto color_item = std::dynamic_pointer_cast(item); - if (key == color_item->key) { - return {item, i}; - } - } - return {nullptr, -1}; -} + /* * signal handler to set solid colors(color notebook at color list page),_color_picker_wdgt and the active index in @@ -684,19 +823,44 @@ std::pair, guint> RecolorArt::findColorItemByKey(std::st */ void RecolorArt::onOriginalColorClicked(std::string color_id) { - if (_color_wheel && !color_wheel_colors_map.empty()) - _color_wheel->setActiveIndex(color_wheel_colors_map[color_id]); + if (_color_wheel && !_manager->isColorWheelColorsMapEmpty()) + { + int index = _manager->getColorIndex(color_id); + if (index > -1) + _color_wheel->setActiveIndex(_manager->getColorIndex(color_id)); + } _current_color_id = color_id; - auto it = _selected_colors.find(color_id); - if (it != _selected_colors.end() && it->second.second.has_value()) { - Color color = it->second.second.value().new_color; - _solid_colors->set(color); // update sliders under the colorwheel in the colorlist page + std::optional color = _manager->getSelectedNewColor(color_id); + if (color.has_value()) { + _solid_colors->set(color.value()); // update sliders under the colorwheel in the colorlist page _color_picker_wdgt->setCurrentColor(_solid_colors); /* solves the issue of needing to create new - colornotebook every time the _solid_colors changes because it only changes the sliders not the + colornotebook every time the _solid_colors changes because it only changes the sliders not the color wheel it self in colornotebook */ } } +/* +* if LP is checked it searches for the items that has a key matching to the parameter color +* and loop on them to change their color lively +* put the recolor action into the undo stack as well +*/ +void RecolorArt::lpChecked(Color color, bool wheel) +{ + std::optional new_color = wheel ? color : _solid_colors->get(); + if (!new_color.has_value()) { + return; + } + std::string _color_string = new_color.value().toString(); + if (!_manager->findSelectedColor(_current_color_id)) { + return; + } + _manager->setSelectedNewColor(_current_color_id,new_color.value()); + for (auto &item : _manager->getSelectedItems(_current_color_id)) { + _manager->changeObjectColor(item,_color_string); + } + _manager->recolorStops(_current_color_id, new_color.value()); + DocumentUndo::done(_desktop->getDocument(), _("Recolored items"), INKSCAPE_ICON("object-recolor-art")); +} /* * this is a signal handler for when solid color changes either in the sliders or the color wheels in * both notebook pages @@ -713,9 +877,9 @@ void RecolorArt::onColorPickerChanged(Color color, bool wheel) return; } std::string _color_string = new_color.value().toString(); - auto _selected = _selected_colors.find(_current_color_id); - if (_selected != _selected_colors.end()) - _selected->second.second.value().new_color = new_color.value(); + if (_manager->findSelectedColor(_current_color_id)) + _manager->setSelectedNewColor(_current_color_id,new_color.value()); + // apply changes to selected items if (_live_preview.property_active()) { if (wheel) @@ -727,10 +891,14 @@ void RecolorArt::onColorPickerChanged(Color color, bool wheel) Glib::RefPtr item = nullptr; // if change is coming from colorlist page sync that to colorwheel page if (!wheel){ + if (!_manager || index < 0) + return; item = _color_model->get_item(index); - int i = color_wheel_colors_map[_current_color_id]; - _is_updating = true; - _color_wheel->changeColor(i,new_color.value()); + int i = _manager->getColorIndex(_current_color_id); + if (i > -1) { + _is_updating = true; + _color_wheel->changeColor(i, new_color.value()); + } } else { // if change is coming from colorwheel page sync that to colorlist page auto item_index = findColorItemByKey(_current_color_id); @@ -738,7 +906,7 @@ void RecolorArt::onColorPickerChanged(Color color, bool wheel) index = item_index.second; } if (!item) { - // g_message("ERROR: item is null"); + g_message("ERROR: item is null"); return; } // update colormodel item to refresh listview ui @@ -749,131 +917,6 @@ void RecolorArt::onColorPickerChanged(Color color, bool wheel) // g_message("color picker changed"); } -/* -* if LP is checked it searches for the items that has a key matching to the parameter color -* and loop on them to change their color lively -* put the recolor action into the undo stack as well -*/ -void RecolorArt::lpChecked(Color color, bool wheel) -{ - auto _selected = _selected_colors.find(_current_color_id); - std::optional new_color = wheel ? color : _solid_colors->get(); - if (!new_color.has_value()) { - // g_message("there is no color"); - return; - } - std::string _color_string = new_color.value().toString(); - if (_selected == _selected_colors.end()) { - // g_message("no items found"); - return; - } - _selected->second.second.value().new_color = new_color.value(); - for (auto &item : _selected->second.first) { - // std::cout << *item.item << std::endl; - // std::cout << item.kind << std::endl; - if (item.kind == "stop") - continue; - std::string k = (item.kind.find("fill") != std::string::npos) - ? "fill" - : (item.kind.find("stroke") != std::string::npos ? "stroke" : ""); - if (k == "") - continue; - - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, k.c_str(), _color_string); - if(!item.item->getId()) // for handling text content that inheirts its style from parent - { - auto repr = item.item->parent->getRepr(); - sp_repr_css_change(repr, css, "style"); - } - else - sp_desktop_apply_css_recursive(item.item, css, true); - sp_repr_css_attr_unref(css); - } - recolorStops(_selected->first, new_color.value()); - DocumentUndo::done(_desktop->getDocument(), _("Recolored items"), INKSCAPE_ICON("object-recolor-art")); -} - -/* -* signal function handler for reset button clicked -* that reset every thing to its original states -*/ -void RecolorArt::onResetClicked() -{ - _color_wheel->toggleHueLock(false); - _color_wheel->setLightness(100.0); - _color_wheel->setSaturation(100.0); - _color_wheel->setColor(colors); - updateColorModel(); - revertToOriginalColors(true); - guint index = _selection_model->get_selected(); - auto item = _color_model->get_item(index); - auto color_item = std::dynamic_pointer_cast(item); - - onOriginalColorClicked(color_item->key); -} - -/* -* reset selected object colors to their original colors all at once -* used when LP checkbox is unchecked -*/ -void RecolorArt::revertToOriginalColors(bool is_reset_clicked) -{ - for (auto &[key, items] : _selected_colors) { - if (is_reset_clicked) - items.second.value().new_color = items.second.value().old_color; - for (auto &item : items.first) { - if (item.kind == "stop") - continue; - std::string k = (item.kind.find("fill") != std::string::npos) - ? "fill" - : (item.kind.find("stroke") != std::string::npos ? "stroke" : ""); - if (k == "") - continue; - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, k.c_str(), key); - if (!item.item->getId()) { // for handling text content that inheirts its style from parent - auto repr = item.item->parent->getRepr(); - sp_repr_css_change(repr, css, "style"); - } else - sp_desktop_apply_css_recursive(item.item, css, true); - sp_repr_css_attr_unref(css); - } - recolorStops(key, items.second.value().old_color); - } -} - -/* -* convert selected object colors to the new choosen colors all at once -* used when LP checkbox is unchecked then checked again -*/ -void RecolorArt::convertToRecoloredColors() -{ - for (auto [key, items] : _selected_colors) { - if (items.second.has_value()) { - std::string new_color = items.second.value().new_color.toString(); - for (auto &item : items.first) { - if (item.kind == "stop") - continue; - std::string k = (item.kind.find("fill") != std::string::npos) - ? "fill" - : (item.kind.find("stroke") != std::string::npos ? "stroke" : ""); - if (k == "") - continue; - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, k.c_str(), new_color); - if (!item.item->getId()) { // for handling text content that inheirts its style from parent - auto repr = item.item->parent->getRepr(); - sp_repr_css_change(repr, css, "style"); - } else - sp_desktop_apply_css_recursive(item.item, css, true); - sp_repr_css_attr_unref(css); - } - recolorStops(key, items.second.value().new_color); - } - } -} - /* * update color model to refresh the listview ui with the new chossen colors */ @@ -883,7 +926,7 @@ void RecolorArt::updateColorModel(std::vector new_colors) for (auto i = 0; i < _color_model->get_n_items(); i++) { auto item = _color_model->get_item(i); auto color_item = std::dynamic_pointer_cast(item); - int index = color_wheel_colors_map[color_item->key]; + int index = _manager->getColorIndex(color_item->key); auto new_item = ColorItem::create(color_item->key, color_item->old_color, new_colors.empty() ? color_item->old_color : new_colors[index]); new_colors_buttons.push_back(new_item); @@ -892,82 +935,36 @@ void RecolorArt::updateColorModel(std::vector new_colors) } /* -* get stops vector from the _gradient_stops map and loop over it to -* set them to the new color +* finding a color model item by key */ -void RecolorArt::recolorStops(std::string old_color, Color new_color) +std::pair, guint> RecolorArt::findColorItemByKey(std::string const &key) { - auto stops_vector = _gradient_stops.find(old_color); - if (stops_vector != _gradient_stops.end()) { - for (auto &stop : stops_vector->second) { - stop->setColor(new_color); + for (auto i = 0; i < _color_model->get_n_items(); i++) { + auto item = _color_model->get_item(i); + auto color_item = std::dynamic_pointer_cast(item); + if (key == color_item->key) { + return {item, i}; } } + return {nullptr, -1}; } - /* -* loop over selection and lowers opacity for items with color -* that doesn't match the parameter color for when user hovers on -* any colorpreview in the list to highlight the hovered on colored objects +* signal function handler for reset button clicked +* that reset every thing to its original states */ -void RecolorArt::getSelection(std::string color) +void RecolorArt::onResetClicked() { - for (auto &[key, value] : _selected_colors) { - Color new_color = value.second.value().new_color; - new_color.setOpacity(0.05); - for (auto &item : value.first) { - if (key != color) { - if (item.kind == "stop") - continue; - std::string k = (item.kind.find("fill") != std::string::npos) - ? "fill" - : (item.kind.find("stroke") != std::string::npos ? "stroke" : ""); - if (k == "") - continue; - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, k.c_str(), new_color.toString()); - if (!item.item->getId()) { // for handling text content that inheirts its style from parent - auto repr = item.item->parent->getRepr(); - sp_repr_css_change(repr, css, "style"); - } else - sp_desktop_apply_css_recursive(item.item, css, true); - sp_repr_css_attr_unref(css); - } - } - if (key != color) { - recolorStops(key, new_color); - } - } -} + _color_wheel->toggleHueLock(false); + _color_wheel->setLightness(100.0); + _color_wheel->setSaturation(100.0); + _color_wheel->setColor(_manager->getColors()); + updateColorModel(); + _manager->revertToOriginalColors(true); + guint index = _selection_model->get_selected(); + auto item = _color_model->get_item(index); + auto color_item = std::dynamic_pointer_cast(item); -/* -* loop over selected objects and reset their opacity to 100 if the user isnt hovering over the -* color preview or the widget is closed -* it is the undo of the getSelection function -*/ -void RecolorArt::resetOpacity() -{ - for (auto &[key, value] : _selected_colors) { - std::string new_color = value.second.value().new_color.toString(); - for (auto &item : value.first) { - if (item.kind == "stop") - continue; - std::string k = (item.kind.find("fill") != std::string::npos) - ? "fill" - : (item.kind.find("stroke") != std::string::npos ? "stroke" : ""); - if (k == "") - continue; - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, k.c_str(), new_color); - if (!item.item->getId()) { // for handling text content that inheirts its style from parent - auto repr = item.item->parent->getRepr(); - sp_repr_css_change(repr, css, "style"); - } else - sp_desktop_apply_css_recursive(item.item, css, true); - sp_repr_css_attr_unref(css); - } - recolorStops(key, value.second.value().new_color); - } + onOriginalColorClicked(color_item->key); } /* @@ -978,9 +975,9 @@ void RecolorArt::onLivePreviewToggled() { _is_preview = _live_preview.property_active(); if (_is_preview) { - convertToRecoloredColors(); + _manager->convertToRecoloredColors(); } else { - revertToOriginalColors(); + _manager->revertToOriginalColors(); } // g_message(_is_preview ? "is true" : "is false"); // g_message("LP toggled"); @@ -1003,12 +1000,11 @@ void RecolorArt::setPaintSelector(PaintSelector *ps) */ void RecolorArt::performUpdate() { + if (!_desktop) return; for (auto child : _color_list.get_children()) { _color_list.remove(*child); } - colors.clear(); - _gradient_stops.clear(); - _selected_colors.clear(); + if(_manager) _manager->clearData(); // _current_color_id = ""; if (auto selection = _desktop->getSelection()) { if (_paint_selector) @@ -1017,12 +1013,12 @@ void RecolorArt::performUpdate() if (_paint_selector) _paint_selector->set_change_selection(false); std::vector vec(selection->items().begin(), selection->items().end()); - collectColors(vec); - if (!colors.empty()) - _color_wheel->setColor(colors); - if (!_selected_colors.empty()) { + _extractor->collectColors(vec); + if (!_manager->isColorsEmpty()) + _color_wheel->setColor(_manager->getColors()); + if (!_manager->isSelectedColorsEmpty()) { generateVisualList(); - auto first_button_id = _selected_colors.begin()->first; + auto first_button_id = _manager->getFirstKey(); onOriginalColorClicked(first_button_id); } // g_message("Performing Update\n"); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index 6dc814b830..f208b7b415 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -89,6 +89,65 @@ struct ColorItem : public Glib::Object return item; } }; + +class DataManager +{ + public : + using SelectedColorsMap = + std::unordered_map, std::optional>>; + DataManager(){} + ~DataManager(){} + void populateMap(Color color, SPObject *style, std::string kind); + void revertToOriginalColors(bool is_reset_clicked = false); + void convertToRecoloredColors(); + void populateStopsMap(SPStop *stop); + void recolorStops(std::string old_color, Color new_color); + void changeObjectColor(const ColorRef& item , std::string color); + void changeOpacity(bool change_opacity = false , std::string color=""); + void setSelectedNewColor(std::string key_color,Color new_color); + std::optional getSelectedNewColor(std::string key_color); + bool findSelectedColor(std::string key_color); + bool isSelectedColorsEmpty(){return _selected_colors.empty();} + bool isGradientStopsEmpty(){return _gradient_stops.empty();} + bool isColorWheelColorsMapEmpty(){return color_wheel_colors_map.empty();} + bool isColorsEmpty(){return colors.empty();} + void clearData(); + void setSelectedNewColor(std::vector &new_colors); + std::string getFirstKey(){return _selected_colors.begin()->first;} + const std::vector& getSelectedItems(std::string key_color); + int getColorIndex(std::string key_color); + std::vector& getColors(){return colors;} + std::optionalgetColor(int index); + SelectedColorsMap& getSelectedColorsMap(){return _selected_colors;} + private : + SelectedColorsMap _selected_colors; + std::unordered_map> _gradient_stops; + std::vector colors; + std::unordered_map color_wheel_colors_map; + +}; + +class ColorsExtractor +{ +public: + ColorsExtractor(std::shared_ptr m){ + manager = m; + }; + ~ColorsExtractor(){} + void collectColors(std::vector objects, std::string kind = ""); + +private: + std::shared_ptr manager; + void extractGradientStops(SPObject *object, bool isFill); + void extractMeshStops(std::vector> &mesh_nodes, SPObject *object, std::string kind); + void extractObjectColors(SPObject *object, std::string kind = ""); + void extractObjectStyle(SPObject *object, std::string kind = ""); + void extractPatternColors(SPPattern *pattern); + void extractMarkerColors(Glib::ustring marker, SPObject *object); +}; + + + class RecolorArt : public Gtk::Box { private: @@ -99,7 +158,6 @@ private: PaintSelector *_paint_selector; std::shared_ptr _solid_colors = std::make_shared(); sigc::connection _solid_color_changed ; - std::unordered_map, std::optional>> _selected_colors; Gtk::Box &_color_list ; Gtk::Button &_reset; Gtk::CheckButton &_live_preview; @@ -112,50 +170,28 @@ private: Glib::RefPtr _color_factory; Glib::RefPtr _selection_model; - std::unordered_map> _gradient_stops; - + std::shared_ptr _manager = std::make_shared();; + std::unique_ptr _extractor = std::make_unique(_manager);; MultiMarkerColorPlate *_color_wheel = nullptr; - std::vector colors; - std::unordered_mapcolor_wheel_colors_map; + int colors_index=0; bool _is_updating = false; bool _is_wheel_page = false; - void populateMap(Color color, SPObject *style, std::string kind); - void collectColors(std::vector& objects,std::string kind=""); - void extractGradientStops(SPObject *object, bool isFill); - void extractMeshStops(std::vector>& mesh_nodes, SPObject *object, std::string kind); - void extractObjectColors(SPObject *object,std::string kind=""); - void extractObjectStyle(SPObject *object ,std::string kind=""); - void extractPatternColors(SPPattern *pattern); - void extractMarkerColors(Glib::ustring marker, SPObject *object); void generateVisualList(); void layoutColorPicker(std::shared_ptr updated_color = nullptr); void colorButtons(Gtk::Box *button, Color color, bool is_original = false); - // void colorBorderOnClick(Gtk::Button *button, bool kind); // signals handelrs void onOriginalColorClicked(std::string color_id); void onColorPickerChanged(Color color=Color(0x00000000) , bool wheel = false); void onLivePreviewToggled(); void lpChecked(Color color=Color(0x00000000) , bool wheel = false); - void revertToOriginalColors(bool is_reset_clicked = false); - void convertToRecoloredColors(); - void updateColorModel(std::vector new_colors = std::vector{}); - // void _onApplyButtonClicked(); - - void populateStopsMap(SPStop *stop); - void recolorStops(std::string old_color, Color new_color); - - void getSelection(std::string color); - void resetOpacity(); - void setUpTypeBox(Gtk::Box *box, Color color); - + void updateColorModel(std::vector new_colors = std::vector{}); std::pair,guint> findColorItemByKey(const std::string& key); - public: RecolorArt(); ~RecolorArt(); -- GitLab From 9acfbe95869a7429277c05ff2d3eff62f9e9e208 Mon Sep 17 00:00:00 2001 From: ftomara Date: Fri, 29 Aug 2025 19:00:35 +0300 Subject: [PATCH 122/122] changed strings to uint32_t for faster operations reducing string conversions --- src/ui/widget/recolor-art.cpp | 56 ++++++++++++++++++----------------- src/ui/widget/recolor-art.h | 34 ++++++++++----------- 2 files changed, 46 insertions(+), 44 deletions(-) diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp index b6cfa2e163..171f6d55d2 100644 --- a/src/ui/widget/recolor-art.cpp +++ b/src/ui/widget/recolor-art.cpp @@ -291,7 +291,7 @@ void DataManager::revertToOriginalColors(bool is_reset_clicked) if (is_reset_clicked) items.second.value().new_color = items.second.value().old_color; for (auto &item : items.first) { - changeObjectColor(item,key); + changeObjectColor(item,items.second.value().old_color); } recolorStops(key, items.second.value().old_color); } @@ -305,7 +305,7 @@ void DataManager::convertToRecoloredColors() { for (auto [key, items] : _selected_colors) { if (items.second.has_value()) { - std::string new_color = items.second.value().new_color.toString(); + Color new_color = items.second.value().new_color; for (auto &item : items.first) { changeObjectColor(item,new_color); } @@ -319,14 +319,14 @@ void DataManager::convertToRecoloredColors() * that doesn't match the parameter color for when user hovers on * any colorpreview in the list to highlight the hovered on colored objects */ -void DataManager::changeOpacity(bool change_opacity , std::string color) +void DataManager::changeOpacity(bool change_opacity , uint32_t color) { for (auto &[key, value] : _selected_colors) { Color new_color = value.second.value().new_color; if(change_opacity && key != color) new_color.setOpacity(0.05); for (auto &item : value.first) { - changeObjectColor(item, new_color.toString()); + changeObjectColor(item, new_color); } recolorStops(key, new_color); } @@ -336,7 +336,7 @@ void DataManager::changeOpacity(bool change_opacity , std::string color) * get stops vector from the _gradient_stops map and loop over it to * set them to the new color */ -void DataManager::recolorStops(std::string old_color, Color new_color) +void DataManager::recolorStops(uint32_t old_color, Color new_color) { auto stops_vector = _gradient_stops.find(old_color); if (stops_vector != _gradient_stops.end()) { @@ -356,7 +356,7 @@ void DataManager::populateStopsMap(SPStop *stop) { // g_message("populateStopsMap in"); while (stop) { - std::string color = stop->getColor().toString(); + uint32_t color = stop->getColor().toRGBA(); _gradient_stops[color].push_back(stop); stop = stop->getNextStop(); } @@ -373,21 +373,23 @@ void DataManager::populateMap(Color color, SPObject *item, std::string kind) color.addOpacity(); ColorRef ref {item, kind}; ColorPair pair {color, color}; - std::string color_string = color.toString(true); + uint32_t color_rgba = color.toRGBA(); + auto _selected = _selected_colors.find(color_rgba); // search if key exist and just push the object to the objects vector - if (_selected_colors.count(color_string)) { - _selected_colors[color_string].first.push_back(ref); + if (_selected != _selected_colors.end()) { + _selected->second.first.push_back(ref); } else { // create key and push the object and their color ref colors.push_back(color); - color_wheel_colors_map[color_string]=colors.size()-1; - _selected_colors.emplace(color_string, std::make_pair(std::vector{ref}, pair)); + color_wheel_colors_map[color_rgba]=colors.size()-1; + _selected_colors.emplace(color_rgba, std::make_pair(std::vector{ref}, pair)); } } -void DataManager::changeObjectColor(const ColorRef& item, std::string color) +void DataManager::changeObjectColor(const ColorRef& item, Color color) { + std::string c = color.toString(true); if (item.kind == "stop") return; std::string k = (item.kind.find("fill") != std::string::npos) @@ -397,7 +399,7 @@ void DataManager::changeObjectColor(const ColorRef& item, std::string color) return; SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property_string(css, k.c_str(), color); + sp_repr_css_set_property_string(css, k.c_str(), c); if (!item.item->getId()) // for handling text content that inheirts its style from parent { auto repr = item.item->parent->getRepr(); @@ -409,7 +411,7 @@ void DataManager::changeObjectColor(const ColorRef& item, std::string color) -bool DataManager::findSelectedColor(std::string key_color) +bool DataManager::findSelectedColor(uint32_t key_color) { auto _selected = _selected_colors.find(key_color); if (_selected == _selected_colors.end()) @@ -434,14 +436,14 @@ void DataManager::setSelectedNewColor(std::vector &new_colors) } } -const std::vector& DataManager::getSelectedItems(std::string key_color) +const std::vector& DataManager::getSelectedItems(uint32_t key_color) { if(findSelectedColor(key_color)) return _selected_colors[key_color].first; return {}; } -int DataManager::getColorIndex(std::string key_color) +int DataManager::getColorIndex(uint32_t key_color) { if (color_wheel_colors_map.find(key_color) != color_wheel_colors_map.end()) return color_wheel_colors_map[key_color]; @@ -457,15 +459,16 @@ std::optional DataManager::getColor(int index) return colors[index]; } -void DataManager::setSelectedNewColor(std::string key_color , Color new_color) +void DataManager::setSelectedNewColor(uint32_t key_color , Color new_color) { _selected_colors[key_color].second.value().new_color = new_color; } -std::optional DataManager::getSelectedNewColor(std::string key_color) +std::optional DataManager::getSelectedNewColor(uint32_t key_color) { - if (findSelectedColor(key_color)) - return _selected_colors[key_color].second.value().new_color; + auto _selected = _selected_colors.find(key_color); + if (_selected != _selected_colors.end()) + return _selected->second.second.value().new_color; return std::nullopt; } @@ -500,7 +503,7 @@ RecolorArt::RecolorArt() int index = _color_wheel->getActiveIndex(); if (!_manager->getColor(index).has_value()) return; - _current_color_id = _manager->getColor(index).value().toString(true); + _current_color_id = _manager->getColor(index).value().toRGBA(); auto idx = findColorItemByKey(_current_color_id); _selection_model->set_selected(idx.second); onColorPickerChanged(c, true); @@ -524,7 +527,7 @@ RecolorArt::RecolorArt() int index = _color_wheel->getHoverIndex(); if (!_manager->getColor(index).has_value()) return; - _current_color_id = _manager->getColor(index).value().toString(true); + _current_color_id = _manager->getColor(index).value().toRGBA(); _manager->changeOpacity(true , _current_color_id); } else @@ -748,7 +751,7 @@ void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) if (!box->get_children().empty()) return; - auto items = _manager->getSelectedItems(color.toString()); + auto items = _manager->getSelectedItems(color.toRGBA()); if (!items.empty()) { std::string size = "" + std::to_string(items.size()) + ""; std::map> kinds; @@ -821,7 +824,7 @@ void RecolorArt::setUpTypeBox(Gtk::Box *box, Color color) * signal handler to set solid colors(color notebook at color list page),_color_picker_wdgt and the active index in * colorwheel page to the color of the colorpreview clicked */ -void RecolorArt::onOriginalColorClicked(std::string color_id) +void RecolorArt::onOriginalColorClicked(uint32_t color_id) { if (_color_wheel && !_manager->isColorWheelColorsMapEmpty()) { @@ -850,13 +853,12 @@ void RecolorArt::lpChecked(Color color, bool wheel) if (!new_color.has_value()) { return; } - std::string _color_string = new_color.value().toString(); if (!_manager->findSelectedColor(_current_color_id)) { return; } _manager->setSelectedNewColor(_current_color_id,new_color.value()); for (auto &item : _manager->getSelectedItems(_current_color_id)) { - _manager->changeObjectColor(item,_color_string); + _manager->changeObjectColor(item,new_color.value()); } _manager->recolorStops(_current_color_id, new_color.value()); DocumentUndo::done(_desktop->getDocument(), _("Recolored items"), INKSCAPE_ICON("object-recolor-art")); @@ -937,7 +939,7 @@ void RecolorArt::updateColorModel(std::vector new_colors) /* * finding a color model item by key */ -std::pair, guint> RecolorArt::findColorItemByKey(std::string const &key) +std::pair, guint> RecolorArt::findColorItemByKey(uint32_t const &key) { for (auto i = 0; i < _color_model->get_n_items(); i++) { auto item = _color_model->get_item(i); diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h index f208b7b415..5e38ef8392 100644 --- a/src/ui/widget/recolor-art.h +++ b/src/ui/widget/recolor-art.h @@ -76,11 +76,11 @@ struct ColorPair struct ColorItem : public Glib::Object { - std::string key; + uint32_t key; Color old_color = Color(0x00000000); Color new_color = Color(0x00000000); - static Glib::RefPtr create(std::string const& k, Color const& old_c, Color const& new_c) + static Glib::RefPtr create(uint32_t const& k, Color const& old_c, Color const& new_c) { auto item = Glib::make_refptr_for_instance(new ColorItem()); item->key = k; @@ -94,36 +94,36 @@ class DataManager { public : using SelectedColorsMap = - std::unordered_map, std::optional>>; + std::unordered_map, std::optional>>; DataManager(){} ~DataManager(){} void populateMap(Color color, SPObject *style, std::string kind); void revertToOriginalColors(bool is_reset_clicked = false); void convertToRecoloredColors(); void populateStopsMap(SPStop *stop); - void recolorStops(std::string old_color, Color new_color); - void changeObjectColor(const ColorRef& item , std::string color); - void changeOpacity(bool change_opacity = false , std::string color=""); - void setSelectedNewColor(std::string key_color,Color new_color); - std::optional getSelectedNewColor(std::string key_color); - bool findSelectedColor(std::string key_color); + void recolorStops(uint32_t old_color, Color new_color); + void changeObjectColor(const ColorRef& item , Color color); + void changeOpacity(bool change_opacity = false , uint32_t color= 0); + void setSelectedNewColor(uint32_t key_color,Color new_color); + std::optional getSelectedNewColor(uint32_t key_color); + bool findSelectedColor(uint32_t key_color); bool isSelectedColorsEmpty(){return _selected_colors.empty();} bool isGradientStopsEmpty(){return _gradient_stops.empty();} bool isColorWheelColorsMapEmpty(){return color_wheel_colors_map.empty();} bool isColorsEmpty(){return colors.empty();} void clearData(); void setSelectedNewColor(std::vector &new_colors); - std::string getFirstKey(){return _selected_colors.begin()->first;} - const std::vector& getSelectedItems(std::string key_color); - int getColorIndex(std::string key_color); + uint32_t getFirstKey(){return _selected_colors.begin()->first;} + const std::vector& getSelectedItems(uint32_t key_color); + int getColorIndex(uint32_t key_color); std::vector& getColors(){return colors;} std::optionalgetColor(int index); SelectedColorsMap& getSelectedColorsMap(){return _selected_colors;} private : SelectedColorsMap _selected_colors; - std::unordered_map> _gradient_stops; + std::unordered_map> _gradient_stops; std::vector colors; - std::unordered_map color_wheel_colors_map; + std::unordered_map color_wheel_colors_map; }; @@ -163,7 +163,7 @@ private: Gtk::CheckButton &_live_preview; Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr ; Gtk::ListView *_list_view = nullptr; - std::string _current_color_id; + uint32_t _current_color_id; bool _is_preview = false; Glib::RefPtr> _color_model; @@ -184,13 +184,13 @@ private: void colorButtons(Gtk::Box *button, Color color, bool is_original = false); // signals handelrs - void onOriginalColorClicked(std::string color_id); + void onOriginalColorClicked(uint32_t color_id); void onColorPickerChanged(Color color=Color(0x00000000) , bool wheel = false); void onLivePreviewToggled(); void lpChecked(Color color=Color(0x00000000) , bool wheel = false); void setUpTypeBox(Gtk::Box *box, Color color); void updateColorModel(std::vector new_colors = std::vector{}); - std::pair,guint> findColorItemByKey(const std::string& key); + std::pair,guint> findColorItemByKey(const uint32_t& key); public: RecolorArt(); -- GitLab