Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
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
39
40void gr_get_usage_counts(SPDocument *doc, std::map<SPGradient *, gint> *mapUsageCount );
41unsigned long sp_gradient_to_hhssll(SPGradient *gr);
42
43// TODO FIXME kill these globals!!!
44static Glib::ustring const prefs_path = "/dialogs/gradienteditor/";
45
46namespace Inkscape {
47namespace UI {
48namespace Widget {
49
51{
53 _store = Gtk::ListStore::create(*_columns);
54 set_orientation(Gtk::Orientation::VERTICAL);
55
56 if (doc) {
57 set_gradient(doc, gr);
58 } else {
60 }
61}
62
64{
65// g_message("sp_gradient_vector_selector_set_gradient(%p, %p, %p) [%s] %d %d", gvs, doc, gr,
66// (gr ? gr->getId():"N/A"),
67// (gr ? gr->isSwatch() : -1),
68// (gr ? gr->isSolid() : -1));
69 static gboolean suppress = FALSE;
70
71 g_return_if_fail(!gr || (doc != nullptr));
72 g_return_if_fail(!gr || (gr->document == doc));
73 g_return_if_fail(!gr || gr->hasStops());
74
75 if (doc != _doc) {
76 /* Disconnect signals */
77 if (_gr) {
79 _gr = nullptr;
80 }
81 if (_doc) {
82 _defs_release_connection.disconnect();
83 _defs_modified_connection.disconnect();
84 _doc = nullptr;
85 }
86
87 // Connect signals
88 if (doc) {
91 }
92 if (gr) {
94 }
95 _doc = doc;
96 _gr = gr;
98 if (!suppress) _signal_vector_set.emit(gr);
99 } else if (gr != _gr) {
100 // Harder case - keep document, rebuild list and stuff
101 // fixme: (Lauris)
102 suppress = TRUE;
103 set_gradient(nullptr, nullptr);
104 set_gradient(doc, gr);
105 suppress = FALSE;
106 _signal_vector_set.emit(gr);
107 }
108 /* The case of setting NULL -> NULL is not very interesting */
109}
110
111void
113{
114 /* Disconnect gradient */
115 if (_gr) {
116 _gradient_release_connection.disconnect();
117 _gr = nullptr;
118 }
119
120 /* Rebuild GUI */
122}
123
124void
126{
127 _doc = nullptr;
128
129 _defs_release_connection.disconnect();
130 _defs_modified_connection.disconnect();
131
132 /* Disconnect gradient as well */
133 if (_gr) {
134 _gradient_release_connection.disconnect();
135 _gr = nullptr;
136 }
137
138 /* Rebuild GUI */
140}
141
142void
144{
145 /* fixme: We probably have to check some flags here (Lauris) */
147}
148
149void
151{
153
154 /* Clear old list, if there is any */
155 _store->clear();
156
157 /* Pick up all gradients with vectors */
158 std::vector<SPGradient *> gl;
159 if (_gr) {
160 auto gradients = _gr->document->getResourceList("gradient");
161 for (auto gradient : gradients) {
162 auto grad = cast<SPGradient>(gradient);
163 if ( grad->hasStops() && (grad->isSwatch() == _swatched) ) {
164 gl.push_back(cast<SPGradient>(gradient));
165 }
166 }
167 }
168
169 /* Get usage count of all the gradients */
170 std::map<SPGradient *, gint> usageCount;
171 gr_get_usage_counts(_doc, &usageCount);
172
173 if (!_doc) {
174 Gtk::TreeModel::Row row = *(_store->append());
175 row[_columns->name] = _("No document selected");
176
177 } else if (gl.empty()) {
178 Gtk::TreeModel::Row row = *(_store->append());
179 row[_columns->name] = _("No gradients in document");
180
181 } else if (!_gr) {
182 Gtk::TreeModel::Row row = *(_store->append());
183 row[_columns->name] = _("No gradient selected");
184
185 } else {
186 for (auto gr:gl) {
187 unsigned long hhssll = sp_gradient_to_hhssll(gr);
189 Glib::ustring label = gr_prepare_label(gr);
190
191 Gtk::TreeModel::Row row = *(_store->append());
192 row[_columns->name] = label.c_str();
193 row[_columns->color] = hhssll;
194 row[_columns->refcount] = usageCount[gr];
195 row[_columns->data] = gr;
196 row[_columns->pixbuf] = Glib::wrap(pixb);
197 }
198 }
199
200 _tree_select_connection.unblock();
201}
202
203void
209
214
215} // namespace Widget
216} // namespace UI
217} // namespace Inkscape
218
219Glib::ustring gr_prepare_label(SPObject *obj)
220{
221 const gchar *id = obj->label() ? obj->label() : obj->getId();
222 if (!id) {
223 id = obj->getRepr()->name();
224 }
225
226 if (strlen(id) > 14 && (!strncmp (id, "linearGradient", 14) || !strncmp (id, "radialGradient", 14)))
227 return gr_ellipsize_text(id+14, 35);
228 return gr_ellipsize_text (id, 35);
229}
230
231/*
232 * Ellipse text if longer than maxlen, "50% start text + ... + ~50% end text"
233 * Text should be > length 8 or just return the original text
234 */
235Glib::ustring gr_ellipsize_text(Glib::ustring const &src, size_t maxlen)
236{
237 if (src.length() > maxlen && maxlen > 8) {
238 size_t p1 = (size_t) maxlen / 2;
239 size_t p2 = (size_t) src.length() - (maxlen - p1 - 1);
240 return src.substr(0, p1) + "…" + src.substr(p2);
241 }
242 return src;
243}
244
245
246/*
247 * Return a "HHSSLL" version of the first stop color so we can sort by it
248 */
250{
251 auto hsl = gr->getFirstStop()->getColor();
253 return ((int)(hsl[0]*100 * 10000)) + ((int)(hsl[1]*100 * 100)) + ((int)(hsl[2]*100 * 1));
254}
255
256/*
257 * Map each gradient to its usage count for both fill and stroke styles
258 */
259void gr_get_usage_counts(SPDocument *doc, std::map<SPGradient *, gint> *mapUsageCount )
260{
261 if (!doc)
262 return;
263
264 for (auto item : sp_get_all_document_items(doc)) {
265 if (!item->getId())
266 continue;
267 SPGradient *gr = nullptr;
268 gr = sp_item_get_gradient(item, true); // fill
269 if (gr) {
270 mapUsageCount->count(gr) > 0 ? (*mapUsageCount)[gr] += 1 : (*mapUsageCount)[gr] = 1;
271 }
272 gr = sp_item_get_gradient(item, false); // stroke
273 if (gr) {
274 mapUsageCount->count(gr) > 0 ? (*mapUsageCount)[gr] += 1 : (*mapUsageCount)[gr] = 1;
275 }
276 }
277}
278
279/*
280 Local Variables:
281 mode:c++
282 c-file-style:"stroustrup"
283 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
284 indent-tabs-mode:nil
285 fill-column:99
286 End:
287*/
288// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
struct _GdkPixbuf GdkPixbuf
Definition cairo-utils.h:20
bool convert(Color const &other)
Convert to the same format as the other color.
Definition color.cpp:145
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.
Typed SVG document implementation.
Definition document.h:101
std::vector< SPObject * > const getResourceList(char const *key)
SPDefs * getDefs()
Return the main defs object for the document.
Definition document.cpp:247
Gradient.
Definition sp-gradient.h:86
SPStop * getFirstStop()
bool hasStops() const
SPObject is an abstract base class of all of the document nodes at the SVG document level.
Definition sp-object.h:160
char const * label() const
Gets the author-visible label property for the object or a default if no label is defined.
SPDocument * document
Definition sp-object.h:188
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
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
sigc::connection connectModified(sigc::slot< void(SPObject *, unsigned int)> slot)
Connects to the modification notification signal.
Definition sp-object.h:705
Inkscape::Colors::Color getColor() const
Definition sp-stop.cpp:130
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
Glib::ustring label
static constexpr int height
Helper class to stream background task notifications as a series of messages.
Singleton class to access the preferences file in a convenient way.
TODO: insert short description here.
double width