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 0000000000000000000000000000000000000000..b078cf421c5c1beec4852445a720247bf9c2827c
--- /dev/null
+++ b/share/icons/Dash/symbolic/actions/object-recolor-art-symbolic.svg
@@ -0,0 +1,5 @@
+
+
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 0000000000000000000000000000000000000000..7d47572893ed89f875798b4b0e353615b756fc70
--- /dev/null
+++ b/share/icons/Dash/symbolic/actions/reset-colors-symbolic.svg
@@ -0,0 +1,4 @@
+
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 09c40a1e3021e4ad13a7d5a0086ef0a972d948e6..0000000000000000000000000000000000000000
--- a/share/icons/Dash/symbolic/actions/reset-symbolic.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-
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 0000000000000000000000000000000000000000..7d47572893ed89f875798b4b0e353615b756fc70
--- /dev/null
+++ b/share/icons/hicolor/symbolic/actions/reset-colors-symbolic.svg
@@ -0,0 +1,4 @@
+
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 7dcef2b3f70fffc0d4e14bd1fdd4381979bf9177..0000000000000000000000000000000000000000
--- a/share/icons/hicolor/symbolic/actions/reset-symbolic.svg
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-
-
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 0000000000000000000000000000000000000000..b078cf421c5c1beec4852445a720247bf9c2827c
--- /dev/null
+++ b/share/icons/multicolor/symbolic/actions/object-recolor-art-symbolic.svg
@@ -0,0 +1,5 @@
+
+
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 0000000000000000000000000000000000000000..7d47572893ed89f875798b4b0e353615b756fc70
--- /dev/null
+++ b/share/icons/multicolor/symbolic/actions/reset-colors-symbolic.svg
@@ -0,0 +1,4 @@
+
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 7dcef2b3f70fffc0d4e14bd1fdd4381979bf9177..0000000000000000000000000000000000000000
--- 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
new file mode 100644
index 0000000000000000000000000000000000000000..d1488022ed8302538aa164968871c2dcc6fb9896
--- /dev/null
+++ b/share/ui/recolor-art.glade
@@ -0,0 +1,181 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/share/ui/style.css b/share/ui/style.css
index 5a9f9d2bf1d470bd221d55214edf8cb1777ab482..6500c1e2986369acf1cdf14237d7236d55ea85dc 100644
--- a/share/ui/style.css
+++ b/share/ui/style.css
@@ -67,7 +67,7 @@
* "..combobright" Combo bright
*/
-*{
+* {
font-feature-settings: "tnum";
}
@@ -75,9 +75,11 @@
.view.image {
color: @theme_fg_color;
}
+
.view.image:backdrop {
color: @theme_unfocused_fg_color;
}
+
.view.image:disabled {
color: @insensitive_fg_color;
}
@@ -102,7 +104,7 @@
-gtk-icon-style: symbolic;
}
-.titlebutton > image {
+.titlebutton>image {
-gtk-icon-style: requested;
}
@@ -118,32 +120,58 @@
.highlight {
color: @theme_fg_color;
- background-color: alpha(@theme_selected_bg_color,0.5);
- background-image: image(alpha(@theme_selected_bg_color,0.5));
+ background-color: alpha(@theme_selected_bg_color, 0.5);
+ background-image: image(alpha(@theme_selected_bg_color, 0.5));
caret-color: @theme_bg_color;
- border-radius:4px;
+ border-radius: 4px;
-gtk-secondary-caret-color: @theme_fg_color;
}
-.noborder{
- border-width:0;
+.noborder {
+ border-width: 0;
}
/* blinking animation for dialogs reopen*/
@keyframes blink_border {
- 0% { border-color: @theme_selected_fg_color;}
- 90% { border-color: @theme_selected_bg_color; }
- 100% { border-color: @theme_selected_fg_color; }
+ 0% {
+ border-color: @theme_selected_fg_color;
+ }
+
+ 90% {
+ border-color: @theme_selected_bg_color;
+ }
+
+ 100% {
+ border-color: @theme_selected_fg_color;
+ }
}
+
@keyframes blink_background {
- 0% { background-color: @theme_bg_color; }
- 90% { background-color: @theme_selected_bg_color; }
- 100% { background-color: @theme_bg_color; }
+ 0% {
+ background-color: @theme_bg_color;
+ }
+
+ 90% {
+ background-color: @theme_selected_bg_color;
+ }
+
+ 100% {
+ background-color: @theme_bg_color;
+ }
}
+
@keyframes blink_background_img {
- 0% { background-image: image(@theme_bg_color); }
- 90% { background-image: image(@theme_selected_bg_color); }
- 100% { background-image: image(@theme_bg_color); }
+ 0% {
+ background-image: image(@theme_bg_color);
+ }
+
+ 90% {
+ background-image: image(@theme_selected_bg_color);
+ }
+
+ 100% {
+ background-image: image(@theme_bg_color);
+ }
}
button.blink {
@@ -151,11 +179,11 @@ button.blink {
}
notebook.blink {
- animation: 0.5s blink_border 0.1s ease 1;
+ animation: 0.5s blink_border 0.1s ease 1;
}
-notebook.blink > header > tabs > tab:checked {
- animation: 0.5s blink_background 0.1s ease 1;
+notebook.blink>header>tabs>tab:checked {
+ animation: 0.5s blink_background 0.1s ease 1;
}
.inverted :not(menuitem):not(.rawstyle):not(overshoot):not(undershoot):not(selection),
@@ -167,17 +195,19 @@ notebook.blink > header > tabs > tab:checked {
}
.dark .combobright .combo,
-.dark .combobright menu{
+.dark .combobright menu {
background-color: @theme_text_color;
background-image: linear-gradient(to top, @theme_text_color, @theme_fd_color);
caret-color: @theme_base_color;
-gtk-secondary-caret-color: @theme_base_color;
}
-.dark .combobright box *{
+
+.dark .combobright box * {
color: @theme_base_color;
}
+
.dark .combobright .combo *,
-.dark .combobright menu *{
+.dark .combobright menu * {
color: inherit;
}
@@ -225,10 +255,10 @@ iconview *:hover {
border-color: @theme_bg_color;
}
-#startscreennotebook iconview *:hover{
- background-color:@theme_selected_bg_color;
- border-radius:5px;
- border-width:0;
+#startscreennotebook iconview *:hover {
+ background-color: @theme_selected_bg_color;
+ border-radius: 5px;
+ border-width: 0;
}
.inksmall {
@@ -255,7 +285,8 @@ iconview *:hover {
}
#CommandPaletteBase {
- background-color: @theme_base_color; /* some themes don't seem to have a background color for list rows defined and would end up transparent otherwise */
+ background-color: @theme_base_color;
+ /* some themes don't seem to have a background color for list rows defined and would end up transparent otherwise */
border: 5px solid @theme_bg_color;
border-radius: 5px;
}
@@ -308,18 +339,18 @@ iconview *:hover {
border-width: 0;
}
-#SelectorsAndStyleDialog #StyleDialog treeview button *{
- font-size:5px;
- min-height:1px;
- padding:0;
- margin:0;
+#SelectorsAndStyleDialog #StyleDialog treeview button * {
+ font-size: 5px;
+ min-height: 1px;
+ padding: 0;
+ margin: 0;
}
#SelectorsAndStyleDialog #StyleDialog treeview button {
- padding:0;
- min-height:1px;
- border-left-width:4px;
- border-color:@success_color;
+ padding: 0;
+ min-height: 1px;
+ border-left-width: 4px;
+ border-color: @success_color;
}
/* ink-ruler */
@@ -346,25 +377,28 @@ iconview *:hover {
/* Ensure ui/themes.cpp excludes these classes on applying overridebasecolor: */
.bright #InkRuler.shadow {
- color: rgba(0,0,0,0.3);
+ color: rgba(0, 0, 0, 0.3);
}
+
.dark #InkRuler.shadow {
- color: rgba(0,0,0,0.5);
+ color: rgba(0, 0, 0, 0.5);
}
.bright #InkRuler.page {
color: @theme_base_color;
}
+
.dark #InkRuler.page {
color: shade(@theme_base_color, 0.666);
}
.bright #InkRuler.selection.border,
-.dark #InkRuler.selection.border {
+.dark #InkRuler.selection.border {
color: @theme_selected_bg_color;
}
+
.bright #InkRuler.selection.background,
-.dark #InkRuler.selection.background {
+.dark #InkRuler.selection.background {
color: transparent;
}
@@ -374,7 +408,9 @@ SPCanvas {
}
/* Those are three buttons in canvas corners; their size dictates how large scrollbars are */
-#QuickActions, #LockGuides, #CMS_Adjust {
+#QuickActions,
+#LockGuides,
+#CMS_Adjust {
padding: 0;
margin: 0;
outline: none;
@@ -383,10 +419,14 @@ SPCanvas {
min-width: 22px;
min-height: 22px;
}
+
/* Don't let images inside those buttons inflate their sizes */
-#QuickActions *, #LockGuides *, #CMS_Adjust * {
+#QuickActions *,
+#LockGuides *,
+#CMS_Adjust * {
padding: 0;
}
+
#QuickActions image {
margin-top: 1px;
}
@@ -433,13 +473,15 @@ SPCanvas {
#InkSpinScale scale {
padding: 0px;
- margin:0;
+ margin: 0;
}
#InkSpinScale trough {
min-height: 25px;
- padding: 0; /* remove padding to make inkspinscale the same height as spinbutton */
+ padding: 0;
+ /* remove padding to make inkspinscale the same height as spinbutton */
}
+
#InkSpinScale trough highlight {
margin: 0;
}
@@ -451,7 +493,7 @@ SPCanvas {
#InkSpinScale spinbutton {
box-shadow: none;
min-height: 10px;
- border-left:0;
+ border-left: 0;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
@@ -470,10 +512,11 @@ SPCanvas {
outline-width: 5px;
outline-color: alpha(@theme_fg_color, 0.1);
}
+
#Objects .search {
- padding: 2px 4px;
- min-height: 16px;
- font-size: smaller;
+ padding: 2px 4px;
+ min-height: 16px;
+ font-size: smaller;
}
#SimpleFilterModifier #InkSpinScale {
@@ -484,6 +527,7 @@ SPCanvas {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
+
#CompletionPopup button {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
@@ -509,7 +553,7 @@ treeview.view:drop(active).before {
border-radius: 10px;
}
-button.close-button{
+button.close-button {
background-image: none;
padding: 0px;
min-height: 1px;
@@ -519,7 +563,7 @@ button.close-button{
box-shadow: none;
}
-button.close-button:hover{
+button.close-button:hover {
box-shadow: none;
opacity: 1;
}
@@ -528,27 +572,29 @@ button.close-button:hover{
* Inkscape start dialog styles
*/
-#start-screen-window .titlebar stack { /* banner-stack */
+#start-screen-window .titlebar stack {
+ /* banner-stack */
padding: 0;
/* opaque bg at bottom corners, rather than having gap, which in GTK3 glitches in transition */
background: linear-gradient(to bottom, transparent 0%, transparent 50%, @theme_bg_color);
}
#start-screen-window .combo {
- padding:1px 10px;
+ padding: 1px 10px;
}
+
#start-screen-window .combo * {
- padding:2px;
+ padding: 2px;
}
#start-screen-window grid label {
- font-size:small;
- margin:12px;
+ font-size: small;
+ margin: 12px;
}
#start-screen-window * {
- outline:0;
+ outline: 0;
}
button.link:hover image {
@@ -558,6 +604,7 @@ button.link:hover image {
.marker-item-box {
padding: 1px;
}
+
.marker-separator {
padding: 0;
}
@@ -592,6 +639,7 @@ stackswitcher button {
margin: 0;
min-width: 16px;
}
+
.color-palette-main-box flowbox,
.color-palette-main-box scrolledwindow {
padding: 0;
@@ -600,6 +648,7 @@ stackswitcher button {
min-width: 1px;
min-height: 1px;
}
+
/* remove padding/margins from FlowBoxChild widgets,
* so previews can be adjacent to each other */
.color-palette-main-box flowboxchild {
@@ -609,6 +658,7 @@ stackswitcher button {
min-width: 1px;
min-height: 1px;
}
+
/*removes dashed line (scrolling indicator) on color palette for all themes */
.color-palette-main-box scrolledwindow undershoot.top,
.color-palette-main-box scrolledwindow undershoot.right,
@@ -624,33 +674,36 @@ stackswitcher button {
}
@keyframes pulse {
- 0% {
- opacity: 0.3;
- }
- 50% {
- opacity: 0.9;
- }
- 100% {
- opacity: 0.3;
- }
+ 0% {
+ opacity: 0.3;
+ }
+
+ 50% {
+ opacity: 0.9;
+ }
+
+ 100% {
+ opacity: 0.3;
+ }
}
.backgnd-active {
- animation-name: pulse;
- background-color: @theme_selected_bg_color;
- animation-duration: 1s;
- animation-timing-function: ease;
- animation-iteration-count: infinite;
+ animation-name: pulse;
+ background-color: @theme_selected_bg_color;
+ animation-duration: 1s;
+ animation-timing-function: ease;
+ animation-iteration-count: infinite;
}
-.nb-highlight > header.top {
- background-color: @theme_selected_bg_color;
+.nb-highlight>header.top {
+ background-color: @theme_selected_bg_color;
}
.tight-flowbox flowboxchild {
margin: 0;
padding: 0px;
}
+
.tight-flowbox button {
margin: 0;
padding: 4px;
@@ -690,7 +743,8 @@ button.square-button image {
}
.tag-box label {
- min-width: 2em; /* don't let it collapse */
+ min-width: 2em;
+ /* don't let it collapse */
margin-right: 1px;
margin-left: 8px;
}
@@ -701,11 +755,10 @@ button.square-button image {
}
/* Give layer selector button label a highlight color */
-#LayerSelector label
-{
+#LayerSelector label {
padding-left: 6px;
border-left-style: solid;
- border-left-width: 3px ;
+ border-left-width: 3px;
/* Color is set in src/ui/widget/layer-selector.cpp */
}
@@ -714,17 +767,18 @@ button.square-button image {
padding-right: 3px;
}
-#DialogNotebook #Swatches #ColorItem.group + label {
+#DialogNotebook #Swatches #ColorItem.group+label {
font-weight: bold;
}
-#DialogNotebook #Swatches #ColorItem.paint-none + label {
+#DialogNotebook #Swatches #ColorItem.paint-none+label {
font-style: italic;
}
#StyleSwatch {
font-size: smaller;
}
+
#StyleSwatch.vertical {
line-height: 0.8;
/* Extra height for text descenders (?) makes style swatch bounding box too tall enlarging toolbars;
@@ -748,17 +802,21 @@ button.square-button image {
/* heading label in dialogs */
.heading {
font-weight: bold;
- font-size: 1.1em; /* make it optically comparable with non-bold */
+ font-size: 1.1em;
+ /* make it optically comparable with non-bold */
margin-top: 0.5em;
}
+
/* topmost heading in dialogs */
.heading.top {
margin-top: 0.2em;
}
+
/* slightly smaller (sub)heading label in dialogs */
.heading1 {
font-weight: bold;
- font-size: 1em; /* make it optically comparable with non-bold */
+ font-size: 1em;
+ /* make it optically comparable with non-bold */
margin-top: 0.5em;
}
@@ -774,18 +832,22 @@ button.square-button image {
.inkscape-toolbar {
margin: 4px;
}
-.inkscape-toolbar > * {
+
+.inkscape-toolbar>* {
margin-right: 2px;
margin-left: 2px;
}
-.inkscape-toolbar > box > image,
-.inkscape-toolbar > box > label {
+
+.inkscape-toolbar>box>image,
+.inkscape-toolbar>box>label {
margin-right: 2px;
}
-.inkscape-toolbar popover content > * {
+
+.inkscape-toolbar popover content>* {
margin-right: 2px;
margin-left: 2px;
}
+
/* Revise for gtk4: There's no box in popover */
/*.inkscape-toolbar > popover > box {*/
/* margin: 4px 3px;*/
@@ -823,15 +885,18 @@ button.menu-btn-tight {
#DesktopStatusBar {
margin-right: 1em;
}
+
/*
* Inkscape Export Dialog
*/
-#ExportDialog #export_selection{
+#ExportDialog #export_selection {
border-radius: 0px;
}
+
#ExportDialog #export_preview_single {
border: 1px solid;
}
+
#ExportDialog #export_preview_batch {
border: 1px solid;
}
@@ -848,29 +913,33 @@ combobox.flat-combobox button {
background-image: image(transparent);
}
-.filter-effects, .effects-params {
+.filter-effects,
+.effects-params {
min-height: 50px;
}
/* Defeat standard darker background color on views: use popoverʼs background */
popover.background.filter-effects-info textview,
-popover.background.filter-effects-info textview > text {
+popover.background.filter-effects-info textview>text {
background: none;
}
.dark .symbolsoverlay iconview:not(:selected) {
- background-color: #f0f0f0; /* bright background color for typically black symbols */
+ background-color: #f0f0f0;
+ /* bright background color for typically black symbols */
/* background-color: @theme_fg_color; - this doesn't work for some themes (like MonoThemeDark) */
- color:@theme_bg_color; /* symbol text labels */
+ color: @theme_bg_color;
+ /* symbol text labels */
}
.dark .symbolsoverlay {
- color: @theme_bg_color; /* this is for overlay widget's children */
+ color: @theme_bg_color;
+ /* this is for overlay widget's children */
}
/* LPE Dialog add */
#LPEScrolled {
- border:none;
+ border: none;
}
#LPESelectorFlowBox GtkFlowBoxChild,
@@ -934,12 +1003,12 @@ popover.background.filter-effects-info textview > text {
margin: 0px 0px 10px 0px;
border-radius: 0px;
border-width: 0 0 1px 0;
- padding:5px;
+ padding: 5px;
}
-#LPESelectorFlowBox image{
- background-color:@theme_bg_color;
- border-color:transparent;
+#LPESelectorFlowBox image {
+ background-color: @theme_bg_color;
+ border-color: transparent;
}
#LPEExperimental image {
@@ -953,29 +1022,29 @@ popover.background.filter-effects-info textview > text {
}
#LPEDialogSelector.LPEPackMore flowboxchild {
-margin:5px 1px 0px;
-padding:3px 3px 10px 3px;
+ margin: 5px 1px 0px;
+ padding: 3px 3px 10px 3px;
}
#LPEDialogSelector.LPEList .lpename {
margin-bottom: 1px;
- font-weight:bold;
+ font-weight: bold;
}
#LPEDialogSelector.LPEList flowboxchild {
- padding:3px 1px 3px 10px;
- margin:1px 0px 1px;
- border-radius:0;
- border-style:dotted;
- border-color:@theme_fg_color;
+ padding: 3px 1px 3px 10px;
+ margin: 1px 0px 1px;
+ border-radius: 0;
+ border-style: dotted;
+ border-color: @theme_fg_color;
border-width: 0 0 1px 0;
}
#LPEDialogSelector.LPEList flowboxchild:selected {
- border-style:none;
- margin:-3px 0px 0px;
- padding:4px 1px 4px 10px;
+ border-style: none;
+ margin: -3px 0px 0px;
+ padding: 4px 1px 4px 10px;
}
#LPEDialogSelector.LPEList #LPESelectorFlowBox *:selected #LPESelectorEffectFavTop,
@@ -984,132 +1053,139 @@ padding:3px 3px 10px 3px;
}
#LivePathEffect {
- padding-top:5px;
+ padding-top: 5px;
}
-#LivePathEffect expander:focus, #LivePathEffect expander > label:focus{
- outline-width:0;
+#LivePathEffect expander:focus,
+#LivePathEffect expander>label:focus {
+ outline-width: 0;
}
-#LivePathEffect list{
- margin:5px 5px 0 5px;
+#LivePathEffect list {
+ margin: 5px 5px 0 5px;
}
-#LivePathEffect list row{
- margin:0;
- padding:0;
- border-width:0;
- border-style:none;
- outline-width:0;
+#LivePathEffect list row {
+ margin: 0;
+ padding: 0;
+ border-width: 0;
+ border-style: none;
+ outline-width: 0;
}
-#LivePathEffect list row > box{
- margin:0;
- padding:1px;
- border-width:1px;
- border-radius:4px;
- margin-bottom:5px;
- border-style:solid;
- border-color:@borders;
- outline-width:0;
+
+#LivePathEffect list row>box {
+ margin: 0;
+ padding: 1px;
+ border-width: 1px;
+ border-radius: 4px;
+ margin-bottom: 5px;
+ border-style: solid;
+ border-color: @borders;
+ outline-width: 0;
}
-#LivePathEffect list row:last-child > box{
- margin-bottom:0px;
+#LivePathEffect list row:last-child>box {
+ margin-bottom: 0px;
}
-#LPEEffectItem{
- border-radius:3px;
- padding:2px;
- outline:0;
+#LPEEffectItem {
+ border-radius: 3px;
+ padding: 2px;
+ outline: 0;
}
#LPEEffectItem .minbutton {
- padding:0;
- margin:0;
- outline:0;
- border-color:@borders;
+ padding: 0;
+ margin: 0;
+ outline: 0;
+ border-color: @borders;
}
#LPEEffectItem expander title label {
- min-height:26px;
+ min-height: 26px;
}
-#LPEEffectItem expander,
+#LPEEffectItem expander,
#LPEEffectItem expander *,
-#LPEEffectItem expander:focus,
+#LPEEffectItem expander:focus,
#LPEEffectItem expander *:focus {
- outline:0;
+ outline: 0;
}
-.LPEDrag,.LPEDrag:active,.LPEDrag:focus,.LPEDrag:hover {
- margin:0;
- padding:0;
- border-style:none;
- opacity:0.7;
- background-color:transparent;
- background-image:none;
- outline:0;
+.LPEDrag,
+.LPEDrag:active,
+.LPEDrag:focus,
+.LPEDrag:hover {
+ margin: 0;
+ padding: 0;
+ border-style: none;
+ opacity: 0.7;
+ background-color: transparent;
+ background-image: none;
+ outline: 0;
}
.LPEDrag:hover {
- opacity:1;
- background-color:transparent;
- background-image:none;
+ opacity: 1;
+ background-color: transparent;
+ background-image: none;
}
-#LivePathEffect list#LPEParentBox row{
- border-style:none;
- outline:0;
+#LivePathEffect list#LPEParentBox row {
+ border-style: none;
+ outline: 0;
}
-#LivePathEffect list#LPEParentBox row > button {
- padding:2px;
- margin:0;
+#LivePathEffect list#LPEParentBox row>button {
+ padding: 2px;
+ margin: 0;
}
#LPEContainer:drop(active) {
- box-shadow:none;
+ box-shadow: none;
}
-#LPECurrentItem *{
- color:@theme_fg_color;
+#LPECurrentItem * {
+ color: @theme_fg_color;
}
-#LPEContainer #LPEListBox{
+#LPEContainer #LPEListBox {
border-style: solid none solid none;
border-color: @theme_base_color;
- border-width:0;
- padding:0;
+ border-width: 0;
+ padding: 0;
}
-#LPEListBox row:drop(active){
- box-shadow:none;
+
+#LPEListBox row:drop(active) {
+ box-shadow: none;
}
-#LPEContainer:drop(active).before row:first-child > box,
-#LPEListBox row:drop(active).before > box{
- border-width:6px 1px 1px 1px;
+
+#LPEContainer:drop(active).before row:first-child>box,
+#LPEListBox row:drop(active).before>box {
+ border-width: 6px 1px 1px 1px;
border-color: @theme_selected_bg_color @borders @borders @borders;
- box-shadow:none;
- border-radius:6px 6px 0 0;
+ box-shadow: none;
+ border-radius: 6px 6px 0 0;
}
-#LPEContainer:drop(active).after row:last-child > box,
-#LPEListBox row:drop(active).after > box{
- border-width:1px 1px 6px 1px;
+#LPEContainer:drop(active).after row:last-child>box,
+#LPEListBox row:drop(active).after>box {
+ border-width: 1px 1px 6px 1px;
border-color: @borders @borders @theme_selected_bg_color @borders;
- border-radius:0 0 6px 6px;
- box-shadow:none;
+ border-radius: 0 0 6px 6px;
+ box-shadow: none;
}
#LPEEffectItem expander title label {
- min-height:34px;
+ min-height: 34px;
}
#LPEMenu menuitem:not(.menu-category):disabled {
- color:alpha(@theme_text_color,0.4);
+ color: alpha(@theme_text_color, 0.4);
}
-#LPEListBox row > *:disabled * {
- color:@theme_text_color;
+#LPEListBox row>*:disabled * {
+ color: @theme_text_color;
}
@@ -1121,44 +1197,49 @@ padding:3px 3px 10px 3px;
#LivePathEffect list row .drag-icon,
#LPEListBox row.activatable .drag-icon:hover {
background-color: @theme_base_color;
- border-width:1px;
- border-radius:0;
- margin:0;
- padding:5px;
- border-style:solid;
- border-color:@borders;
- outline-width:0;
+ border-width: 1px;
+ border-radius: 0;
+ margin: 0;
+ padding: 5px;
+ border-style: solid;
+ border-color: @borders;
+ outline-width: 0;
}
#LivePathEffect list row .drag-icon * {
- outline:0;
+ outline: 0;
}
-#LPEActionButtons #eventbutton:nth-child(1) button{
- border-radius:3px 0 0 3px;
- border-width:1px 0 1px 1px;
+#LPEActionButtons #eventbutton:nth-child(1) button {
+ border-radius: 3px 0 0 3px;
+ border-width: 1px 0 1px 1px;
}
-#LPEActionButtons #eventbutton:nth-child(2) button{
- border-radius:0;
- border-width:1px 0 1px 1px;
+#LPEActionButtons #eventbutton:nth-child(2) button {
+ border-radius: 0;
+ border-width: 1px 0 1px 1px;
}
+
#LPECurrentItem * {
- border-width:0;
- border-style:none;
+ border-width: 0;
+ border-style: none;
}
+
#LPECurrentItem {
- margin-top:0;
+ margin-top: 0;
}
-#LPECurrentItem image{
- margin-right:6px;
+
+#LPECurrentItem image {
+ margin-right: 6px;
}
+
#LPECurrentItem {
- margin-top:0;
+ margin-top: 0;
}
-#LPEParentBox{
- margin:10px 4px;
- padding:0;
+
+#LPEParentBox {
+ margin: 10px 4px;
+ padding: 0;
}
/* min size for an angle slider in gradient editor */
@@ -1168,24 +1249,30 @@ padding:3px 3px 10px 3px;
/* Gtk::PopoverMenu and Inkscape::UI::Widget::PopoverMenu */
/* Make it look basically like GtkMenu; see comments @ original merge request */
-popover.menu, /* GTK sets .menu/make_menuized_popover() sets .menuize */
-popover.popover-menu { /* Inkscape::UI::Widget::PopoverMenu */
+popover.menu,
+/* GTK sets .menu/make_menuized_popover() sets .menuize */
+popover.popover-menu {
+ /* Inkscape::UI::Widget::PopoverMenu */
/* Rounded corners can glitch in GTK3 with submenus, and GtkMenu was square anyway = emulate */
border-radius: 0;
border-color: @borders;
padding: 0;
}
+
popover.popover-menu contents {
padding: 1px 0;
}
+
popover.popover-menu menu {
background: none;
border: none;
}
+
popover.popover-menu .menu-category {
min-height: 16px;
padding: 2px 10px;
}
+
/* popover.menu modelbutton, */
popover.popover-menu .regular-item {
border-radius: 0;
@@ -1193,21 +1280,26 @@ popover.popover-menu .regular-item {
min-height: 23px;
padding: 2px 10px;
}
+
popover.popover-menu menuitem:hover {
background-color: @theme_selected_bg_color;
color: @theme_selected_fg_color;
}
+
popover.popover-menu menuitem:hover image {
background-color: @theme_selected_bg_color;
color: @theme_selected_fg_color;
}
+
popover.popover-menu separator {
margin: 1px 0;
}
+
/* Defeat defaulting to having more spacing between RadioButtons than GtkMenu */
popover.popover-menu radiobutton {
padding: 0;
}
+
/* Emulate GtkMenu theming in absence of ability to change CSS node name, unlike our PopoverMenu */
/* popover.menu modelbutton:focus,
popover.menu modelbutton:hover {
@@ -1215,18 +1307,22 @@ popover.menu modelbutton:hover {
color: @theme_selected_fg_color;
} */
/* UGH! GtkMenuSectionBox has Widget:margin = 10px. Counteract to look like popover.popover-menu */
-popover.menu > stack > box {
+popover.menu>stack>box {
margin: -2px -6px;
}
+
/* Detect submenu headings & replicate GTK .dim-label, looks nicer than leaving normal fg colour */
-popover.menu > stack > box > modelbutton:first-child > * /* Affect children not bgcolour */
-{
+popover.menu>stack>box>modelbutton:first-child>*
+
+/* Affect children not bgcolour */
+ {
opacity: 0.55;
}
/* regular popover that has no arrow and pretends to be a dropdown menu */
popover.popup-menu contents {
- margin-top: 1px; /* distance from the bottom of the button above this menu */
+ margin-top: 1px;
+ /* distance from the bottom of the button above this menu */
}
/* darker background for extensions gallery due to fixed-color thumbnails (white background + drop shadow) */
@@ -1239,20 +1335,22 @@ popover.popup-menu contents {
margin-top: 1px;
margin-bottom: 1px;
}
+
#tool-toolbar button {
margin-left: 1px;
margin-right: 1px;
}
+
#tool-toolbar {
- margin: 1px; /* toolbar box itself, so it has some breathing space; other toolbars have much larger margins */
+ margin: 1px;
+ /* toolbar box itself, so it has some breathing space; other toolbars have much larger margins */
}
/* used @ ui/themes to get correct foreground color; get_color() can be wrong */
/* Asterisks & stuff in the selectors are just to ensure sufficient priority. */
*.theme_fg_color,
*.theme_fg_color:not(:backdrop),
-*.theme_fg_color:backdrop
-{
+*.theme_fg_color:backdrop {
color: @theme_fg_color;
}
@@ -1261,21 +1359,20 @@ popover.popup-menu contents {
Asterisks & stuff in the selectors are just to ensure sufficient priority. */
*.theme_bg_color,
*.theme_bg_color:not(:backdrop),
-*.theme_bg_color:backdrop
-{
+*.theme_bg_color:backdrop {
color: @theme_bg_color;
}
+
*.theme_selected_bg_color,
*.theme_selected_bg_color:not(:backdrop),
-*.theme_selected_bg_color:backdrop
-{
+*.theme_selected_bg_color:backdrop {
color: @theme_selected_bg_color;
}
/* ColorSlider */
#ColorSlider {
- min-width : 96px;
- min-height: 8px;
+ min-width: 96px;
+ min-height: 8px;
}
#ColorPicker {
@@ -1283,24 +1380,28 @@ popover.popup-menu contents {
min-width: 24px;
min-height: 24px;
}
-#ColorPicker > button {
+
+#ColorPicker>button {
border-width: 0;
padding: 0;
}
-#ColorPicker > .toggle {
+
+#ColorPicker>.toggle {
border-width: 0;
padding: 0;
}
/* ColorPreview */
#ColorPreview {
- min-width : 16px;
+ min-width: 16px;
min-height: 16px;
}
+
#ColorPreview.simple {
- min-width : 32px;
+ min-width: 32px;
min-height: 12px;
}
+
#ColorPreview:hover:not(.simple) {
border-radius: 3px;
border: solid @theme_selected_bg_color 1px;
@@ -1308,32 +1409,35 @@ popover.popup-menu contents {
/* GradientImage */
#GradientImage {
- min-width : 54px;
+ min-width: 54px;
min-height: 12px;
}
/* GradientWithStops */
#GradientEdit {
- min-width : 60px;
+ min-width: 60px;
/* widget's height; it should take stop template's height into account
* current value is fine-tuned to make stop handles overlap gradient image
* just the right amount */
min-height: 33px;
}
+
/* focus outline, emulates style of GTKʼs Adwaita/Default CSS themeʼs outline */
#GradientEdit {
- border: 1px dashed transparent; /* reserve space but donʼt draw til focus */
+ border: 1px dashed transparent;
+ /* reserve space but donʼt draw til focus */
border-radius: 3px;
padding: 3px;
}
+
#GradientEdit:focus-within {
border-color: alpha(@theme_fg_color, 0.3);
}
/* Canvas */
#InkscapeCanvas {
- min-width : 256px;
+ min-width: 256px;
min-height: 256px;
}
@@ -1346,8 +1450,9 @@ popover.popup-menu contents {
frame.icon-preview {
border-radius: 0;
}
+
button.icon-preview {
- min-width : 0;
+ min-width: 0;
min-height: 0;
padding: 5px;
}
@@ -1358,9 +1463,9 @@ frame.flat {
}
/*we dont want higlight with tab order only want checked ones */
-#ToolToolbar flowboxchild:selected {
- background-color:transparent;
- background-image:image(@theme_bg_color);
+#ToolToolbar flowboxchild:selected {
+ background-color: transparent;
+ background-image: image(@theme_bg_color);
}
/* Adding some margins for popup dialogs, so the content is not touching the window borders */
@@ -1369,86 +1474,107 @@ frame.flat {
}
/* Tabs widget */
-#DocumentTab { padding: 3px; }
+#DocumentTab {
+ padding: 3px;
+}
#DocumentTab:hover {
- background-color:shade(@theme_bg_color, 0.97);
+ background-color: shade(@theme_bg_color, 0.97);
}
#DocumentTab.tab_active {
box-shadow: inset 0 -2px @theme_selected_bg_color;
- background-color:@theme_bg_color;
+ background-color: @theme_bg_color;
}
-#DocumentTabsWidget { box-shadow: none; }
+#DocumentTabsWidget {
+ box-shadow: none;
+}
@keyframes pulse-border {
- 0% {
- box-shadow: inset alpha(@theme_selected_bg_color, 0.4) 0px 0px 2px 1px;
- }
- 50% {
- box-shadow: inset @theme_selected_bg_color 0px 0px 6px 2px;
- }
- 100% {
- box-shadow: inset alpha(@theme_selected_bg_color, 0.4) 0px 0px 2px 1px;
- }
+ 0% {
+ box-shadow: inset alpha(@theme_selected_bg_color, 0.4) 0px 0px 2px 1px;
+ }
+
+ 50% {
+ box-shadow: inset @theme_selected_bg_color 0px 0px 6px 2px;
+ }
+
+ 100% {
+ box-shadow: inset alpha(@theme_selected_bg_color, 0.4) 0px 0px 2px 1px;
+ }
}
-#DocumentTabsWidget.drop-highlight > #Overlay {
- box-shadow: inset @theme_selected_bg_color 0px 0px 5px 1px;
- animation-name: pulse-border;
- animation-duration: 1s;
- animation-timing-function: ease;
- animation-iteration-count: infinite;
+#DocumentTabsWidget.drop-highlight>#Overlay {
+ box-shadow: inset @theme_selected_bg_color 0px 0px 5px 1px;
+ animation-name: pulse-border;
+ animation-duration: 1s;
+ animation-timing-function: ease;
+ animation-iteration-count: infinite;
}
/*helper info in popover menu*/
-.menu_search{
- background-color:alpha(@theme_fg_color,0.1);
- margin:0 0 -8px -8px;
+.menu_search {
+ background-color: alpha(@theme_fg_color, 0.1);
+ margin: 0 0 -8px -8px;
}
/* limit height of list view items */
-columnview.list-view-small > listview > row > cell {
+columnview.list-view-small>listview>row>cell {
padding: 5px;
}
/* gridview items with smaller margins */
-gridview.grid-view-small > child box.item-box {
+gridview.grid-view-small>child box.item-box {
padding: 0;
margin: 8px;
border-spacing: 8px;
}
/* list view with items based on labels need some extra vertical space */
-listview.list-view-small > row > box.item-box {
+listview.list-view-small>row>box.item-box {
margin-top: 3px;
margin-bottom: 3px;
}
-listview.list-view-small > row > box.item-box.separator {
+listview.list-view-small>row>box.item-box.separator {
margin: 1px;
}
/* About screen slide show transitions >>>>>>>>>>>>>>>>>>>>>>>>> */
@keyframes fade_in_opacity {
- 0% { opacity: 0; }
- 100% { opacity: 1; }
+ 0% {
+ opacity: 0;
+ }
+
+ 100% {
+ opacity: 1;
+ }
}
+
@keyframes fade_out_opacity {
- 0% { opacity: 1; }
- 100% { opacity: 0; }
+ 0% {
+ opacity: 1;
+ }
+
+ 100% {
+ opacity: 0;
+ }
}
+
.fade-in {
animation: 1.2s fade_in_opacity 0s both;
}
+
.fade-out {
animation: 1.2s fade_out_opacity 0s both;
}
+
.background-transition {
transition-property: background-color;
transition-duration: 1.2s;
}
+
/* <<<<<<<<<<<<<<<<<<<<<<<< About screen slide show transitions */
/* Grid definition panel/box in document properties dialog */
@@ -1484,6 +1610,7 @@ separator.faint {
#ColorPlate.rectangular {
min-height: 160px;
}
+
#ColorPlate.circular {
min-height: 300px;
}
@@ -1497,17 +1624,18 @@ separator.faint {
/* Simple decorators for resizing handles giving them borders */
#MultipanedHandle.horizontal {
background-image: linear-gradient(to right,
- alpha(@theme_fg_color, 0.25) 0%,
- @theme_bg_color 10%,
- @theme_bg_color 90%,
- alpha(@theme_fg_color, 0.25) 100%);
+ alpha(@theme_fg_color, 0.25) 0%,
+ @theme_bg_color 10%,
+ @theme_bg_color 90%,
+ alpha(@theme_fg_color, 0.25) 100%);
}
+
#MultipanedHandle.vertical {
background-image: linear-gradient(to bottom,
- alpha(@theme_fg_color, 0.25) 0%,
- @theme_bg_color 10%,
- @theme_bg_color 90%,
- alpha(@theme_fg_color, 0.25) 100%);
+ alpha(@theme_fg_color, 0.25) 0%,
+ @theme_bg_color 10%,
+ @theme_bg_color 90%,
+ alpha(@theme_fg_color, 0.25) 100%);
}
/* Adds an exception to StartScreen recent files tab
@@ -1544,31 +1672,69 @@ listview row.top-separator {
min-height: calc(2em + 4px);
padding: 0 4px;
}
+
#SimpleTab {
min-width: 4em;
min-height: calc(2em + 4px);
}
+
#SimpleTab:hover {
box-shadow: inset 0 -3px alpha(@theme_fg_color, 0.15);
}
+
#SimpleTab.tab-active {
background-color: @theme_base_color;
box-shadow: inset 0 -3px @theme_selected_bg_color,
inset -1px 0 alpha(@theme_fg_color, 0.10),
- inset 1px 0 alpha(@theme_fg_color, 0.10);
+ inset 1px 0 alpha(@theme_fg_color, 0.10);
}
+
#SimpleTab.tab-active:hover {
/*border-bottom-color: @theme_selected_bg_color;*/
}
+
#NewTabButton {
margin-left: 3px;
}
+
#DialogMenuButton {
margin-left: 3px;
}
/* Some themes add color decoration for active drop targets; we use our own highlight, so disable them */
-#MultipanedDropZone:drop(active), #MultipanedDropZone:drop(active):focus,
- #DialogMultipaned:drop(active), #DialogMultipaned:drop(active):focus {
+#MultipanedDropZone:drop(active),
+#MultipanedDropZone:drop(active):focus,
+#DialogMultipaned:drop(active),
+#DialogMultipaned:drop(active):focus {
box-shadow: none;
}
+
+/*
+**********************
+* Recolor Art class *
+**********************
+*/
+
+
+#recolor-art #original,
+#recolored {
+ min-height: 6px;
+ border-radius: 4px;
+ border: 2px solid transparent;
+}
+
+#original-recolor-box button#original:hover,
+button#recolored:hover {
+ border-color: @theme_fq_color;
+}
+
+#recolor-art listview row:selected {
+ background-color: transparent;
+ border: 2px solid @theme_selected_bg_color;
+ border-radius: 4px;
+}
+
+#recolor-art {
+ min-width: 400px;
+ min-height: 500px;
+}
\ No newline at end of file
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index df176e03431ccbf30a5b47adb1941b7a8799563c..5d4f2108ceb642401946898a7384cb437703d60c 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -285,10 +285,10 @@ set(ui_SRC
widget/unit-tracker.cpp
widget/widget-vfuncs-class-init.cpp
widget/xml-treeview.cpp
+ widget/recolor-art.cpp
view/svg-view-widget.cpp
-
# -------
# Headers
builder-utils.h
@@ -597,7 +597,8 @@ set(ui_SRC
widget/unit-tracker.h
widget/widget-vfuncs-class-init.h
widget/xml-treeview.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 a3736bae318004ddef8d59b2d620843806c00a30..02de1d41d0c7b72ee93f5e713e0415af08f7e919 100644
--- a/src/ui/dialog/fill-and-stroke.cpp
+++ b/src/ui/dialog/fill-and-stroke.cpp
@@ -23,15 +23,17 @@
#include
#include
-#include "desktop.h"
#include "desktop-style.h"
+#include "desktop.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/notebook-page.h"
+#include "ui/widget/recolor-art.h"
+#include "ui/widget/stroke-style.h"
namespace Inkscape::UI::Dialog {
@@ -40,12 +42,9 @@ 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))
- , _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)
{
@@ -54,7 +53,8 @@ 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_stroke_style,
+ _createPageTabLabel(_("Stroke st_yle"), INKSCAPE_ICON("object-stroke-style")));
_notebook.set_vexpand(true);
_switch_page_conn = _notebook.signal_switch_page().connect(sigc::mem_fun(*this, &FillAndStroke::_onSwitchPage));
@@ -62,7 +62,6 @@ FillAndStroke::FillAndStroke()
_layoutPageFill();
_layoutPageStrokePaint();
_layoutPageStrokeStyle();
-
UI::pack_end(*this, _composite_settings, UI::PackOptions::shrink);
_composite_settings.setSubject(&_subject);
@@ -80,6 +79,7 @@ FillAndStroke::~FillAndStroke()
void FillAndStroke::selectionChanged(Selection *selection)
{
+
if (!page_changed) {
changed_fill = true;
changed_stroke = true;
@@ -94,6 +94,7 @@ void FillAndStroke::selectionChanged(Selection *selection)
if (strokeStyleWdgt && npage == 2) {
strokeStyleWdgt->selectionChangedCB();
}
+
}
void FillAndStroke::selectionModified(Selection *selection, guint flags)
@@ -110,6 +111,7 @@ void FillAndStroke::selectionModified(Selection *selection, guint flags)
if (strokeStyleWdgt && npage == 2) {
strokeStyleWdgt->selectionModifiedCB(flags);
}
+
}
void FillAndStroke::desktopReplaced()
@@ -126,10 +128,11 @@ void FillAndStroke::desktopReplaced()
if (strokeStyleWdgt) {
strokeStyleWdgt->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()) {
@@ -153,65 +156,55 @@ 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);
}
-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::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);
-
}
-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 0a918df2f0af4d1b9ec2a65a397ca69653e66a77..29c3ba92b4eb2e9efb668d6d36628c24be0c37ae 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 {
@@ -32,6 +33,7 @@ namespace Widget {
class FillNStroke;
class NotebookPage;
class StrokeStyle;
+class RecolorArt;
} // namespace Widget
namespace Dialog {
@@ -78,6 +80,7 @@ private:
UI::Widget::FillNStroke *fillWdgt = nullptr;
UI::Widget::FillNStroke *strokeWdgt = nullptr;
UI::Widget::StrokeStyle *strokeStyleWdgt = nullptr;
+
sigc::scoped_connection _switch_page_conn;
};
diff --git a/src/ui/widget/paint-selector.cpp b/src/ui/widget/paint-selector.cpp
index 5ad356bd70b23474f5b7816466c7b594282bde39..d3a34ead5bec22d962946baf5fd5911bc4bce789 100644
--- a/src/ui/widget/paint-selector.cpp
+++ b/src/ui/widget/paint-selector.cpp
@@ -57,6 +57,7 @@
#include "ui/widget/gradient-editor.h"
#include "ui/widget/gradient-selector.h"
#include "ui/widget/pattern-editor.h"
+#include "ui/widget/recolor-art.h"
#include "ui/widget/swatch-selector.h"
#include "widgets/widget-sizes.h"
#include "xml/repr.h"
@@ -135,6 +136,9 @@ GradientSelectorInterface *PaintSelector::getGradientFromData() const
PaintSelector::PaintSelector(FillOrStroke kind, std::shared_ptr colors)
: _selected_colors(std::move(colors))
+ ,recolorArtWdgt(Gtk::make_managed())
+ ,recolorButtonTriger(Gtk::make_managed())
+ , recolorPopOver(Gtk::make_managed())
{
set_orientation(Gtk::Orientation::VERTICAL);
@@ -205,6 +209,16 @@ PaintSelector::PaintSelector(FillOrStroke kind, std::shared_ptrsignal_released.connect(sigc::mem_fun(*this, &PaintSelector::onSelectedColorReleased));
_selected_colors->signal_changed.connect(sigc::mem_fun(*this, &PaintSelector::onSelectedColorChanged));
+ recolorButtonTriger->set_label("Recolor Selection");
+ recolorButtonTriger->set_hexpand(false);
+ recolorButtonTriger->signal_clicked().connect([this]() {
+ recolorPopOver->popup();
+ recolorArtWdgt->performUpdate();
+ });
+ recolorPopOver->set_parent(*recolorButtonTriger);
+ recolorPopOver->set_child(*recolorArtWdgt);
+ recolorPopOver->set_position(Gtk::PositionType::LEFT);
+ _frame->append(*recolorButtonTriger);
// from _new function
setMode(PaintSelector::MODE_MULTIPLE);
diff --git a/src/ui/widget/paint-selector.h b/src/ui/widget/paint-selector.h
index f76eda68f6cfa78a5620674edaf59896fcf29e63..41a0e4a674acef444d661eca5401cfe282610b7b 100644
--- a/src/ui/widget/paint-selector.h
+++ b/src/ui/widget/paint-selector.h
@@ -42,6 +42,7 @@ class SPStyle;
namespace Gtk {
class Label;
class ToggleButton;
+class Popover;
} // namespace Gtk
namespace Inkscape::UI::Widget {
@@ -50,6 +51,7 @@ class FillRuleRadioButton;
class GradientEditor;
class PatternEditor;
class StyleToggleButton;
+class RecolorArt;
/**
* Generic paint selector widget.
@@ -103,6 +105,10 @@ class PaintSelector : public Gtk::Box {
SwatchSelector *_selector_swatch = nullptr;
PatternEditor* _selector_pattern = nullptr;
+ UI::Widget::RecolorArt *recolorArtWdgt = nullptr;
+ Gtk::Button *recolorButtonTriger = nullptr;
+ Gtk::Popover* recolorPopOver=nullptr;
+
Gtk::Label *_label;
GtkWidget *_patternmenu = nullptr;
bool _patternmenu_update = false;
diff --git a/src/ui/widget/recolor-art.cpp b/src/ui/widget/recolor-art.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b66164d0b8751132d9e8d6a181b9f0ba92b639fe
--- /dev/null
+++ b/src/ui/widget/recolor-art.cpp
@@ -0,0 +1,529 @@
+#include "recolor-art.h"
+
+#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 "desktop-style.h"
+#include "desktop.h"
+#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"
+#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"
+
+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();
+ _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);
+
+ 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);
+ _color_factory = Gtk::SignalListItemFactory::create();
+
+ _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();
+
+ original->set_hexpand(true);
+
+ recolored->set_hexpand(true);
+
+ arrow->set_use_markup(true);
+ 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);
+ box->append(*arrow);
+ box->append(*recolored);
+ list_item->set_child(*box);
+ });
+
+ _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;
+
+ 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);
+
+ 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);
+ });
+ buttons[item->key] = {original, recolored};
+ }
+ });
+
+ _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);
+ });
+ _desktop = SP_ACTIVE_DESKTOP;
+ // _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");
+}
+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(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);
+ SPGradient *vectorGradient = gradient->getVector();
+ if (vectorGradient) {
+ 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()) {
+ populateMap(stop.color.value(), item, kind);
+ }
+ }
+ }
+}
+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");
+ 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);
+ 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}, pair));
+ }
+}
+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()) {
+ extractGradientStops(item, "stop", true);
+ }
+
+ if (style->stroke.isColor()) {
+ auto color = style->stroke.getColor();
+ populateMap(color, item, "stroke");
+ }
+ // get gradient stops strokes
+ else if (style->stroke.isPaintserver()) {
+ extractGradientStops(item, "stop", false);
+ }
+}
+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();
+ _color_model->append(ColorItem::create(key, old_color, new_color));
+ }
+ _color_list->append(*_list_view);
+}
+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));
+
+ auto container = _builder->get_widget("color-picker");
+ if (container) {
+ 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)
+{
+ 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;}";
+ 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::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;
+ 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()) {
+ 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);
+ // 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;
+ }
+ 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()) {
+ 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()
+{
+ 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) {
+ 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()
+{
+ 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);
+}
+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()
+{
+ 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;
+ 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);
+ }
+ }
+}
+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");
+}
+void RecolorArt::performUpdate()
+{
+ for (auto child : _color_list->get_children()) {
+ _color_list->remove(*child);
+ }
+ buttons.clear();
+ _gradient_stops.clear();
+ _last_original_button = nullptr;
+ _last_recolored_button = nullptr;
+ // _current_color_id = "";
+ if (_desktop) {
+ if (auto selection = _desktop->getSelection()) {
+ std::vector vec(selection->items().begin(), selection->items().end());
+ collectColors(vec);
+ if (!_selected_colors.empty()) {
+ generateVisualList();
+ auto first_button_id = buttons.begin()->first;
+ onOriginalColorClicked(first_button_id);
+ }
+ }
+ g_message("Performing Update\n");
+ }
+ else
+ g_message("Desktop is NULL in Performupdate in recolor widegt\n");
+}
+} // 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
diff --git a/src/ui/widget/recolor-art.h b/src/ui/widget/recolor-art.h
new file mode 100644
index 0000000000000000000000000000000000000000..0c9e9eda6a34a5815b094a8612ff24b2ea054106
--- /dev/null
+++ b/src/ui/widget/recolor-art.h
@@ -0,0 +1,144 @@
+
+
+#ifndef SEEN_DIALOGS_SP_RECOLOR_ART_H
+#define SEEN_DIALOGS_SP_RECOLOR_ART_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "canvas.h"
+#include "style-internal.h"
+#include "style.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;
+class Builder;
+class ListStore;
+class Notebook;
+} // namespace Gtk
+
+class SPDesktop;
+
+namespace Inkscape {
+namespace UI {
+namespace Tools {
+class ToolBase;
+}
+
+namespace Widget {
+class ColorNotebook;
+
+struct ColorRef
+{
+ SPItem *item;
+ std::string kind;
+};
+
+struct ColorPair
+{
+ Color old_color;
+ Color new_color;
+};
+
+struct ColorItem : public Glib::Object
+{
+ Glib::ustring key;
+ Glib::ustring old_color;
+ Glib::ustring new_color;
+
+ static Glib::RefPtr create(Glib::ustring const &k, Glib::ustring const &old_c,
+ Glib::ustring const &new_c)
+ {
+ auto item = Glib::make_refptr_for_instance(new ColorItem());
+ item->key = k;
+ item->old_color = old_c;
+ item->new_color = new_c;
+ return item;
+ }
+};
+class RecolorArt : public Gtk::Box
+{
+private:
+ SPDesktop *_desktop = nullptr;
+ std::shared_ptr _solid_colors;
+ std::map, std::optional>> _selected_colors;
+ Inkscape::UI::Widget::ColorNotebook *_color_picker_wdgt = nullptr;
+ Gtk::Box *_color_list = 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}
+ 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;
+
+ // 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);
+
+ // signals handelrs
+ void onOriginalColorClicked(std::string color_id);
+ void onResetClicked();
+ void onColorPickerChanged();
+ void onLivePreviewToggled();
+ void lpChecked();
+ void revertToOriginalColors();
+ void convertToRecoloredColors();
+ // void _onApplyButtonClicked();
+
+ void populateStopsMap(SPStop *stop);
+ void recolorStops(std::string old_color, Color new_color);
+
+public:
+ RecolorArt();
+ ~RecolorArt();
+ void performUpdate();
+ bool isInPreviewMode() { return _is_preview; }
+ void setDesktop(SPDesktop *desktop);
+};
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape
+
+#endif // SEEN_DIALOGS_SP_RECOLOR_ART_H