Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
color-item.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
5/* Authors: PBS <pbs3141@gmail.com>
6 * Copyright (C) 2022 PBS
7 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
8 */
9
10#include "color-item.h"
11
12#include <algorithm>
13#include <cassert>
14#include <cstdint>
15#include <utility>
16#include <vector>
17#include <cairomm/context.h>
18#include <cairomm/pattern.h>
19#include <cairomm/surface.h>
20#include <glibmm/bytes.h>
21#include <glibmm/convert.h>
22#include <glibmm/i18n.h>
23#include <giomm/menu.h>
24#include <giomm/menuitem.h>
25#include <giomm/simpleaction.h>
26#include <giomm/simpleactiongroup.h>
27#include <gdkmm/contentprovider.h>
28#include <gdkmm/general.h>
29#include <gdkmm/pixbuf.h>
30#include <gdkmm/texture.h>
31#include <gtkmm/binlayout.h>
32#include <gtkmm/dragsource.h>
33#include <gtkmm/eventcontrollermotion.h>
34#include <gtkmm/gestureclick.h>
35#include <gtkmm/popover.h>
36#include <gtkmm/popovermenu.h>
37#include <sigc++/functors/mem_fun.h>
38
39#include "colors/dragndrop.h"
40#include "desktop-style.h"
41#include "document.h"
42#include "document-undo.h"
43#include "message-context.h"
44#include "preferences.h"
45#include "selection.h"
47#include "display/cairo-utils.h"
48#include "io/resource.h"
49#include "object/sp-gradient.h"
50#include "object/tags.h"
51#include "ui/containerize.h"
52#include "ui/controller.h"
55#include "ui/icon-names.h"
56#include "ui/util.h"
57#include "util/value-utils.h"
59
60namespace Inkscape::UI::Dialog {
61namespace {
62
64Glib::RefPtr<Gdk::Pixbuf> get_removecolor()
65{
66 // Load the pixbuf only once
67 static const auto remove_color = [] {
68 auto path = IO::Resource::get_path(IO::Resource::SYSTEM, IO::Resource::UIS, "resources", "remove-color.png");
69 auto pixbuf = Gdk::Pixbuf::create_from_file(path.pointer());
70 if (!pixbuf) {
71 std::cerr << "Null pixbuf for " << Glib::filename_to_utf8(path.pointer()) << std::endl;
72 }
73 return pixbuf;
74 }();
75 return remove_color;
76}
77
78} // namespace
79
81 : dialog(dialog)
82{
83 data = PaintNone();
84 pinned_default = true;
85 add_css_class("paint-none");
86 description = C_("Paint", "None");
87 color_id = "none";
89}
90
92 : dialog(dialog)
93{
94 description = color.getName();
95 color_id = color_to_id(color);
96 data = std::move(color);
98}
99
101 : dialog(dialog)
102{
103 data = GradientData{gradient};
104 description = gradient->defaultLabel();
105 color_id = gradient->getId();
106
107 gradient->connectRelease(sigc::track_object([this] (SPObject*) {
108 std::get<GradientData>(data).gradient = nullptr;
109 }, *this));
110
111 gradient->connectModified(sigc::track_object([this] (SPObject *obj, unsigned flags) {
112 if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
113 cache_dirty = true;
114 queue_draw();
115 }
116 description = obj->defaultLabel();
117 _signal_modified.emit();
118 if (is_pinned() != was_grad_pinned) {
120 _signal_pinned.emit();
121 }
122 }, *this));
123
125 common_setup();
126}
127
129 : description(std::move(name))
130{
131 bool group = !description.empty();
132 set_name("ColorItem");
133 set_tooltip_text(description);
134 color_id = "-";
135 add_css_class(group ? "group" : "filler");
136}
137
138ColorItem::~ColorItem() = default;
139
141 return !dialog && color_id == "-" && !description.empty();
142}
143
145 return !dialog && color_id == "-" && description.empty();
146}
147
149{
150 containerize(*this);
151 set_layout_manager(Gtk::BinLayout::create());
152 set_name("ColorItem");
153 set_tooltip_text(description + (tooltip.empty() ? tooltip : "\n" + tooltip));
154
155 set_draw_func(sigc::mem_fun(*this, &ColorItem::draw_func));
156
157 auto const drag = Gtk::DragSource::create();
158 drag->set_button(1); // left
159 drag->set_actions(Gdk::DragAction::MOVE | Gdk::DragAction::COPY);
160 drag->signal_prepare().connect([this](auto &&...) { return on_drag_prepare(); }, false); // before
161 drag->signal_drag_begin().connect([this, &drag = *drag](auto &&...) { on_drag_begin(drag); });
162 add_controller(drag);
163
164 auto const motion = Gtk::EventControllerMotion::create();
165 motion->set_propagation_phase(Gtk::PropagationPhase::TARGET);
166 motion->signal_enter().connect([this](auto &&...) { on_motion_enter(); });
167 motion->signal_leave().connect([this](auto &&...) { on_motion_leave(); });
168 add_controller(motion);
169
170 auto const click = Gtk::GestureClick::create();
171 click->set_button(0); // any
172 click->signal_pressed().connect(Controller::use_state([this](auto& controller, auto &&...) { return on_click_pressed(controller); }, *click));
173 click->signal_released().connect(Controller::use_state([this](auto& controller, auto &&...) { return on_click_released(controller); }, *click));
174 add_controller(click);
175}
176
177void ColorItem::set_pinned_pref(const std::string &path)
178{
179 pinned_pref = path + "/pinned/" + color_id;
180}
181
182void ColorItem::draw_color(Cairo::RefPtr<Cairo::Context> const &cr, int w, int h) const
183{
184 std::visit(VariantVisitor{
185 [&] (Undefined) {
186 // there's no color to paint; indicate clearly that there is nothing to select:
187 auto y = h / 2 + 0.5;
188 auto width = w / 4;
189 auto x = (w - width) / 2 - 0.5;
190 cr->move_to(x, y);
191 cr->line_to(x + width, y);
192 auto const fg = get_color();
193 cr->set_source_rgba(fg.get_red(), fg.get_green(), fg.get_blue(), 0.5);
194 cr->set_line_width(1);
195 cr->stroke();
196 },
197 [&] (PaintNone) {
198 if (auto const pixbuf = get_removecolor()) {
199 const auto device_scale = get_scale_factor();
200 cr->save();
201 cr->scale((double)w / pixbuf->get_width() / device_scale, (double)h / pixbuf->get_height() / device_scale);
202 Gdk::Cairo::set_source_pixbuf(cr, pixbuf, 0, 0);
203 cr->paint();
204 cr->restore();
205 }
206 },
207 [&] (Colors::Color const &color) {
209 cr->paint();
210 // there's no way to query background color to check if color item stands out,
211 // so we apply faint outline to let users make out color shapes blending with background
212 auto const fg = get_color();
213 cr->rectangle(0.5, 0.5, w - 1, h - 1);
214 cr->set_source_rgba(fg.get_red(), fg.get_green(), fg.get_blue(), 0.07);
215 cr->set_line_width(1);
216 cr->stroke();
217 },
218 [&] (GradientData graddata) {
219 // Gradient pointer may be null if the gradient was destroyed.
220 auto grad = graddata.gradient;
221 if (!grad) return;
222
223 auto pat_checkerboard = Cairo::RefPtr<Cairo::Pattern>(new Cairo::Pattern(ink_cairo_pattern_create_checkerboard(), true));
224 auto pat_gradient = Cairo::RefPtr<Cairo::Pattern>(new Cairo::Pattern(grad->create_preview_pattern(w), true));
225
226 cr->set_source(pat_checkerboard);
227 cr->paint();
228 cr->set_source(pat_gradient);
229 cr->paint();
230 }}, data);
231}
232
233void ColorItem::draw_func(Cairo::RefPtr<Cairo::Context> const &cr, int const w, int const h)
234{
235 // Only using caching for none and gradients. None is included because the image is huge.
236 bool const use_cache = std::holds_alternative<PaintNone>(data) || std::holds_alternative<GradientData>(data);
237
238 if (use_cache) {
239 auto scale = get_scale_factor();
240 // Ensure cache exists and has correct size.
241 if (!cache || cache->get_width() != w * scale || cache->get_height() != h * scale) {
242 cache = Cairo::ImageSurface::create(Cairo::Surface::Format::ARGB32, w * scale, h * scale);
243 cairo_surface_set_device_scale(cache->cobj(), scale, scale);
244 cache_dirty = true;
245 }
246 // Ensure cache contents is up-to-date.
247 if (cache_dirty) {
248 draw_color(Cairo::Context::create(cache), w * scale, h * scale);
249 cache_dirty = false;
250 }
251 // Paint from cache.
252 cr->set_source(cache, 0, 0);
253 cr->paint();
254 } else {
255 // Paint directly.
256 draw_color(cr, w, h);
257 }
258
259 // Draw fill/stroke indicators.
260 if (is_fill || is_stroke) {
262 auto [gray, alpha] = Colors::get_contrasting_color(lightness);
263 cr->set_source_rgba(gray, gray, gray, alpha);
264
265 // Scale so that the square -1...1 is the biggest possible square centred in the widget.
266 auto minwh = std::min(w, h);
267 cr->translate((w - minwh) / 2.0, (h - minwh) / 2.0);
268 cr->scale(minwh / 2.0, minwh / 2.0);
269 cr->translate(1.0, 1.0);
270
271 if (is_fill) {
272 cr->arc(0.0, 0.0, 0.35, 0.0, 2 * M_PI);
273 cr->fill();
274 }
275
276 if (is_stroke) {
277 cr->set_fill_rule(Cairo::Context::FillRule::EVEN_ODD);
278 cr->arc(0.0, 0.0, 0.65, 0.0, 2 * M_PI);
279 cr->arc(0.0, 0.0, 0.5, 0.0, 2 * M_PI);
280 cr->fill();
281 }
282 }
283}
284
285void ColorItem::size_allocate_vfunc(int width, int height, int baseline)
286{
287 Gtk::DrawingArea::size_allocate_vfunc(width, height, baseline);
288
289 cache_dirty = true;
290}
291
293{
294 assert(dialog);
295
296 mouse_inside = true;
297 if (auto desktop = dialog->getDesktop()) {
298 auto msg = Glib::ustring::compose(_("Color: <b>%1</b>; <b>Click</b> to set fill, <b>Shift+click</b> to set stroke"), description);
300 }
301}
302
304{
305 assert(dialog);
306
307 mouse_inside = false;
308 if (auto desktop = dialog->getDesktop()) {
310 }
311}
312
313Gtk::EventSequenceState ColorItem::on_click_pressed(Gtk::GestureClick const &click)
314{
315 assert(dialog);
316
317 if (click.get_current_button() == 3) {
319 return Gtk::EventSequenceState::CLAIMED;
320 }
321 // Return true necessary to avoid stealing the canvas focus.
322 return Gtk::EventSequenceState::CLAIMED;
323}
324
325Gtk::EventSequenceState ColorItem::on_click_released(Gtk::GestureClick const &click)
326{
327 assert(dialog);
328
329 auto const button = click.get_current_button();
330 if (mouse_inside && (button == 1 || button == 2)) {
331 auto const state = click.get_current_event_state();
332 auto const stroke = button == 2 || Controller::has_flag(state, Gdk::ModifierType::SHIFT_MASK);
334 return Gtk::EventSequenceState::CLAIMED;
335 }
336 return Gtk::EventSequenceState::NONE;
337}
338
340{
341 assert(dialog);
342
343 auto desktop = dialog->getDesktop();
344 if (!desktop) return;
345
346 auto attr_name = stroke ? "stroke" : "fill";
347 auto css = std::unique_ptr<SPCSSAttr, void(*)(SPCSSAttr*)>(sp_repr_css_attr_new(), [] (auto p) {sp_repr_css_attr_unref(p);});
348
349 Glib::ustring descr;
350 if (is_paint_none()) {
351 sp_repr_css_set_property(css.get(), attr_name, "none");
352 descr = stroke ? _("Set stroke color to none") : _("Set fill color to none");
353 } else if (auto const color = std::get_if<Colors::Color>(&data)) {
354 sp_repr_css_set_property_string(css.get(), attr_name, color->toString());
355 descr = stroke ? _("Set stroke color from swatch") : _("Set fill color from swatch");
356 } else if (auto const graddata = std::get_if<GradientData>(&data)) {
357 auto grad = graddata->gradient;
358 if (!grad) return;
359 auto colorspec = "url(#" + Glib::ustring(grad->getId()) + ")";
360 sp_repr_css_set_property(css.get(), attr_name, colorspec.c_str());
361 descr = stroke ? _("Set stroke color from swatch") : _("Set fill color from swatch");
362 }
363
365
366 DocumentUndo::done(desktop->getDocument(), descr.c_str(), INKSCAPE_ICON("swatches"));
367}
368
370{
371 // Only re/insert actions on click, not in ctor, to avoid performance hit on rebuilding palette
372 auto const main_actions = Gio::SimpleActionGroup::create();
373 main_actions->add_action("set-fill" , sigc::mem_fun(*this, &ColorItem::action_set_fill ));
374 main_actions->add_action("set-stroke", sigc::mem_fun(*this, &ColorItem::action_set_stroke));
375 main_actions->add_action("delete" , sigc::mem_fun(*this, &ColorItem::action_delete ));
376 main_actions->add_action("edit" , sigc::mem_fun(*this, &ColorItem::action_edit ));
377 main_actions->add_action("toggle-pin", sigc::mem_fun(*this, &ColorItem::action_toggle_pin));
378 insert_action_group("color-item", main_actions);
379
380 auto const menu = Gio::Menu::create();
381
382 // TRANSLATORS: An item in context menu on a colour in the swatches
383 menu->append(_("Set Fill" ), "color-item.set-fill" );
384 menu->append(_("Set Stroke"), "color-item.set-stroke");
385
386 auto section = menu;
387
388 if (auto const graddata = std::get_if<GradientData>(&data)) {
389 section = Gio::Menu::create();
390 menu->append_section(section);
391 section->append(_("Delete" ), "color-item.delete");
392 section->append(_("Edit..."), "color-item.edit" );
393 section = Gio::Menu::create();
394 menu->append_section(section);
395 }
396
397 section->append(is_pinned() ? _("Unpin Color") : _("Pin Color"), "color-item.toggle-pin");
398
399 // If document has gradients, add Convert section w/ actions to convert them to swatches.
400 auto grad_names = std::vector<Glib::ustring>{};
401 for (auto const obj : dialog->getDesktop()->getDocument()->getResourceList("gradient")) {
402 auto const grad = static_cast<SPGradient *>(obj);
403 if (grad->hasStops() && !grad->isSwatch()) {
404 grad_names.emplace_back(grad->getId());
405 }
406 }
407 if (!grad_names.empty()) {
408 auto const convert_actions = Gio::SimpleActionGroup::create();
409 auto const convert_submenu = Gio::Menu::create();
410
411 std::sort(grad_names.begin(), grad_names.end());
412 for (auto const &name: grad_names) {
413 convert_actions->add_action(name, sigc::bind(sigc::mem_fun(*this, &ColorItem::action_convert), name));
414 convert_submenu->append(name, "color-item-convert." + name);
415 }
416
417 insert_action_group("color-item-convert", convert_actions);
418
419 section = Gio::Menu::create();
420 section->append_submenu(_("Convert"), convert_submenu);
421 menu->append_section(section);
422 }
423
424
425 if (_popover) {
426 _popover->unparent();
427 }
428
429 _popover = std::make_unique<Gtk::PopoverMenu>(menu, Gtk::PopoverMenu::Flags::NESTED);
430 _popover->set_parent(*this);
431
432 _popover->popup();
433}
434
436{
437 on_click(false);
438}
439
441{
442 on_click(true);
443}
444
446{
447 auto const grad = std::get<GradientData>(data).gradient;
448 if (!grad) return;
449
450 grad->setSwatch(false);
451 DocumentUndo::done(grad->document, _("Delete swatch"), INKSCAPE_ICON("color-gradient"));
452}
453
455{
456 auto const grad = std::get<GradientData>(data).gradient;
457 if (!grad) return;
458
459 auto desktop = dialog->getDesktop();
460 auto selection = desktop->getSelection();
461 auto items = std::vector<SPItem*>(selection->items().begin(), selection->items().end());
462
463 if (!items.empty()) {
464 auto query = SPStyle(desktop->doc());
465 int result = objects_query_fillstroke(items, &query, true);
467 if (query.fill.isPaintserver()) {
468 if (cast<SPGradient>(query.getFillPaintServer()) == grad) {
469 desktop->getContainer()->new_dialog("FillStroke");
470 return;
471 }
472 }
473 }
474 }
475
476 // Otherwise, invoke the gradient tool.
477 set_active_tool(desktop, "Gradient");
478}
479
481{
482 if (auto const graddata = std::get_if<GradientData>(&data)) {
483 auto const grad = graddata->gradient;
484 if (!grad) return;
485
486 grad->setPinned(!is_pinned());
487 DocumentUndo::done(grad->document, is_pinned() ? _("Pin swatch") : _("Unpin swatch"), INKSCAPE_ICON("color-gradient"));
488 } else {
490 }
491}
492
493void ColorItem::action_convert(Glib::ustring const &name)
494{
495 // This will not be needed until next menu
496 remove_action_group("color-item-convert");
497
498 auto const doc = dialog->getDesktop()->getDocument();
499 auto const resources = doc->getResourceList("gradient");
500 auto const it = std::find_if(resources.cbegin(), resources.cend(),
501 [&](auto &_){ return _->getId() == name; });
502 if (it == resources.cend()) return;
503
504 auto const grad = static_cast<SPGradient *>(*it);
505 grad->setSwatch();
506 DocumentUndo::done(doc, _("Add gradient stop"), INKSCAPE_ICON("color-gradient"));
507}
508
509Glib::RefPtr<Gdk::ContentProvider> ColorItem::on_drag_prepare()
510{
511 if (!dialog) return {};
512
513 Colors::Paint paint;
514 if (!is_paint_none()) {
515 paint = getColor();
516 }
517
518 return Gdk::ContentProvider::create(Util::GlibValue::create<Colors::Paint>(std::move(paint)));
519}
520
521void ColorItem::on_drag_begin(Gtk::DragSource &source)
522{
523 constexpr int w = 32;
524 constexpr int h = 24;
525
526 auto surface = Cairo::ImageSurface::create(Cairo::Surface::Format::ARGB32, w, h);
527 draw_color(Cairo::Context::create(surface), w, h);
528 auto const pixbuf = Gdk::Pixbuf::create(surface, 0, 0, w, h);
529 auto const texture = Gdk::Texture::create_for_pixbuf(pixbuf);
530 source.set_icon(texture, 0, 0);
531}
532
534{
535 is_fill = b;
536 queue_draw();
537}
538
540{
541 is_stroke = b;
542 queue_draw();
543}
544
546{
547 if (auto const graddata = std::get_if<GradientData>(&data)) {
548 auto const grad = graddata->gradient;
549 return grad && grad->isPinned();
550 } else {
552 }
553}
554
560{
561 return std::visit(VariantVisitor{
562 [] (Undefined) {
563 assert(false);
564 return Colors::Color{0xffffffff};
565 },
566 [] (PaintNone) {
567 return Colors::Color(0xffffffff);
568 },
569 [] (Colors::Color const &color) {
570 return color;
571 },
572 [] (GradientData graddata) {
573 auto grad = graddata.gradient;
574 assert(grad);
575 auto pat = Cairo::RefPtr<Cairo::Pattern>(new Cairo::Pattern(grad->create_preview_pattern(1), true));
576 auto img = Cairo::ImageSurface::create(Cairo::Surface::Format::ARGB32, 1, 1);
577 auto cr = Cairo::Context::create(img);
578 cr->set_source(pat);
579 cr->paint();
580 auto color = ink_cairo_surface_average_color(img->cobj());
581 color.setName(grad->getId());
582 return color;
583 }}, data);
584}
585
587 return std::holds_alternative<PaintNone>(data);
588}
589
590
591} // namespace Inkscape::UI::Dialog
592
593/*
594 Local Variables:
595 mode:c++
596 c-file-style:"stroustrup"
597 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
598 indent-tabs-mode:nil
599 fill-column:99
600 End:
601*/
602// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
double scale
Definition aa.cpp:228
void set_active_tool(InkscapeWindow *win, Glib::ustring const &tool)
void ink_cairo_set_source_color(Cairo::RefPtr< Cairo::Context > ctx, Inkscape::Colors::Color const &color, double opacity)
The following functions interact between Inkscape color model, and cairo surface rendering.
Colors::Color ink_cairo_surface_average_color(cairo_surface_t *surface, cairo_surface_t *mask)
Get the average color from the given surface.
cairo_pattern_t * ink_cairo_pattern_create_checkerboard(guint32 rgba, bool use_alpha)
Cairo integration helpers.
Cairo::RefPtr< Cairo::ImageSurface > surface
Definition canvas.cpp:137
std::string getName() const
Definition color.h:78
static void done(SPDocument *document, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
void set(MessageType type, char const *message)
pushes a message on the stack, replacing our old message
void clear()
removes our current message from the stack
bool getBool(Glib::ustring const &pref_path, bool def=false)
Retrieve a Boolean value.
static Preferences * get()
Access the singleton Preferences object.
void setBool(Glib::ustring const &pref_path, bool value)
Set a Boolean value.
bool is_pinned() const
Update whether this item is pinned.
Cairo::RefPtr< Cairo::ImageSurface > cache
Definition color-item.h:149
Gtk::EventSequenceState on_click_pressed(Gtk::GestureClick const &click)
sigc::signal< void()> _signal_modified
Definition color-item.h:157
void draw_color(Cairo::RefPtr< Cairo::Context > const &cr, int w, int h) const
Glib::RefPtr< Gdk::ContentProvider > on_drag_prepare()
void set_fill(bool)
Update the fill indicator, showing this widget is the fill of the current selection.
std::variant< Undefined, PaintNone, Colors::Color, GradientData > data
Definition color-item.h:139
void on_drag_begin(Gtk::DragSource &source)
void draw_func(Cairo::RefPtr< Cairo::Context > const &, int width, int height)
void set_stroke(bool)
Update the stroke indicator, showing this widget is the stroke of the current selection.
void size_allocate_vfunc(int width, int height, int baseline) override
Glib::ustring pinned_pref
The pinned preference path.
Definition color-item.h:132
sigc::signal< void()> _signal_pinned
Definition color-item.h:158
Gtk::EventSequenceState on_click_released(Gtk::GestureClick const &click)
void action_convert(Glib::ustring const &name)
std::unique_ptr< Gtk::Popover > _popover
Definition color-item.h:160
void set_pinned_pref(const std::string &path)
Colors::Color getColor() const
Return the average color for this color item.
DialogBase is the base class for the dialog system.
Definition dialog-base.h:42
SPDesktop * getDesktop() const
Definition dialog-base.h:79
void new_dialog(const Glib::ustring &dialog_type)
Add new dialog to the current container or in a floating window, based on preferences.
SPDocument * getDocument() const
Definition desktop.h:189
Inkscape::MessageContext * tipsMessageContext() const
Definition desktop.h:161
Inkscape::UI::Dialog::DialogContainer * getContainer()
Definition desktop.cpp:335
Inkscape::Selection * getSelection() const
Definition desktop.h:188
SPDocument * doc() const
Definition desktop.h:159
std::vector< SPObject * > const getResourceList(char const *key)
Gradient.
Definition sp-gradient.h:86
void setSwatch(bool swatch=true)
SPObject is an abstract base class of all of the document nodes at the SVG document level.
Definition sp-object.h:160
char const * getId() const
Returns the objects current ID string.
sigc::connection connectRelease(sigc::slot< void(SPObject *)> slot)
Connects to the release request signal.
Definition sp-object.h:237
char const * defaultLabel() const
Returns a default label property for this object.
sigc::connection connectModified(sigc::slot< void(SPObject *, unsigned int)> slot)
Connects to the modification notification signal.
Definition sp-object.h:705
An SVG style object.
Definition style.h:45
Color item used in palettes and swatches UI.
const double w
Definition conic-4.cpp:19
Utilities to more easily use Gtk::EventController & subclasses like Gesture.
std::shared_ptr< Css const > css
Css & result
Glib::ustring msg
Colors::Color stroke
Glib::RefPtr< Gdk::Texture > texture
void sp_desktop_set_style(SPDesktop *desktop, SPCSSAttr *css, bool change, bool write_current, bool switch_style)
Apply style on selection on desktop.
int objects_query_fillstroke(const std::vector< SPItem * > &objects, SPStyle *style_res, bool const isfill)
Write to style_res the average fill or stroke of list of objects, if applicable.
@ QUERY_STYLE_SINGLE
@ QUERY_STYLE_MULTIPLE_SAME
A base class for all dialogs.
A widget that manages DialogNotebook's and other widgets inside a horizontal DialogMultipaned.
TODO: insert short description here.
Macro for icon names used in Inkscape.
Interface for locally managing a current status message.
std::variant< NoColor, Color > Paint
Definition xml-color.h:32
std::pair< double, double > get_contrasting_color(double l)
Definition utils.cpp:179
double get_perceptual_lightness(Color const &color)
Return a value for how the light the color appears to be using HSLUV.
Definition utils.cpp:174
double lightness(Color color)
std::string color_to_id(std::optional< Color > const &color)
Create a somewhat unique id for the given color used for palette identification.
Definition utils.cpp:81
Util::ptr_shared get_path(Domain domain, Type type, char const *filename, char const *extra)
Definition resource.cpp:137
auto use_state(Slot &&slot)
Definition controller.h:43
bool has_flag(Gdk::ModifierType const state, Gdk::ModifierType const flags)
Helper to query if ModifierType state contains one or more of given flag(s).
Definition controller.h:25
Dialog code.
Definition desktop.h:117
static constexpr int height
void containerize(Gtk::Widget &widget)
Make a custom widget implement sensible memory management for its children.
@ INFORMATION_MESSAGE
Definition message.h:30
STL namespace.
Singleton class to access the preferences file in a convenient way.
SPCSSAttr * sp_repr_css_attr_new()
Creates an empty SPCSSAttr (a class for manipulating CSS style properties).
Definition repr-css.cpp:67
void sp_repr_css_attr_unref(SPCSSAttr *css)
Unreferences an SPCSSAttr (will be garbage collected if no references remain).
Definition repr-css.cpp:76
void sp_repr_css_set_property_string(SPCSSAttr *css, char const *name, std::string const &value)
Set a style property to a standard string.
Definition repr-css.cpp:235
void sp_repr_css_set_property(SPCSSAttr *css, gchar const *name, gchar const *value)
Set a style property to a new value (e.g.
Definition repr-css.cpp:191
Inkscape::IO::Resource - simple resource API.
GList * items
SPDesktop * desktop
double width
Glib::ustring name
Definition toolbars.cpp:55
Wrapper for the GLib value API.