/*
8 * bulia byak <buliabyak@users.sf.net>
9 * John Cliff <simarilius@yahoo.com>
10 * Jon A. Cruz <jon@joncruz.org>
13 * Copyright (C) 2018 Authors
14 * Released under GNU GPL v2+, read the file
'COPYING' for more information.
17#define noSP_PS_VERBOSE
30#include <glibmm/fileutils.h>
31#include <glibmm/i18n.h>
32#include <gtkmm/combobox.h>
33#include <gtkmm/label.h>
34#include <gtkmm/togglebutton.h>
70 "MODE_GRADIENT_LINEAR",
71 "MODE_GRADIENT_RADIAL",
84GtkWidget *ink_combo_box_new_with_model(GtkTreeModel *model)
86 auto const combobox = Gtk::make_managed<Gtk::ComboBox>();
87 gtk_combo_box_set_model(combobox->gobj(), model);
88 return combobox->Gtk::Widget::gobj();
96class FillRuleRadioButton :
public Gtk::ToggleButton {
101 FillRuleRadioButton() =
default;
102 FillRuleRadioButton(Gtk::ToggleButton &group) { set_group(group); }
108class StyleToggleButton :
public Gtk::ToggleButton {
137 : _selected_colors(
std::move(colors))
139 set_orientation(Gtk::Orientation::VERTICAL);
144 _style = Gtk::make_managed<Gtk::Box>();
145 _style->set_name(
"PaintSelector");
146 _style->set_visible(
true);
153 _(
"Linear gradient"));
155 _(
"Radial gradient"));
163 _(
"Unset paint (make it undefined so it can be inherited)"));
170 _evenodd = Gtk::make_managed<FillRuleRadioButton>();
174 _(
"Any path self-intersections or subpaths create holes in the fill (fill-rule: evenodd)"));
176 _evenodd->set_image_from_icon_name(
"fill-rule-even-odd", Gtk::IconSize::NORMAL);
181 _nonzero = Gtk::make_managed<FillRuleRadioButton>();
185 _nonzero->set_tooltip_text(_(
"Fill is solid unless a subpath is counterdirectional (fill-rule: nonzero)"));
187 _nonzero->set_image_from_icon_name(
"fill-rule-nonzero", Gtk::IconSize::NORMAL);
194 _label = Gtk::make_managed<Gtk::Label>(
"");
195 auto const lbbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 0);
196 _label->set_visible(
true);
200 _frame = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL);
201 _frame->set_visible(
true);
216 auto const b = Gtk::make_managed<StyleToggleButton>();
217 b->set_tooltip_text(tip);
218 b->set_visible(
true);
219 b->set_has_frame(
false);
222 b->set_group(*
_none);
225 b->set_image_from_icon_name(pixmap, Gtk::IconSize::NORMAL);
235 if (!
_update && tb->get_active()) {
243 if (!
_update && tb->get_active()) {
244 auto fr = tb->get_fillrule();
256 _label->set_visible(
true);
295 g_warning(
"file %s: line %d: Unknown paint mode %d", __FILE__, __LINE__,
mode);
316 g_print(
"PaintSelector set SWATCH\n");
328 g_print(
"PaintSelector set GRADIENT LINEAR\n");
335 gsel->setGradient(gradient);
336 gsel->setVector((vector) ? vector->
document :
nullptr, vector);
337 gsel->selectStop(selected);
343 g_print(
"PaintSelector set GRADIENT RADIAL\n");
350 gsel->setGradient(gradient);
351 gsel->setVector((vector) ? vector->
document :
nullptr, vector);
352 gsel->selectStop(selected);
359 g_print(
"PaintSelector set GRADIENT MESH\n");
375 gsel->setUnits(units);
376 gsel->setSpread(spread);
384 units = gsel->getUnits();
385 spread = gsel->getSpread();
434 _style->set_sensitive(
false);
436 _label->set_markup(_(
"<b>No objects</b>"));
442 _style->set_sensitive(
true);
444 _label->set_markup(_(
"<b>Multiple styles</b>"));
450 _style->set_sensitive(
true);
452 _label->set_markup(_(
"<b>Paint is undefined</b>"));
458 _style->set_sensitive(
true);
460 _label->set_markup(_(
"<b>No paint</b>"));
480 g_warning(
"PaintSelector::onSelectedColorChanged(): selected color changed while not in color selection mode");
504 _style->set_sensitive(
true);
518 auto const color_selector = Gtk::make_managed<ColorNotebook>(
_selected_colors);
519 color_selector->set_visible(
true);
523 color_selector->set_label(_(
"<b>Flat color</b>"));
530 _label->set_visible(
false);
533 g_print(
"Color req\n");
554 _style->set_sensitive(
true);
573 catch (std::exception& ex) {
574 g_error(
"Creation of GradientEditor widget failed: %s.", ex.what());
589 _label->set_visible(
false);
593 _label->set_visible(
false);
597 g_print(
"Gradient req\n");
606 g_object_unref(G_OBJECT(widget));
617 std::vector<SPMeshGradient *> pl;
618 if (source ==
nullptr)
623 for (
auto meshe : meshes) {
624 if (is<SPMeshGradient>(meshe) && cast<SPGradient>(meshe) == cast<SPGradient>(meshe)->getArray()) {
626 pl.push_back(cast<SPMeshGradient>(meshe));
637 GtkListStore *
store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo)));
640 for (
auto i : mesh_list) {
644 gchar
const *meshid = repr->
attribute(
"id");
645 gchar
const *
label = meshid;
648 gboolean stockid =
false;
649 if (repr->
attribute(
"inkscape:stockid")) {
654 gtk_list_store_append(
store, &iter);
711 GtkListStore *
store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo)));
716 gtk_list_store_append(
store, &iter);
719 gtk_widget_set_sensitive(combo, FALSE);
724 gtk_widget_set_sensitive(combo, TRUE);
728 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(
store), &iter)) {
729 gboolean sep =
false;
732 gtk_tree_model_iter_next(GTK_TREE_MODEL(
store), &iter);
734 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(combo), &iter);
751 GtkTreeModel *
store = gtk_combo_box_get_model(GTK_COMBO_BOX(
_meshmenu));
752 gtk_list_store_clear(GTK_LIST_STORE(
store));
764 gchar *meshid =
nullptr;
765 bool valid = gtk_tree_model_get_iter_first(
store, &iter);
770 while (valid && strcmp(meshid, meshname) != 0) {
771 valid = gtk_tree_model_iter_next(
store, &iter);
778 gtk_combo_box_set_active_iter(GTK_COMBO_BOX(
_meshmenu), &iter);
792 _style->set_sensitive(
true);
802 _selector_mesh = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 4);
804 auto const hb = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 1);
811 gtk_list_store_new(
COMBO_N_COLS, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_BOOLEAN);
812 GtkWidget *combo = ink_combo_box_new_with_model(GTK_TREE_MODEL(
store));
815 GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
816 gtk_cell_renderer_set_padding(renderer, 2, 0);
817 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, TRUE);
818 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), renderer,
"text",
COMBO_COL_LABEL,
nullptr);
824 g_object_ref(G_OBJECT(combo));
826 gtk_box_append(hb->gobj(), combo);
829 g_object_unref(G_OBJECT(
store));
831 auto const hb2 = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 0);
833 auto const l = Gtk::make_managed<Gtk::Label>();
834 l->set_markup(_(
"Use the <b>Mesh tool</b> to modify the mesh."));
836 l->set_size_request(180, -1);
844 _label->set_markup(_(
"<b>Mesh fill</b>"));
847 g_print(
"Mesh req\n");
860 GtkTreeModel *
store = gtk_combo_box_get_model(GTK_COMBO_BOX(
_meshmenu));
864 if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(
_meshmenu), &iter) ||
865 !gtk_list_store_iter_is_valid(GTK_LIST_STORE(
store), &iter)) {
869 gchar *meshid =
nullptr;
870 gboolean stockid = FALSE;
876 if (meshid ==
nullptr) {
881 if (strcmp(meshid,
"none")) {
885 mesh_name = g_strconcat(
"urn:inkscape:mesh:", meshid,
nullptr);
887 mesh_name = g_strdup(meshid);
891 if (mesh_obj && is<SPMeshGradient>(mesh_obj)) {
892 mesh = cast<SPMeshGradient>(mesh_obj);
896 std::cerr <<
"PaintSelector::getMeshGradient: Unexpected meshid value." << std::endl;
924 g_object_unref(G_OBJECT(widget));
945 _style->set_sensitive(
true);
963 _label->set_visible(
false);
966 g_print(
"Pattern req\n");
976 _style->set_sensitive(
true);
983 _label->set_markup(_(
"<b>Hatch fill</b>"));
986 g_print(
"Hatch req\n");
992 gboolean sep = FALSE;
1042 auto stock_doc = sel.second;
1044 if (sel.first.empty())
return nullptr;
1046 auto patid = sel.first;
1048 if (patid !=
"none") {
1050 patid =
"urn:inkscape:pattern:" + patid;
1052 pat_obj =
get_stock_item(patid.c_str(), stock_doc !=
nullptr, stock_doc);
1058 return cast<SPPattern>(pat_obj);
1067 _style->set_sensitive(
true);
1091 _label->set_markup(_(
"<b>Swatch fill</b>"));
1095 g_print(
"Swatch req\n");
1110 g_message(
"PaintSelector::getModeForStyle(%p, %d)", &style, kind);
1111 g_message(
"==== server:%p %s grad:%s swatch:%s", server, server->
getId(),
1112 (is<SPGradient>(server) ?
"Y" :
"n"),
1113 (is<SPGradient>(server) && cast<SPGradient>(server)->getVector()->isSwatch() ?
"Y" :
"n"));
1117 if (server && is<SPGradient>(server) && cast<SPGradient>(server)->getVector()->isSwatch()) {
1119 }
else if (is<SPLinearGradient>(server)) {
1121 }
else if (is<SPRadialGradient>(server)) {
1124 }
else if (is<SPMeshGradient>(server)) {
1127 }
else if (is<SPPattern>(server)) {
1129 }
else if (is<SPHatch>(server)) {
1132 g_warning(
"file %s: line %d: Unknown paintserver", __FILE__, __LINE__);
1135 }
else if (target.
isColor()) {
1138 }
else if (target.
isNone()) {
1141 g_warning(
"file %s: line %d: Unknown paint type", __FILE__, __LINE__);
Cartesian point / 2D vector and related operations.
3x3 affine transformation matrix.
3x3 matrix representing an affine transformation.
Two-dimensional point that doubles as a vector.
sigc::signal< void(SPStop *)> & signal_stop_selected()
static PatternManager & get(Args &&... args)
Interface for refcounted XML nodes.
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
Typed SVG document implementation.
SPObject * getObjectById(std::string const &id) const
std::vector< SPObject * > const getResourceList(char const *key)
SPGradient * getVector(bool force_private=false)
Returns private vector of given gradient (the gradient at the end of the href chain which has stops),...
void setSpread(SPGradientSpread spread)
Set spread property of gradient and emit modified.
void setUnits(SPGradientUnits units)
Set units property of gradient and emit modified.
void set(SPAttr key, char const *value) override
Set gradient attribute to value.
Paint type internal to SPStyle.
bool isPaintserver() const
SPObject is an abstract base class of all of the document nodes at the SVG document level.
char const * getId() const
Returns the objects current ID string.
Inkscape::XML::Node * updateRepr(unsigned int flags=SP_OBJECT_WRITE_EXT)
Updates the object's repr based on the object's state.
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
Inkscape::Colors::Color getColor() const
SPPaintServer * getFillPaintServer()
SPPaintServer * getStrokePaintServer()
SPIPaint * getFillOrStroke(bool fill_)
Get either the fill or the stroke property.
A notebook with RGB, CMYK, CMS, HSL, and Wheel pages.
TODO: insert short description here.
Gradient vector and position widget.
Macro for icon names used in Inkscape.
void pack_end(Gtk::Box &box, Gtk::Widget &child, bool const expand, bool const fill, unsigned const padding)
Adds child to box, packed with reference to the end of box.
void pack_start(Gtk::Box &box, Gtk::Widget &child, bool const expand, bool const fill, unsigned const padding)
Adds child to box, packed with reference to the start of box.
Helper class to stream background task notifications as a series of messages.
Helpers for using Gtk::Boxes, encapsulating large changes between GTK3 & GTK4.
static gchar const * modeStrings[]
PaintSelector: Generic paint selector widget.
TODO: insert short description here.
C facade to Inkscape::XML::Node.
Inkscape::IO::Resource - simple resource API.
@ SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX
SVG <hatch> implementation.
TODO: insert short description here.
TODO: insert short description here.
SVG <pattern> implementation.
TODO: insert short description here.
TODO: insert short description here.
SPObject * get_stock_item(gchar const *urn, bool stock, SPDocument *stock_doc)
TODO: insert short description here.
SPStyle - a style object for SPItem objects.
TODO: insert short description here.
struct _GtkListStore GtkListStore