Inkscape
Vector Graphics Editor
gradient-vector-selector.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Gradient vector selection widget
4 *
5 * Authors:
6 * Lauris Kaplinski <lauris@kaplinski.com>
7 * bulia byak <buliabyak@users.sf.net>
8 * MenTaLguY <mental@rydia.net>
9 * Jon A. Cruz <jon@joncruz.org>
10 * Abhishek Sharma
11 *
12 * Copyright (C) 2001-2002 Lauris Kaplinski
13 * Copyright (C) 2001 Ximian, Inc.
14 * Copyright (C) 2004 Monash University
15 * Copyright (C) 2004 David Turner
16 * Copyright (C) 2006 MenTaLguY
17 * Copyright (C) 2010 Jon A. Cruz
18 *
19 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
20 *
21 */
22
24
25#include <set>
26
27#include <glibmm.h>
28#include <glibmm/i18n.h>
29#include <gdkmm/pixbuf.h>
30
31#include "document.h"
32#include "gradient-chemistry.h"
33#include "preferences.h"
34
35#include "object/sp-defs.h"
36#include "object/sp-stop.h"
37
38#include "ui/selected-color.h"
40
42
43void gr_get_usage_counts(SPDocument *doc, std::map<SPGradient *, gint> *mapUsageCount );
44unsigned long sp_gradient_to_hhssll(SPGradient *gr);
45
46// TODO FIXME kill these globals!!!
47static Glib::ustring const prefs_path = "/dialogs/gradienteditor/";
48
49namespace Inkscape {
50namespace UI {
51namespace Widget {
52
54{
57 set_orientation(Gtk::Orientation::VERTICAL);
58
59 if (doc) {
60 set_gradient(doc, gr);
61 } else {
63 }
64}
65
67{
68// g_message("sp_gradient_vector_selector_set_gradient(%p, %p, %p) [%s] %d %d", gvs, doc, gr,
69// (gr ? gr->getId():"N/A"),
70// (gr ? gr->isSwatch() : -1),
71// (gr ? gr->isSolid() : -1));
72 static gboolean suppress = FALSE;
73
74 g_return_if_fail(!gr || (doc != nullptr));
75 g_return_if_fail(!gr || (gr->document == doc));
76 g_return_if_fail(!gr || gr->hasStops());
77
78 if (doc != _doc) {
79 /* Disconnect signals */
80 if (_gr) {
82 _gr = nullptr;
83 }
84 if (_doc) {
87 _doc = nullptr;
88 }
89
90 // Connect signals
91 if (doc) {
94 }
95 if (gr) {
97 }
98 _doc = doc;
99 _gr = gr;
101 if (!suppress) _signal_vector_set.emit(gr);
102 } else if (gr != _gr) {
103 // Harder case - keep document, rebuild list and stuff
104 // fixme: (Lauris)
105 suppress = TRUE;
106 set_gradient(nullptr, nullptr);
107 set_gradient(doc, gr);
108 suppress = FALSE;
109 _signal_vector_set.emit(gr);
110 }
111 /* The case of setting NULL -> NULL is not very interesting */
112}
113
114void
116{
117 /* Disconnect gradient */
118 if (_gr) {
120 _gr = nullptr;
121 }
122
123 /* Rebuild GUI */
125}
126
127void
129{
130 _doc = nullptr;
131
134
135 /* Disconnect gradient as well */
136 if (_gr) {
138 _gr = nullptr;
139 }
140
141 /* Rebuild GUI */
143}
144
145void
147{
148 /* fixme: We probably have to check some flags here (Lauris) */
150}
151
152void
154{
156
157 /* Clear old list, if there is any */
158 _store->clear();
159
160 /* Pick up all gradients with vectors */
161 std::vector<SPGradient *> gl;
162 if (_gr) {
163 auto gradients = _gr->document->getResourceList("gradient");
164 for (auto gradient : gradients) {
165 auto grad = cast<SPGradient>(gradient);
166 if ( grad->hasStops() && (grad->isSwatch() == _swatched) ) {
167 gl.push_back(cast<SPGradient>(gradient));
168 }
169 }
170 }
171
172 /* Get usage count of all the gradients */
173 std::map<SPGradient *, gint> usageCount;
174 gr_get_usage_counts(_doc, &usageCount);
175
176 if (!_doc) {
177 Gtk::TreeModel::Row row = *(_store->append());
178 row[_columns->name] = _("No document selected");
179
180 } else if (gl.empty()) {
181 Gtk::TreeModel::Row row = *(_store->append());
182 row[_columns->name] = _("No gradients in document");
183
184 } else if (!_gr) {
185 Gtk::TreeModel::Row row = *(_store->append());
186 row[_columns->name] = _("No gradient selected");
187
188 } else {
189 for (auto gr:gl) {
190 unsigned long hhssll = sp_gradient_to_hhssll(gr);
192 Glib::ustring label = gr_prepare_label(gr);
193
194 Gtk::TreeModel::Row row = *(_store->append());
195 row[_columns->name] = label.c_str();
196 row[_columns->color] = hhssll;
197 row[_columns->refcount] = usageCount[gr];
198 row[_columns->data] = gr;
199 row[_columns->pixbuf] = Glib::wrap(pixb);
200 }
201 }
202
204}
205
206void
208{
209 _swatched = true;
211}
212
216}
217
218} // namespace Widget
219} // namespace UI
220} // namespace Inkscape
221
222Glib::ustring gr_prepare_label(SPObject *obj)
223{
224 const gchar *id = obj->label() ? obj->label() : obj->getId();
225 if (!id) {
226 id = obj->getRepr()->name();
227 }
228
229 if (strlen(id) > 14 && (!strncmp (id, "linearGradient", 14) || !strncmp (id, "radialGradient", 14)))
230 return gr_ellipsize_text(id+14, 35);
231 return gr_ellipsize_text (id, 35);
232}
233
234/*
235 * Ellipse text if longer than maxlen, "50% start text + ... + ~50% end text"
236 * Text should be > length 8 or just return the original text
237 */
238Glib::ustring gr_ellipsize_text(Glib::ustring const &src, size_t maxlen)
239{
240 if (src.length() > maxlen && maxlen > 8) {
241 size_t p1 = (size_t) maxlen / 2;
242 size_t p2 = (size_t) src.length() - (maxlen - p1 - 1);
243 return src.substr(0, p1) + "…" + src.substr(p2);
244 }
245 return src;
246}
247
248
249/*
250 * Return a "HHSSLL" version of the first stop color so we can sort by it
251 */
253{
254 SPStop *stop = gr->getFirstStop();
255 unsigned long rgba = stop->get_rgba32();
256 float hsl[3];
257 SPColor::rgb_to_hsl_floatv (hsl, SP_RGBA32_R_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_B_F(rgba));
258
259 return ((int)(hsl[0]*100 * 10000)) + ((int)(hsl[1]*100 * 100)) + ((int)(hsl[2]*100 * 1));
260}
261
262/*
263 * Map each gradient to its usage count for both fill and stroke styles
264 */
265void gr_get_usage_counts(SPDocument *doc, std::map<SPGradient *, gint> *mapUsageCount )
266{
267 if (!doc)
268 return;
269
270 for (auto item : sp_get_all_document_items(doc)) {
271 if (!item->getId())
272 continue;
273 SPGradient *gr = nullptr;
274 gr = sp_item_get_gradient(item, true); // fill
275 if (gr) {
276 mapUsageCount->count(gr) > 0 ? (*mapUsageCount)[gr] += 1 : (*mapUsageCount)[gr] = 1;
277 }
278 gr = sp_item_get_gradient(item, false); // stroke
279 if (gr) {
280 mapUsageCount->count(gr) > 0 ? (*mapUsageCount)[gr] += 1 : (*mapUsageCount)[gr] = 1;
281 }
282 }
283}
284
285/*
286 Local Variables:
287 mode:c++
288 c-file-style:"stroustrup"
289 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
290 indent-tabs-mode:nil
291 fill-column:99
292 End:
293*/
294// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
struct _GdkPixbuf GdkPixbuf
Definition: cairo-utils.h:21
Gtk::TreeModelColumn< Glib::ustring > name
Gtk::TreeModelColumn< unsigned long > color
Gtk::TreeModelColumn< Glib::RefPtr< Gdk::Pixbuf > > pixbuf
sigc::signal< void(SPGradient *)> _signal_vector_set
GradientVectorSelector(SPDocument *doc, SPGradient *gradient)
void set_gradient(SPDocument *doc, SPGradient *gr)
Inkscape::UI::Widget::GradientSelector::ModelColumns * _columns
virtual char const * name() const =0
Get the name of the element node.
bool block(bool should_block=true) noexcept
Sets or unsets the blocking state of this connection.
static void rgb_to_hsl_floatv(float *hsl, float r, float g, float b)
Fill hsl float array from r,g,b float values.
Definition: color.cpp:413
Typed SVG document implementation.
Definition: document.h:106
std::vector< SPObject * > const getResourceList(char const *key)
Definition: document.cpp:1900
SPDefs * getDefs()
Return the main defs object for the document.
Definition: document.cpp:259
Gradient.
Definition: sp-gradient.h:86
SPStop * getFirstStop()
bool hasStops() const
Definition: sp-gradient.cpp:59
SPObject is an abstract base class of all of the document nodes at the SVG document level.
Definition: sp-object.h:146
char const * label() const
Gets the author-visible label property for the object or a default if no label is defined.
Definition: sp-object.cpp:428
SPDocument * document
Definition: sp-object.h:174
char const * getId() const
Returns the objects current ID string.
Definition: sp-object.cpp:206
sigc::connection connectRelease(sigc::slot< void(SPObject *)> slot)
Connects to the release request signal.
Definition: sp-object.h:223
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
Definition: sp-object.cpp:232
sigc::connection connectModified(sigc::slot< void(SPObject *, unsigned int)> slot)
Connects to the modification notification signal.
Definition: sp-object.h:691
Gradient stop.
Definition: sp-stop.h:28
guint32 get_rgba32() const
Return stop's color as 32bit value.
Definition: sp-stop.cpp:165
std::vector< SPItem * > sp_get_all_document_items(SPDocument *document)
SPGradient * sp_item_get_gradient(SPItem *item, bool fillorstroke)
GdkPixbuf * sp_gradient_to_pixbuf(SPGradient *gr, int width, int height)
Glib::ustring gr_ellipsize_text(Glib::ustring const &src, size_t maxlen)
Glib::ustring gr_prepare_label(SPObject *obj)
static Glib::ustring const prefs_path
void gr_get_usage_counts(SPDocument *doc, std::map< SPGradient *, gint > *mapUsageCount)
unsigned long sp_gradient_to_hhssll(SPGradient *gr)
SPItem * item
Definition: imagemagick.cpp:43
static constexpr int height
CMYK to sRGB conversion routines.
@ VERTICAL
The y-dimension (1).
Definition: rectangle.h:47
Singleton class to access the preferences file in a convenient way.
Color selected in color selector widget.
TODO: insert short description here.
double width
std::unique_ptr< Toolbar >(* create)(SPDesktop *desktop)
Definition: toolbars.cpp:63