16#include <sigc++/connection.h>
17#include <sigc++/adaptors/bind.h>
18#include <sigc++/functors/mem_fun.h>
19#include <glibmm/ustring.h>
20#include <gtkmm/adjustment.h>
21#include <gtkmm/droptarget.h>
22#include <gtkmm/gestureclick.h>
23#include <gtkmm/checkbutton.h>
67 32, 16, 10, 8, 6, 4, 3, 2, 1.5, 1, 0.75, 0.5, 0.25, 0.1};
71 {{ _(
"N/A"), _(
"Nothing selected")},
72 { _(
"N/A"), _(
"Nothing selected")}},
73 {{C_(
"Fill",
"<i>None</i>"), _(
"No fill, middle-click for black fill")},
74 {C_(
"Stroke",
"<i>None</i>"), _(
"No stroke, middle-click for black stroke")}},
75 {{ _(
"<b>Unset</b>"), _(
"Unset fill")},
76 { _(
"<b>Unset</b>"), _(
"Unset stroke")}},
77 {{ _(
"≠"), _(
"Different fills")},
78 { _(
"≠"), _(
"Different strokes")}},
79 {{ _(
"Pattern"), _(
"Pattern (fill)")},
80 { _(
"Pattern"), _(
"Pattern (stroke)")}},
81 {{ _(
"Hatch"), _(
"Pattern (fill)")},
82 { _(
"Hatch"), _(
"Pattern (stroke)")}},
83 {{ _(
"<b>L</b>"), _(
"Linear gradient (fill)")},
84 { _(
"<b>L</b>"), _(
"Linear gradient (stroke)")}},
85 {{ _(
"<b>R</b>"), _(
"Radial gradient (fill)")},
86 { _(
"<b>R</b>"), _(
"Radial gradient (stroke)")}},
87 {{ _(
"<b>M</b>"), _(
"Mesh gradient (fill)")},
88 { _(
"<b>M</b>"), _(
"Mesh gradient (stroke)")}},
89 {{ _(
"<b>C</b>"), _(
"Flat color (fill)")},
90 { _(
"<b>C</b>"), _(
"Flat color (stroke)")}}
104 if (flags & (SP_OBJECT_STYLE_MODIFIED_FLAG)) {
117struct SelectedStyleDropTracker final {
131 :
Gtk::Box(
Gtk::Orientation::HORIZONTAL)
134 set_name(
"SelectedStyle");
137 grid = Gtk::make_managed<Gtk::Grid>();
141 for (
int i = 0; i <2; i++) {
142 label[i] = Gtk::make_managed<Gtk::Label>(i == 0 ? _(
"Fill:") : _(
"Stroke:"));
143 label[i]->set_halign(Gtk::Align::END);
146 tag[i] = Gtk::make_managed<Gtk::Label>();
148 tag[i]->set_name(
"Tag");
158 color_preview[i] = std::make_unique<Inkscape::UI::Widget::ColorPreview>(0);
164 swatch[i] = Gtk::make_managed<RotateableSwatch>(
this, i);
166 swatch[i]->set_hexpand(
false);
174 drop[i] = std::make_unique<SelectedStyleDropTracker>();
175 drop[i]->parent =
this;
178 target->signal_drop().connect([
this, i] (Glib::ValueBase
const &value,
double,
double) {
183 auto const &tracker = *
drop[i];
184 auto const &paintdef = *
reinterpret_cast<PaintDef *
>(g_value_get_boxed(value.gobj()));
187 std::string colorspec;
191 auto const [r, g, b] = paintdef.
get_rgb();
192 colorspec.resize(63);
193 sp_svg_write_color(colorspec.data(), colorspec.size() + 1, SP_RGBA32_U_COMPOSE(r, g, b, 0xff));
194 colorspec.resize(std::strlen(colorspec.c_str()));
205 swatch[i]->add_controller(target);
212 grid->attach(*
tag[i], 1, i, 1, 1);
232 opacity_sb = Gtk::make_managed<Inkscape::UI::Widget::SpinButton>(0.02, 0);
245 grid->set_column_spacing(4);
384 (255 - SP_RGBA32_R_U(color)),
385 (255 - SP_RGBA32_G_U(color)),
386 (255 - SP_RGBA32_B_U(color)),
407 (255 - SP_RGBA32_R_U(color)),
408 (255 - SP_RGBA32_G_U(color)),
409 (255 - SP_RGBA32_B_U(color)),
470 auto const display = Gdk::Display::get_default();
471 display->get_primary_clipboard()->set_text(text);
483 auto const display = Gdk::Display::get_default();
484 display->get_primary_clipboard()->set_text(text);
491 auto const display = Gdk::Display::get_default();
492 Glib::RefPtr<Gdk::Clipboard> refClipboard = display->get_primary_clipboard();
496 text = refClipboard->read_text_finish(
result);
497 }
catch (Glib::Error
const &
err) {
498 std::cout <<
"Pasting text failed: " <<
err.what() << std::endl;
503 if (color == 0x000000ff)
515 auto const display = Gdk::Display::get_default();
516 Glib::RefPtr<Gdk::Clipboard> refClipboard = display->get_primary_clipboard();
521 auto const display = Gdk::Display::get_default();
522 Glib::RefPtr<Gdk::Clipboard> refClipboard = display->get_primary_clipboard();
537 fs->showPageStrokePaint();
543 auto const button = click.get_current_button();
547 }
else if (button == 3) {
549 }
else if (button == 2) {
556 return Gtk::EventSequenceState::CLAIMED;
562 auto const button = click.get_current_button();
565 fs->showPageStrokePaint();
566 }
else if (button == 3) {
568 }
else if (button == 2) {
575 return Gtk::EventSequenceState::CLAIMED;
581 auto const button = click.get_current_button();
584 fs->showPageStrokeStyle();
585 }
else if (button == 3) {
587 [=](
auto const mi){ return mi->get_label() == _sw_unit->abbr; });
588 if (it !=
_unit_mis.cend()) (*it)->set_active(
true);
591 }
else if (button == 2) {
594 return Gtk::EventSequenceState::CLAIMED;
597Gtk::EventSequenceState
599 int ,
double ,
double )
601 const char* opacity =
opacity_sb->get_value() < 50?
"0.5" : (
opacity_sb->get_value() == 100?
"0" :
"1");
607 return Gtk::EventSequenceState::CLAIMED;
610template <
typename Slot,
typename ...Args>
614 auto const item = Gtk::make_managed<UI::Widget::PopoverMenuItem>(std::forward<Args>(args)...);
615 item->set_child(*Gtk::make_managed<Gtk::Label>(label, Gtk::Align::START, Gtk::Align::START));
616 item->signal_activate().connect(std::move(slot));
622 _popup[i] = std::make_unique<UI::Widget::PopoverMenu>(*
this, Gtk::PositionType::TOP);
625 auto const add_item = [&](Glib::ustring
const & fill_label,
auto const fill_method,
626 Glib::ustring
const &stroke_label,
auto const stroke_method)
628 auto const &
label = i ==
SS_FILL || stroke_label.empty() ? fill_label : stroke_label ;
629 auto const method = i ==
SS_FILL || stroke_method ==
nullptr ? fill_method : stroke_method;
635 add_item(_(
"Edit Fill..." ) , &SelectedStyle:: on_fill_edit ,
638 _popup[i]->append_separator();
641 add_item(_(
"Last Set Color") , &SelectedStyle:: on_fill_lastused ,
643 add_item(_(
"Last Selected Color") , &SelectedStyle:: on_fill_lastselected,
646 _popup[i]->append_separator();
648 add_item(_(
"Invert") , &SelectedStyle:: on_fill_invert ,
651 _popup[i]->append_separator();
653 add_item(_(
"White") , &SelectedStyle:: on_fill_white ,
655 add_item(_(
"Black") , &SelectedStyle:: on_fill_black ,
658 _popup[i]->append_separator();
661 _(
"Copy Color") , &SelectedStyle:: on_fill_copy ,
665 add_item(_(
"Paste Color") , &SelectedStyle:: on_fill_paste ,
670 _popup[i]->append_separator();
672 add_item(_(
"Make Fill Opaque" ) , &SelectedStyle:: on_fill_opaque ,
675 add_item(_(
"Unset Fill" ) , &SelectedStyle:: on_fill_unset ,
677 add_item(_(
"Remove Fill" ) , &SelectedStyle:: on_fill_remove ,
683 _popup_sw = std::make_unique<UI::Widget::PopoverMenu>(*
this, Gtk::PositionType::TOP);
685 _popup_sw->append_section_label(_(
"<b>Stroke Width</b>"));
689 _popup_sw->append_section_label(_(
"Unit"));
690 Gtk::CheckButton *group =
nullptr;
693 auto const item = Gtk::make_managed<UI::Widget::PopoverMenuItem>();
694 auto const radio = Gtk::make_managed<Gtk::CheckButton>(
key);
698 radio->set_group(*group);
700 item->set_child(*radio);
702 auto const u = unit_table.getUnit(
key);
703 item->signal_activate().connect(
710 _popup_sw->append_section_label(_(
"Width"));
711 for (std::size_t i = 0; i <
_sw_presets.size(); ++i) {
774 tag[i]->set_markup(
"");
789 if (paint->set && paint->isPaintserver()) {
790 SPPaintServer *server = (i ==
SS_FILL)? SP_STYLE_FILL_SERVER (&query) : SP_STYLE_STROKE_SERVER (&query);
797 if (is<SPLinearGradient>(server)) {
798 auto vector = cast<SPGradient>(server)->getVector();
806 }
else if (is<SPRadialGradient>(server)) {
807 auto vector = cast<SPGradient>(server)->getVector();
815 }
else if (is<SPMeshGradient>(server)) {
816 auto array = cast<SPGradient>(server)->getArray();
824 }
else if (is<SPPattern>(server)) {
829 }
else if (is<SPHatch>(server)) {
836 g_warning (
"file %s: line %d: Unknown paint server", __FILE__, __LINE__);
838 }
else if (paint->set && paint->isColor()) {
839 guint32 color = paint->value.color.toRGBA32(
840 SP_SCALE24_TO_FLOAT ((i ==
SS_FILL) ?
847 safeprintf (c_string,
"%06x/%.3g", color >> 8, SP_RGBA32_A_F(color));
851 _(
", drag to adjust, middle-click to remove"));
858 }
else if (paint->set && paint->isNone()) {
863 }
else if (!paint->set) {
872 tag[i]->set_markup(
"<b>a</b>");
873 tag[i]->set_tooltip_text(i == 0 ?
874 _(
"Fill is averaged over selected objects") :
875 _(
"Stroke is averaged over selected objects"));
879 tag[i]->set_markup(
"<b>m</b>");
880 tag[i]->set_tooltip_text(i == 0 ?
881 _(
"Multiple selected objects have same fill") :
882 _(
"Multiple selected objects have same stroke"));
884 tag[i]->set_markup(
"");
885 tag[i]->set_tooltip_text(
"");
906 opacity_sb->set_tooltip_text(_(
"Nothing selected"));
912 opacity_sb->set_tooltip_text(_(
"Opacity (%)"));
936 stroke_width->set_tooltip_text(_(
"Stroke width: Hairline"));
947 gchar *str = g_strdup_printf(
" %#.3g",
w);
948 if (str[strlen(str) - 1] ==
',' || str[strlen(str) - 1] ==
'.') {
949 str[strlen(str)-1] =
'\0';
955 gchar *str = g_strdup_printf(_(
"Stroke width: %.5g%s%s"),
959 _(
" (averaged)") :
"");
979 _popup_opacity = std::make_unique<UI::Widget::PopoverMenu>(*
this, Gtk::PositionType::TOP);
980 auto const add_item = [&](Glib::ustring
const &
label,
auto const method)
1018 set_name(
"RotatableSwatch");
1027 hsla[3] = SP_RGBA32_A_F(cc);
1030 double old = hsla[1];
1032 hsla[1] += by * (1 - hsla[1]);
1034 hsla[1] += by * (hsla[1]);
1036 diff = hsla[1] - old;
1038 double old = hsla[2];
1040 hsla[2] += by * (1 - hsla[2]);
1042 hsla[2] += by * (hsla[2]);
1044 diff = hsla[2] - old;
1046 double old = hsla[3];
1050 }
else if (hsla[3] > 1) {
1053 diff = hsla[3] - old;
1055 double old = hsla[0];
1061 diff = hsla[0] - old;
1069 SP_RGBA32_U_COMPOSE(
1070 (SP_COLOR_F_TO_U(
rgb[0])),
1071 (SP_COLOR_F_TO_U(
rgb[1])),
1072 (SP_COLOR_F_TO_U(
rgb[2])),
1099 std::string cursor_filename =
"adjust_hue.svg";
1101 cursor_filename =
"adjust_saturation.svg";
1103 cursor_filename =
"adjust_lightness.svg";
1105 cursor_filename =
"adjust_alpha.svg";
1127 double ch = hsla[3];
1130 _(
"Adjusting <b>alpha</b>: was %.3g, now <b>%.3g</b> (diff %.3g); with <b>Ctrl</b> to adjust lightness, with <b>Shift</b> to adjust saturation, without modifiers to adjust hue"),
1131 ch - diff, ch, diff);
1135 double ch = hsla[1];
1138 _(
"Adjusting <b>saturation</b>: was %.3g, now <b>%.3g</b> (diff %.3g); with <b>Ctrl</b> to adjust lightness, with <b>Alt</b> to adjust alpha, without modifiers to adjust hue"),
1139 ch - diff, ch, diff);
1143 double ch = hsla[2];
1146 _(
"Adjusting <b>lightness</b>: was %.3g, now <b>%.3g</b> (diff %.3g); with <b>Shift</b> to adjust saturation, with <b>Alt</b> to adjust alpha, without modifiers to adjust hue"),
1147 ch - diff, ch, diff);
1151 double ch = hsla[0];
1154 _(
"Adjusting <b>hue</b>: was %.3g, now <b>%.3g</b> (diff %.3g); with <b>Shift</b> to adjust saturation, with <b>Alt</b> to adjust alpha, with <b>Ctrl</b> to adjust lightness"),
1155 ch - diff, ch, diff);
1175 if (
auto window =
dynamic_cast<Gtk::Window *
>(get_root())) {
1176 window->set_cursor();
1194 if (!strcmp(
undokey,
"ssrot1")) {
1209 startvalue_set(false),
1222 newval =
current * (std::exp(
std::log(max_f-1) * (by+1)) - 1) / (max_f-2);
1225 if (
final && newval < 1e-6) {
1274 if (!strcmp(
undokey,
"swrot1")) {
A thin wrapper around std::ostringstream, but writing floating point numbers in the format required b...
static void maybeDone(SPDocument *document, const gchar *keyconst, Glib::ustring const &event_description, Glib::ustring const &undo_icon)
static void done(SPDocument *document, Glib::ustring const &event_description, Glib::ustring const &undo_icon)
The set of selected SPObjects for a given document and layer model.
sigc::connection connectChanged(sigc::slot< void(Selection *)> slot)
Connects a slot to be notified of selection changes.
sigc::connection connectModified(sigc::slot< void(Selection *, unsigned)> slot)
Connects a slot to be notified of selected object modifications.
DialogBase * get_dialog(const Glib::ustring &dialog_type)
void new_dialog(const Glib::ustring &dialog_type)
Add new dialog to the current container or in a floating window, based on preferences.
static double convert(double from_dist, Unit const *from, Unit const *to)
Convert distances.
Interface for refcounted XML nodes.
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
Pure data representation of a color definition.
std::array< unsigned, 3 > const & get_rgb() const
static void hsl_to_rgb_floatv(float *rgb, float h, float s, float l)
Fill rgb float array from h,s,l float values.
static void rgb_to_hsl_floatv(float *hsl, float r, float g, float b)
Fill hsl float array from r,g,b float values.
To do: update description of desktop.
SPDocument * getDocument() const
SPNamedView * getNamedView() const
Inkscape::UI::Dialog::DialogContainer * getContainer()
Inkscape::Selection * getSelection() const
Inkscape::UI::Tools::ToolBase * getTool() const
sigc::connection connectToolSubselectionChanged(const sigc::slot< void(gpointer)> &slot)
Inkscape::Util::Unit const * display_units
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
T< SPAttr::FILL, SPIPaint > fill
fill
T< SPAttr::STROKE, SPIPaint > stroke
stroke
T< SPAttr::STROKE_WIDTH, SPILength > stroke_width
stroke-width
T< SPAttr::FILL_OPACITY, SPIScale24 > fill_opacity
fill-opacity
T< SPAttr::STROKE_OPACITY, SPIScale24 > stroke_opacity
stroke-opacity
T< SPAttr::OPACITY, SPIScale24 > opacity
opacity
T< SPAttr::STROKE_EXTENSIONS, SPIStrokeExtensions > stroke_extensions
-inkscape-stroke
System-wide clipboard management - class declaration.
Utilities to more easily use Gtk::EventController & subclasses like Gesture.
TODO: insert short description here.
std::shared_ptr< Css const > css
guint32 sp_desktop_get_color(SPDesktop *desktop, bool is_fill)
Return the desktop's current color.
void sp_desktop_set_style(SPDesktop *desktop, SPCSSAttr *css, bool change, bool write_current, bool switch_style)
Apply style on selection on desktop.
int sp_desktop_query_style(SPDesktop *desktop, SPStyle *style, int property)
Query the subselection (if any) or selection on the given desktop for the given property,...
@ QUERY_STYLE_PROPERTY_STROKE
@ QUERY_STYLE_PROPERTY_STROKEWIDTH
@ QUERY_STYLE_PROPERTY_FILL
@ QUERY_STYLE_PROPERTY_MASTEROPACITY
@ QUERY_STYLE_MULTIPLE_DIFFERENT
@ QUERY_STYLE_MULTIPLE_AVERAGED
@ QUERY_STYLE_MULTIPLE_SAME
A base class for all dialogs.
A widget that manages DialogNotebook's and other widgets inside a horizontal DialogMultipaned.
static char const *const current
TODO: insert short description here.
void sp_gradient_invert_selected_gradients(SPDesktop *desktop, Inkscape::PaintTarget fill_or_stroke)
Macro for icon names used in Inkscape.
Interface for locally managing a current status message.
static void err(const char *fmt,...)
Gtk::GestureClick & add_click(Gtk::Widget &widget, ClickSlot on_pressed, ClickSlot on_released, Button const button, Gtk::PropagationPhase const phase, When const when)
Create a click gesture for the given widget; by default claim sequence.
void on_popup_menu(Gtk::Widget &widget, PopupMenuSlot slot)
Connect slot to a widgetʼs key and button events that traditionally trigger a popup menu,...
std::optional< PopupMenuClick > PopupMenuOptionalClick
Optional: not present if popup wasnʼt triggered by click.
Glib::ustring format_classic(T const &... args)
static void append(std::vector< T > &target, std::vector< T > &&source)
void set_svg_cursor(Gtk::Widget &widget, std::string const &file_name, std::uint32_t const fill, std::uint32_t const stroke, double fill_opacity, double stroke_opacity)
Loads an SVG cursor from the specified file name, and sets it as the cursor of the given widget.
@ HORIZONTAL
The x-dimension (0).
static cairo_user_data_key_t key
Piecewise< SBasis > log(Interval in)
SPCSSAttr * sp_repr_css_attr_new()
Creates an empty SPCSSAttr (a class for manipulating CSS style properties).
void sp_repr_css_attr_unref(SPCSSAttr *css)
Unreferences an SPCSSAttr (will be garbage collected if no references remain).
void sp_repr_css_unset_property(SPCSSAttr *css, gchar const *name)
Set a style property to "inkscape:unset".
void sp_repr_css_set_property(SPCSSAttr *css, gchar const *name, gchar const *value)
Set a style property to a new value (e.g.
static void ss_selection_modified(Inkscape::Selection *selection, guint flags, gpointer data)
static void ss_subselection_changed(gpointer, gpointer data)
static constexpr int SELECTED_STYLE_SB_WIDTH
static constexpr int SELECTED_STYLE_FLAG_WIDTH
static constexpr std::array< double, 15 > _sw_presets
static void ss_selection_changed(Inkscape::Selection *, gpointer data)
static const Glib::ustring type_strings[][2][2]
static constexpr int SELECTED_STYLE_PLACE_WIDTH
static constexpr int SELECTED_STYLE_STROKE_WIDTH
static constexpr int SELECTED_STYLE_WIDTH
SVG <hatch> implementation.
TODO: insert short description here.
TODO: insert short description here.
SVG <pattern> implementation.
TODO: insert short description here.
SPStyle - a style object for SPItem objects.
void sp_svg_write_color(gchar *buf, unsigned const buflen, guint32 const rgba32)
Converts an RGBA32 colour to a CSS/SVG representation of the RGB portion of that colour.
guint32 sp_svg_read_color(gchar const *str, guint32 const dfl)
TODO: insert short description here.