Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
color-palette.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
5/* Authors:
6 * Michael Kowalski
7 *
8 * Copyright (C) 2021 Michael Kowalski
9 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
10 */
11
12#include <gtkmm/enums.h>
13#include <utility>
14#include <glibmm/i18n.h>
15#include <glibmm/main.h>
16#include <glibmm/ustring.h>
17#include <gdkmm/frameclock.h>
18#include <gtkmm/adjustment.h>
19#include <gtkmm/builder.h>
20#include <gtkmm/button.h>
21#include <gtkmm/flowbox.h>
22#include <gtkmm/flowboxchild.h>
23#include <gtkmm/label.h>
24#include <gtkmm/menubutton.h>
25#include <gtkmm/popover.h>
26#include <gtkmm/checkbutton.h>
27#include <gtkmm/scale.h>
28#include <gtkmm/scrolledwindow.h>
29#include <gtkmm/scrollbar.h>
30#include <gtkmm/scrolledwindow.h>
31#include <gtkmm/separator.h>
32#include <sigc++/functors/mem_fun.h>
33
34#include "color-palette.h"
35#include "ui/builder-utils.h"
37#include "ui/util.h"
41
42namespace Inkscape::UI::Widget {
43
44[[nodiscard]] static auto make_menu()
45{
46 auto const separator = Gtk::make_managed<Gtk::Separator>(Gtk::Orientation::HORIZONTAL);
47 separator->set_margin_top (5);
48 separator->set_margin_bottom(5);
49
50 auto const config = Gtk::make_managed<PopoverMenuItem>(_("Configure..."), true);
51
52 auto menu = std::make_unique<PopoverMenu>(Gtk::PositionType::TOP);
53 menu->add_css_class("ColorPalette");
54 menu->append(*separator);
55 menu->append(*config);
56
57 return std::make_pair(std::move(menu), std::ref(*config));
58}
59
61 _builder(create_builder("color-palette.glade")),
62 _normal_box(get_widget<Gtk::FlowBox>(_builder, "flow-box")),
63 _pinned_box(get_widget<Gtk::FlowBox>(_builder, "pinned")),
64 _scroll_btn(get_widget<Gtk::FlowBox>(_builder, "scroll-buttons")),
65 _scroll_left(get_widget<Gtk::Button>(_builder, "btn-left")),
66 _scroll_right(get_widget<Gtk::Button>(_builder, "btn-right")),
67 _scroll_up(get_widget<Gtk::Button>(_builder, "btn-up")),
68 _scroll_down(get_widget<Gtk::Button>(_builder, "btn-down")),
69 _scroll(get_widget<Gtk::ScrolledWindow>(_builder, "scroll-wnd"))
70{
71 get_widget<Gtk::CheckButton>(_builder, "show-labels").set_visible(false);
72 _normal_box.set_filter_func([](Gtk::FlowBoxChild*){ return true; });
73
74 auto& box = get_widget<Gtk::Box>(_builder, "palette-box");
75 set_child(box);
76
77 auto [menu, config] = make_menu();
78 _menu = std::move(menu);
79 auto& btn_menu = get_widget<Gtk::MenuButton>(_builder, "btn-menu");
80 btn_menu.set_popover(*_menu);
81 _menu->set_position(Gtk::PositionType::TOP);
82 auto& dlg = get_settings_popover();
83 config.signal_activate().connect([&, this] {
84 dlg.popup();
85 });
86
87 auto& size = get_widget<Gtk::Scale>(_builder, "size-slider");
88 size.signal_change_value().connect([&size, this](Gtk::ScrollType, double val) {
89 _set_tile_size(static_cast<int>(size.get_value()));
91 return true;
92 }, true);
93
94 auto& aspect = get_widget<Gtk::Scale>(_builder, "aspect-slider");
95 aspect.signal_change_value().connect([&aspect, this](Gtk::ScrollType, double val) {
96 _set_aspect(aspect.get_value());
98 return true;
99 }, true);
100
101 auto& border = get_widget<Gtk::Scale>(_builder, "border-slider");
102 border.signal_change_value().connect([&border, this](Gtk::ScrollType, double val) {
103 _set_tile_border(static_cast<int>(border.get_value()));
105 return true;
106 }, true);
107
108 auto& rows = get_widget<Gtk::Scale>(_builder, "row-slider");
109 rows.signal_change_value().connect([&rows, this](Gtk::ScrollType, double val) {
110 _set_rows(static_cast<int>(rows.get_value()));
112 return true;
113 }, true);
114
115 auto& sb = get_widget<Gtk::CheckButton>(_builder, "use-sb");
116 sb.set_active(_force_scrollbar);
117 sb.signal_toggled().connect([&sb, this](){
118 _enable_scrollbar(sb.get_active());
120 });
121
122 auto& stretch = get_widget<Gtk::CheckButton>(_builder, "stretch");
123 stretch.set_active(_force_scrollbar);
124 stretch.signal_toggled().connect([&stretch, this](){
125 _enable_stretch(stretch.get_active());
127 });
129
130 auto& large = get_widget<Gtk::CheckButton>(_builder, "enlarge");
131 large.set_active(_large_pinned_panel);
132 large.signal_toggled().connect([&large, this](){
133 _set_large_pinned_panel(large.get_active());
135 });
137
138 auto& sl = get_widget<Gtk::CheckButton>(_builder, "show-labels");
139 sl.set_visible(false);
140 sl.set_active(_show_labels);
141 sl.signal_toggled().connect([&sl, this](){
142 _show_labels = sl.get_active();
145 });
146
147 _scroll.set_min_content_height(1);
148
149 _scroll_down.signal_clicked().connect([this](){ scroll(0, get_palette_height(), get_tile_height() + _border, true); });
150 _scroll_up.signal_clicked().connect([this](){ scroll(0, -get_palette_height(), get_tile_height() + _border, true); });
151 _scroll_left.signal_clicked().connect([this](){ scroll(-10 * (get_tile_width() + _border), 0, 0.0, false); });
152 _scroll_right.signal_clicked().connect([this](){ scroll(10 * (get_tile_width() + _border), 0, 0.0, false); });
153
154 set_vexpand_set(true);
156
157 connectAfterResize([this] (int w, int h, int) {
158 auto const a = Geom::IntPoint{w, h};
159 if (_allocation == a) return;
160 _allocation = a;
162 });
163
164 if (auto vert_scrollbar = _scroll.get_vscrollbar()) {
165 vert_scrollbar->get_adjustment()->signal_value_changed().connect([this] {
167 });
168 }
169}
170
172
174 return get_widget<Gtk::Popover>(_builder, "config-popup");
175}
176
178 auto& btn_menu = get_widget<Gtk::MenuButton>(_builder, "btn-menu");
179 btn_menu.set_visible(show);
180}
181
182void ColorPalette::do_scroll(int dx, int dy) {
183 if (auto vert = _scroll.get_vscrollbar()) {
184 vert->get_adjustment()->set_value(vert->get_adjustment()->get_value() + dy);
185 }
186 if (auto horz = _scroll.get_hscrollbar()) {
187 horz->get_adjustment()->set_value(horz->get_adjustment()->get_value() + dx);
188 }
189}
190
191static Geom::Interval get_range(Gtk::Scrollbar const &sb) {
192 auto adj = sb.get_adjustment();
193 return {adj->get_lower(), adj->get_upper() - adj->get_page_size()};
194}
195
197 if (auto vert = _scroll.get_vscrollbar()) {
198 double value = vert->get_adjustment()->get_value();
199 auto [min_value, max_value] = get_range(*vert);
200
201 bool at_top = value <= min_value;
202 bool at_bottom = value >= max_value;
203
204 _scroll_up.set_sensitive(!at_top);
205 _scroll_down.set_sensitive(!at_bottom);
206 }
207}
208
209// Update scrolling animation when up/down arrows are clicked.
210bool ColorPalette::scroll_cb(Glib::RefPtr<Gdk::FrameClock> const &clock)
211{
212 // Get or estimate elapsed time since last animation update.
213 auto const timings = clock->get_current_timings();
214 auto const t = timings->get_frame_time();
217 return true;
218 }
219 double const dt = t - *_scroll_cb_last_time;
221
222 bool fire_again = false;
223
224 if (auto vert = _scroll.get_vscrollbar()) {
225 // Ensure target remains within range.
227
228 // Compute the amount to step by.
229 constexpr double SCROLL_SPEED = 4.0; // pixels per 1/60 sec
230 double const step = SCROLL_SPEED * dt * 6e-5;
231
232 auto value = vert->get_adjustment()->get_value();
233 // is this the final adjustment step?
234 if (std::abs(_scroll_final - value) <= step) {
235 vert->get_adjustment()->set_value(_scroll_final);
236 fire_again = false; // cancel timer
237 } else {
238 auto pos = value + step * Geom::sgn(_scroll_final - value);
239 vert->get_adjustment()->set_value(pos);
240 fire_again = true; // fire this callback again
241 }
242 }
243
244 if (!fire_again) {
245 _active_timeout = 0;
246 }
247
248 return fire_again;
249}
250
251void ColorPalette::scroll(int dx, int dy, double snap, bool smooth) {
252 if (auto vert = _scroll.get_vscrollbar()) {
253 if (smooth && dy != 0.0) {
254 _scroll_final = vert->get_adjustment()->get_value() + dy;
255 if (snap > 0) {
256 // round it to whole 'dy' increments
257 _scroll_final -= fmod(_scroll_final, snap);
258 }
260 if (!_active_timeout && vert->get_adjustment()->get_value() != _scroll_final) {
261 _active_timeout = add_tick_callback(sigc::mem_fun(*this, &ColorPalette::scroll_cb));
263 }
264 }
265 else {
266 vert->get_adjustment()->set_value(vert->get_adjustment()->get_value() + dy);
267 }
268 }
269 if (auto horz = _scroll.get_hscrollbar()) {
270 horz->get_adjustment()->set_value(horz->get_adjustment()->get_value() + dx);
271 }
272}
273
275 return _size;
276}
277
279 return _border;
280}
281
283 return _rows;
284}
285
287 return _aspect;
288}
289
292 auto& slider = get_widget<Gtk::Scale>(_builder, "border-slider");
293 slider.set_value(border);
294}
295
297 if (border == _border) return;
298
299 if (border < 0 || border > 100) {
300 g_warning("Unexpected tile border size of color palette: %d", border);
301 return;
302 }
303
304 _border = border;
305 refresh();
306}
307
310 auto& slider = get_widget<Gtk::Scale>(_builder, "size-slider");
311 slider.set_value(size);
312}
313
315 if (size == _size) return;
316
317 if (size < 1 || size > 1000) {
318 g_warning("Unexpected tile size for color palette: %d", size);
319 return;
320 }
321
322 _size = size;
323 refresh();
324}
325
326void ColorPalette::set_aspect(double aspect) {
327 _set_aspect(aspect);
328 auto& slider = get_widget<Gtk::Scale>(_builder, "aspect-slider");
329 slider.set_value(aspect);
330}
331
332void ColorPalette::_set_aspect(double aspect) {
333 if (aspect == _aspect) return;
334
335 if (aspect < -2.0 || aspect > 2.0) {
336 g_warning("Unexpected aspect ratio for color palette: %f", aspect);
337 return;
338 }
339
340 _aspect = aspect;
341 refresh();
342}
343
346 queue_resize();
347}
348
350 _set_rows(rows);
351 auto& slider = get_widget<Gtk::Scale>(_builder, "row-slider");
352 slider.set_value(rows);
353}
354
356 if (rows == _rows) return;
357
358 if (rows < 1 || rows > 1000) {
359 g_warning("Unexpected number of rows for color palette: %d", rows);
360 return;
361 }
362 _rows = rows;
364 refresh();
365}
366
368 auto& sb = get_widget<Gtk::CheckButton>(_builder, "use-sb");
369 // scrollbar can only be applied to single-row layouts
370 bool sens = _rows == 1;
371 if (sb.get_sensitive() != sens) sb.set_sensitive(sens);
372}
373
374void ColorPalette::set_compact(bool compact) {
375 if (_compact != compact) {
376 _compact = compact;
378
379 get_widget<Gtk::Scale>(_builder, "row-slider").set_visible(compact);
380 get_widget<Gtk::Label>(_builder, "row-label").set_visible(compact);
381 get_widget<Gtk::CheckButton>(_builder, "enlarge").set_visible(compact);
382 // get_widget<Gtk::CheckButton>(_builder, "show-labels").set_visible(false);
383 }
384}
385
389
391 return _stretch_tiles;
392}
393
395 auto& stretch = get_widget<Gtk::CheckButton>(_builder, "stretch");
396 stretch.set_active(enable);
397 _enable_stretch(enable);
398}
399
401 if (_stretch_tiles == enable) return;
402
403 _stretch_tiles = enable;
404 _normal_box.set_halign(enable ? Gtk::Align::FILL : Gtk::Align::START);
406 refresh();
407}
408
410 auto& sl = get_widget<Gtk::CheckButton>(_builder, "show-labels");
411 sl.set_active(labels);
412 if (_show_labels != labels) {
413 _show_labels = labels;
415 refresh();
416 }
417}
418
420 auto& aspect = get_widget<Gtk::Scale>(_builder, "aspect-slider");
421 aspect.set_sensitive(!_stretch_tiles);
422 auto& label = get_widget<Gtk::Label>(_builder, "aspect-label");
423 label.set_sensitive(!_stretch_tiles);
424}
425
427 auto& sb = get_widget<Gtk::CheckButton>(_builder, "use-sb");
428 sb.set_active(show);
429 _enable_scrollbar(show);
430}
431
433 if (_force_scrollbar == show) return;
434
435 _force_scrollbar = show;
437}
438
440 auto &box = get_widget<Gtk::Box>(_builder, "palette-box");
441 auto &btn_menu = get_widget<Gtk::MenuButton>(_builder, "btn-menu");
442 auto const colors = UI::get_children(_normal_box);
443 auto normal_count = std::max(1, static_cast<int>(colors.size()));
444 auto pinned_count = std::max(1, static_cast<int>(UI::get_children(_pinned_box).size()));
445
446 _normal_box.set_max_children_per_line(normal_count);
447 _normal_box.set_min_children_per_line(1);
448 _pinned_box.set_max_children_per_line(pinned_count);
449 _pinned_box.set_min_children_per_line(1);
450
451 auto alloc_width = _normal_box.get_parent()->get_allocated_width();
452 // if page-size is defined, align color tiles in columns
453 if (_page_size > 1 && alloc_width > 1 && !_show_labels && !colors.empty()) {
454 int width = get_tile_width();
455 if (width > 1) {
456 int cols = alloc_width / (width + _border);
457 cols = std::max(cols - cols % _page_size, _page_size);
458 if (_normal_box.get_max_children_per_line() != cols) {
459 _normal_box.set_max_children_per_line(cols);
460 }
461 }
462 }
463
464 if (_compact) {
465 box.set_orientation(Gtk::Orientation::HORIZONTAL);
466 box.set_valign(Gtk::Align::START);
467 box.set_vexpand(false);
468 btn_menu.set_margin_bottom(0);
469 btn_menu.set_margin_end(0);
470 // in compact mode scrollbars are hidden; they take up too much space
471 set_valign(Gtk::Align::START);
472 set_vexpand(false);
473
474 _scroll.set_valign(Gtk::Align::END);
475 _normal_box.set_valign(Gtk::Align::END);
476
477 if (_rows == 1 && _force_scrollbar) {
478 // horizontal scrolling with single row
479 _normal_box.set_min_children_per_line(normal_count);
480
481 _scroll_btn.set_visible(false);
482
483 if (_force_scrollbar) {
484 _scroll_left.set_visible(false);
485 _scroll_right.set_visible(false);
486 }
487 else {
488 _scroll_left.set_visible(true);
489 _scroll_right.set_visible(true);
490 }
491
492 // ideally we should be able to use POLICY_AUTOMATIC, but on some themes this leads to a scrollbar
493 // that obscures color tiles (it overlaps them); thus resorting to manual scrollbar selection
494 _scroll.set_policy(_force_scrollbar ? Gtk::PolicyType::ALWAYS : Gtk::PolicyType::EXTERNAL, Gtk::PolicyType::NEVER);
495 }
496 else {
497 // vertical scrolling with multiple rows
498 // 'external' allows scrollbar to shrink vertically
499 _scroll.set_policy(Gtk::PolicyType::NEVER, Gtk::PolicyType::EXTERNAL);
500 _scroll_left.set_visible(false);
501 _scroll_right.set_visible(false);
502 _scroll_btn.set_visible(true);
503 }
504
505 int div = _large_pinned_panel ? (_rows > 2 ? 2 : 1) : _rows;
506 _pinned_box.set_max_children_per_line(std::max((pinned_count + div - 1) / div, 1));
507 _pinned_box.set_margin_end(_border);
508 }
509 else {
510 box.set_orientation(Gtk::Orientation::VERTICAL);
511 box.set_valign(Gtk::Align::FILL);
512 box.set_vexpand(true);
513 btn_menu.set_margin_bottom(2);
514 btn_menu.set_margin_end(2);
515 // in normal mode use regular full-size scrollbars
516 set_valign(Gtk::Align::FILL);
517 set_vexpand(true);
518
519 _scroll_left.set_visible(false);
520 _scroll_right.set_visible(false);
521 _scroll_btn.set_visible(false);
522
523 _normal_box.set_valign(Gtk::Align::START);
524 _scroll.set_valign(Gtk::Align::FILL);
525 // 'always' allocates space for scrollbar
526 _scroll.set_policy(Gtk::PolicyType::NEVER, Gtk::PolicyType::ALWAYS);
527 }
529 resize();
530}
531
532int ColorPalette::get_tile_size(bool horz) const {
533 if (_stretch_tiles) return _size;
534
535 double aspect = horz ? _aspect : -_aspect;
536 int scale = _show_labels ? 2.0 : 1.0;
537 int size = 0;
538
539 if (aspect > 0) {
540 size = static_cast<int>(round((1.0 + aspect) * _size));
541 }
542 else if (aspect < 0) {
543 size = static_cast<int>(round((1.0 / (1.0 - aspect)) * _size));
544 }
545 else {
546 size = _size;
547 }
548 return size * scale;
549}
550
552 return get_tile_size(true);
553}
554
556 return get_tile_size(false);
557}
558
560 return (get_tile_height() + _border) * _rows;
561}
562
564 auto& checkbox = get_widget<Gtk::CheckButton>(_builder, "enlarge");
565 checkbox.set_active(large);
567}
568
570 if (_large_pinned_panel == large) return;
571
572 _large_pinned_panel = large;
573 refresh();
574}
575
579
581 return _show_labels;
582}
583
585 if ((_rows == 1 && _force_scrollbar) || !_compact) {
586 // auto size for single row to allocate space for scrollbar
587 _scroll.set_size_request(-1, -1);
588 }
589 else {
590 // exact size for multiple rows
592 _scroll.set_size_request(1, height);
593 }
594
595 _normal_box.set_column_spacing(_border);
596 _normal_box.set_row_spacing(_border);
597 _pinned_box.set_column_spacing(_border);
598 _pinned_box.set_row_spacing(_border);
599
600 int width = get_tile_width();
601 int height = get_tile_height();
602 for (auto const &item : _normal_items) {
603 item->set_size_request(width, height);
604 }
605
606 int pinned_width = width;
607 int pinned_height = height;
609 double mult = _rows > 2 ? _rows / 2.0 : 2.0;
610 pinned_width = pinned_height = static_cast<int>((height + _border) * mult - _border);
611 }
612 for (auto const &item : _pinned_items) {
613 item->set_size_request(pinned_width, pinned_height);
614 }
615}
616
617void ColorPalette::set_colors(std::vector<std::unique_ptr<Dialog::ColorItem>> coloritems)
618{
619 _normal_items.clear();
620 _pinned_items.clear();
621
622 for (auto &item : coloritems) {
623 item->signal_modified().connect([item = item.get()] {
624 UI::for_each_child(*item->get_parent(), [=](Gtk::Widget& w) {
625 if (auto label = dynamic_cast<Gtk::Label *>(&w)) {
626 label->set_text(item->get_description());
627 }
629 });
630 });
631 if (item->is_pinned()) {
632 _pinned_items.push_back(std::move(item));
633 } else {
634 _normal_items.push_back(std::move(item));
635 }
636 }
637 rebuild_widgets();
638 refresh();
639}
640
641Gtk::Widget *ColorPalette::_get_widget(Dialog::ColorItem *item) {
642 assert(!item->get_parent());
643 if (_show_labels) {
644 item->set_valign(Gtk::Align::CENTER);
645 auto const box = Gtk::make_managed<Gtk::Box>();
646 auto const label = Gtk::make_managed<Gtk::Label>(item->get_description());
647 box->append(*item);
648 box->append(*label);
649 return box;
650 }
651 return item;
652}
653
654void ColorPalette::rebuild_widgets()
655{
656 _normal_box.freeze_notify();
657 _pinned_box.freeze_notify();
658
659 UI::remove_all_children(_normal_box);
660 UI::remove_all_children(_pinned_box);
661
662 for (auto const &item : _normal_items) {
663 // in a tile mode (no labels) group headers are hidden:
664 if (!_show_labels && item->is_group()) continue;
665
666 // in a list mode with labels, do not show fillers:
667 if (_show_labels && item->is_filler()) continue;
668
669 _normal_box.append(*_get_widget(item.get()));
670 }
671 for (auto const &item : _pinned_items) {
672 _pinned_box.append(*_get_widget(item.get()));
673 }
674
675 set_up_scrolling();
676
677 _normal_box.thaw_notify();
678 _pinned_box.thaw_notify();
679}
680
681class ColorPaletteMenuItem : public PopoverMenuItem {
682public:
683 ColorPaletteMenuItem(Gtk::CheckButton *&group,
684 Glib::ustring const &label,
685 Glib::ustring id,
686 std::vector<rgb_t> colors)
687 : Glib::ObjectBase{"ColorPaletteMenuItem"}
689 , _radio_button{Gtk::make_managed<Gtk::CheckButton>(label)}
690 , _preview{Gtk::make_managed<ColorPalettePreview>(std::move(colors))}
691 , id{std::move(id)}
692 {
693 if (group) {
694 _radio_button->set_group(*group);
695 } else {
696 group = _radio_button;
697 }
698 auto const box = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 1);
699 box->append(*_radio_button);
700 box->append(*_preview);
701 set_child(*box);
702 }
703
704 void set_active(bool const active) { _radio_button->set_active(active); }
705
706 Glib::ustring const id;
707
708private:
709 Gtk::CheckButton *_radio_button = nullptr;
710 ColorPalettePreview *_preview = nullptr;
711};
712
713void ColorPalette::set_palettes(std::vector<palette_t> const &palettes)
714{
715 for (auto const &item: _palette_menu_items) {
716 _menu->remove(*item);
717 }
718
719 _palette_menu_items.clear();
720 _palette_menu_items.reserve(palettes.size());
721
722 Gtk::CheckButton *group = nullptr;
723 // We prepend in reverse so we add the palettes above the constant separator & Configure items.
724 for (auto it = palettes.crbegin(); it != palettes.crend(); ++it) {
725 auto& name = it->name;
726 auto& id = it->id;
727 auto item = std::make_unique<ColorPaletteMenuItem>(group, name, id, it->colors);
728 item->signal_activate().connect([id, this](){
729 if (!_in_update) {
730 _in_update = true;
731 _signal_palette_selected.emit(id);
732 _in_update = false;
733 }
734 });
735 item->set_visible(true);
736 _menu->prepend(*item);
737 _palette_menu_items.push_back(std::move(item));
738 }
739}
740
741sigc::signal<void (Glib::ustring)>& ColorPalette::get_palette_selected_signal() {
742 return _signal_palette_selected;
743}
744
745sigc::signal<void ()>& ColorPalette::get_settings_changed_signal() {
746 return _signal_settings_changed;
747}
748
749void ColorPalette::set_selected(const Glib::ustring& id) {
750 _in_update = true;
751
752 for (auto const &item : _palette_menu_items) {
753 item->set_active(item->id == id);
754 }
755
756 _in_update = false;
757}
758
759void ColorPalette::set_page_size(int page_size) {
760 _page_size = page_size;
761}
762
763void ColorPalette::set_filter(std::function<bool (const Dialog::ColorItem&)> filter) {
764 _normal_box.set_filter_func([=](Gtk::FlowBoxChild* c){
765 auto child = c->get_child();
766 if (auto box = dynamic_cast<Gtk::Box*>(child)) {
767 child = UI::get_children(*box).at(0);
768 }
769 if (auto color = dynamic_cast<Dialog::ColorItem*>(child)) {
770 return filter(*color);
771 }
772 return true;
773 });
774}
775
776void ColorPalette::apply_filter() {
777 _normal_box.invalidate_filter();
778}
779
780} // namespace Inkscape::UI::Widget
781
782/*
783 Local Variables:
784 mode:c++
785 c-file-style:"stroustrup"
786 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
787 indent-tabs-mode:nil
788 fill-column:99
789 End:
790*/
791// vim:filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99:
double scale
Definition aa.cpp:228
Gtk builder utilities.
constexpr C clamp(C val) const
Two-dimensional point with integer coordinates.
Definition int-point.h:57
Range of real numbers that is never empty.
Definition interval.h:59
The color item you see on-screen as a clickable box.
Definition color-item.h:46
sigc::connection connectAfterResize(F &&slot)
Register a handler to run immediately after a resize operation.
Definition bin.h:59
void set_child(Gtk::Widget *child)
Sets (parents) the child widget, or unsets (unparents) it if child is null.
Definition bin.cpp:40
A Gtk::DrawingArea to preview color palette menu items by showing a small example of the colors.
sigc::signal< void()> _signal_settings_changed
std::vector< std::unique_ptr< Dialog::ColorItem > > _normal_items
Glib::RefPtr< Gtk::Builder > _builder
std::optional< gint64 > _scroll_cb_last_time
std::unique_ptr< PopoverMenu > _menu
void set_colors(std::vector< std::unique_ptr< Dialog::ColorItem > > coloritems)
bool scroll_cb(Glib::RefPtr< Gdk::FrameClock > const &)
std::vector< std::unique_ptr< Dialog::ColorItem > > _pinned_items
void scroll(int dx, int dy, double snap, bool smooth)
A replacement for GTK3ʼs Gtk::MenuItem, as removed in GTK4.
char * id
Definition sp-object.h:192
Color item used in palettes and swatches UI.
A Gtk::DrawingArea to preview color palette menu items by showing a small example of the colors.
Color palette widget.
const double w
Definition conic-4.cpp:19
double c[8][4]
SPItem * item
Glib::ustring label
int sgn(const T &x)
Sign function - indicates the sign of a numeric type.
Definition math-utils.h:51
Definition desktop.h:50
Custom widgets.
Definition desktop.h:126
static constexpr int height
static Geom::Interval get_range(Gtk::Scrollbar const &sb)
static auto make_menu()
void remove_all_children(Widget &widget)
For each child in get_children(widget), call widget.remove(*child). May not cause delete child!
Definition util.h:75
std::vector< Gtk::Widget * > get_children(Gtk::Widget &widget)
Get a vector of the widgetʼs children, from get_first_child() through each get_next_sibling().
Definition util.cpp:141
W & get_widget(const Glib::RefPtr< Gtk::Builder > &builder, const char *id)
Gtk::Widget * for_each_child(Gtk::Widget &widget, Func &&func, bool const plus_self=false, bool const recurse=false, int const level=0)
Call Func with a reference to each child of parent, until it returns _break.
Definition util.h:90
Glib::RefPtr< Gtk::Builder > create_builder(const char *filename)
STL namespace.
A replacement for GTK3ʼs Gtk::MenuItem, as removed in GTK4.
A replacement for GTK3ʼs Gtk::Menu, as removed in GTK4.
Ocnode * child[8]
Definition quantize.cpp:33
double border
double width
Glib::ustring name
Definition toolbars.cpp:55
Glib::RefPtr< Gtk::Adjustment > smooth