gradient-vector.cpp revision d2e42b9425ccd4c2d4c20c2217455da177035e48
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler/*
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Gradient vector selection widget
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler *
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Authors:
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Lauris Kaplinski <lauris@kaplinski.com>
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * bulia byak <buliabyak@users.sf.net>
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * MenTaLguY <mental@rydia.net>
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Jon A. Cruz <jon@joncruz.org>
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Abhishek Sharma
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler *
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Copyright (C) 2001-2002 Lauris Kaplinski
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Copyright (C) 2001 Ximian, Inc.
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Copyright (C) 2004 Monash University
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Copyright (C) 2004 David Turner
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Copyright (C) 2006 MenTaLguY
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Copyright (C) 2010 Jon A. Cruz
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler *
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Released under GNU GPL, read the file 'COPYING' for more information
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler *
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#ifdef HAVE_CONFIG_H
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler# include "config.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#endif
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include <glibmm.h>
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "gradient-vector.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "ui/widget/color-preview.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "verbs.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include <gtk/gtk.h>
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "macros.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include <glibmm/i18n.h>
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include <set>
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "widgets/gradient-image.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "inkscape.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "document-private.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "gradient-chemistry.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "helper/window.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "io/resource.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "xml/repr.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "ui/dialog-events.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "preferences.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "svg/css-ostringstream.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "sp-stop.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "selection-chemistry.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "style.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "sp-linear-gradient.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "sp-radial-gradient.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "desktop.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "layer-manager.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include <sigc++/sigc++.h>
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "document-undo.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerusing Inkscape::DocumentUndo;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerenum {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler VECTOR_SET,
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler LAST_SIGNAL
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler};
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#if GTK_CHECK_VERSION(3,0,0)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gradient_vector_selector_destroy(GtkWidget *object);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#else
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gradient_vector_selector_destroy(GtkObject *object);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#endif
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gvs_gradient_release(SPObject *obj, SPGradientVectorSelector *gvs);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gvs_defs_release(SPObject *defs, SPGradientVectorSelector *gvs);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gvs_defs_modified(SPObject *defs, guint flags, SPGradientVectorSelector *gvs);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic SPStop *get_selected_stop( GtkWidget *vb);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlervoid gr_get_usage_counts(SPDocument *doc, std::map<SPGradient *, gint> *mapUsageCount );
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerunsigned long sp_gradient_to_hhssll(SPGradient *gr);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic guint signals[LAST_SIGNAL] = {0};
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler// TODO FIXME kill these globals!!!
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic GtkWidget *dlg = NULL;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic win_data wd;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic gint x = -1000, y = -1000, w = 0, h = 0; // impossible original values to make sure they are read from prefs
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic Glib::ustring const prefs_path = "/dialogs/gradienteditor/";
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#if GTK_CHECK_VERSION(3,0,0)
f6df6236fcf18524e049bba12b69704af32eff90Josh AndlerG_DEFINE_TYPE(SPGradientVectorSelector, sp_gradient_vector_selector, GTK_TYPE_BOX);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#else
f6df6236fcf18524e049bba12b69704af32eff90Josh AndlerG_DEFINE_TYPE(SPGradientVectorSelector, sp_gradient_vector_selector, GTK_TYPE_VBOX);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#endif
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gradient_vector_selector_class_init(SPGradientVectorSelectorClass *klass)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler signals[VECTOR_SET] = g_signal_new( "vector_set",
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler G_TYPE_FROM_CLASS(gobject_class),
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler G_SIGNAL_RUN_LAST,
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler G_STRUCT_OFFSET(SPGradientVectorSelectorClass, vector_set),
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler NULL, NULL,
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler g_cclosure_marshal_VOID__POINTER,
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler G_TYPE_NONE, 1,
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler G_TYPE_POINTER);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#if GTK_CHECK_VERSION(3,0,0)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler widget_class->destroy = sp_gradient_vector_selector_destroy;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#else
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler GtkObjectClass *object_class = GTK_OBJECT_CLASS(klass);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler object_class->destroy = sp_gradient_vector_selector_destroy;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#endif
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gradient_vector_selector_init(SPGradientVectorSelector *gvs)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#if GTK_CHECK_VERSION(3,0,0)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gtk_orientable_set_orientation(GTK_ORIENTABLE(gvs), GTK_ORIENTATION_VERTICAL);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#endif
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->idlabel = TRUE;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->swatched = false;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->doc = NULL;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->gr = NULL;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler new (&gvs->gradient_release_connection) sigc::connection();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler new (&gvs->defs_release_connection) sigc::connection();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler new (&gvs->defs_modified_connection) sigc::connection();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->columns = new SPGradientSelector::ModelColumns();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->store = Gtk::ListStore::create(*gvs->columns);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler new (&gvs->tree_select_connection) sigc::connection();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#if GTK_CHECK_VERSION(3,0,0)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gradient_vector_selector_destroy(GtkWidget *object)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#else
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gradient_vector_selector_destroy(GtkObject *object)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#endif
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler SPGradientVectorSelector *gvs = SP_GRADIENT_VECTOR_SELECTOR(object);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (gvs->gr) {
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski gvs->gradient_release_connection.disconnect();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->tree_select_connection.disconnect();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->gr = NULL;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (gvs->doc) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->defs_release_connection.disconnect();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->defs_modified_connection.disconnect();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->doc = NULL;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->gradient_release_connection.~connection();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->defs_release_connection.~connection();
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski gvs->defs_modified_connection.~connection();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->tree_select_connection.~connection();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#if GTK_CHECK_VERSION(3,0,0)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if ((GTK_WIDGET_CLASS(sp_gradient_vector_selector_parent_class))->destroy) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler (GTK_WIDGET_CLASS(sp_gradient_vector_selector_parent_class))->destroy(object);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#else
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if ((GTK_OBJECT_CLASS(sp_gradient_vector_selector_parent_class))->destroy) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler (GTK_OBJECT_CLASS(sp_gradient_vector_selector_parent_class))->destroy(object);
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski }
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski#endif
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
7bda77e763c0af49270427593108b66455dfd125Krzysztof KosinskiGtkWidget *sp_gradient_vector_selector_new(SPDocument *doc, SPGradient *gr)
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler GtkWidget *gvs;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler g_return_val_if_fail(!gr || SP_IS_GRADIENT(gr), NULL);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler g_return_val_if_fail(!gr || (gr->document == doc), NULL);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs = static_cast<GtkWidget*>(g_object_new(SP_TYPE_GRADIENT_VECTOR_SELECTOR, NULL));
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (doc) {
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski sp_gradient_vector_selector_set_gradient(SP_GRADIENT_VECTOR_SELECTOR(gvs), doc, gr);
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski } else {
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski sp_gvs_rebuild_gui_full(SP_GRADIENT_VECTOR_SELECTOR(gvs));
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski return gvs;
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski}
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinskivoid sp_gradient_vector_selector_set_gradient(SPGradientVectorSelector *gvs, SPDocument *doc, SPGradient *gr)
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler// g_message("sp_gradient_vector_selector_set_gradient(%p, %p, %p) [%s] %d %d", gvs, doc, gr,
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler// (gr ? gr->getId():"N/A"),
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler// (gr ? gr->isSwatch() : -1),
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler// (gr ? gr->isSolid() : -1));
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler static gboolean suppress = FALSE;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler g_return_if_fail(gvs != NULL);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler g_return_if_fail(SP_IS_GRADIENT_VECTOR_SELECTOR(gvs));
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler g_return_if_fail(!gr || (doc != NULL));
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler g_return_if_fail(!gr || SP_IS_GRADIENT(gr));
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler g_return_if_fail(!gr || (gr->document == doc));
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler g_return_if_fail(!gr || gr->hasStops());
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (doc != gvs->doc) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler /* Disconnect signals */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (gvs->gr) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->gradient_release_connection.disconnect();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->gr = NULL;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (gvs->doc) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->defs_release_connection.disconnect();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->defs_modified_connection.disconnect();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->doc = NULL;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler // Connect signals
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (doc) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->defs_release_connection = doc->getDefs()->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_gvs_defs_release), gvs));
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->defs_modified_connection = doc->getDefs()->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_gvs_defs_modified), gvs));
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (gr) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->gradient_release_connection = gr->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_gvs_gradient_release), gvs));
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->doc = doc;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->gr = gr;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler sp_gvs_rebuild_gui_full(gvs);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (!suppress) g_signal_emit(G_OBJECT(gvs), signals[VECTOR_SET], 0, gr);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler } else if (gr != gvs->gr) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler // Harder case - keep document, rebuild list and stuff
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler // fixme: (Lauris)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler suppress = TRUE;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler sp_gradient_vector_selector_set_gradient(gvs, NULL, NULL);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler sp_gradient_vector_selector_set_gradient(gvs, doc, gr);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler suppress = FALSE;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler g_signal_emit(G_OBJECT(gvs), signals[VECTOR_SET], 0, gr);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler /* The case of setting NULL -> NULL is not very interesting */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh AndlerSPDocument *sp_gradient_vector_selector_get_document(SPGradientVectorSelector *gvs)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler g_return_val_if_fail(gvs != NULL, NULL);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler g_return_val_if_fail(SP_IS_GRADIENT_VECTOR_SELECTOR(gvs), NULL);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler return gvs->doc;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh AndlerSPGradient *sp_gradient_vector_selector_get_gradient(SPGradientVectorSelector *gvs)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler g_return_val_if_fail(gvs != NULL, NULL);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler g_return_val_if_fail(SP_IS_GRADIENT_VECTOR_SELECTOR(gvs), NULL);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler return gvs->gr;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh AndlerGlib::ustring gr_prepare_label (SPObject *obj)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler const gchar *id = obj->label() ? obj->label() : obj->getId();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (!id) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler id = obj->getRepr()->name();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (strlen(id) > 14 && (!strncmp (id, "linearGradient", 14) || !strncmp (id, "radialGradient", 14)))
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler return gr_ellipsize_text (g_strdup_printf ("%s", id+14), 35);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler return gr_ellipsize_text (id, 35);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler/*
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Ellipse text if longer than maxlen, "50% start text + ... + ~50% end text"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Text should be > length 8 or just return the original text
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler */
f6df6236fcf18524e049bba12b69704af32eff90Josh AndlerGlib::ustring gr_ellipsize_text(Glib::ustring const &src, size_t maxlen)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski if (src.length() > maxlen && maxlen > 8) {
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski size_t p1 = (size_t) maxlen / 2;
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski size_t p2 = (size_t) src.length() - (maxlen - p1 - 1);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler return src.substr(0, p1) + "…" + src.substr(p2);
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler return src;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->tree_select_connection.block();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler /* Clear old list, if there is any */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->store->clear();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler /* Pick up all gradients with vectors */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler GSList *gl = NULL;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (gvs->gr) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler const GSList *gradients = gvs->gr->document->getResourceList("gradient");
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler for (const GSList *curr = gradients; curr; curr = curr->next) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler SPGradient* grad = SP_GRADIENT(curr->data);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if ( grad->hasStops() && (grad->isSwatch() == gvs->swatched) ) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gl = g_slist_prepend(gl, curr->data);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski }
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski gl = g_slist_reverse(gl);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler /* Get usage count of all the gradients */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler std::map<SPGradient *, gint> usageCount;
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski gr_get_usage_counts(gvs->doc, &usageCount);
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski if (!gvs->doc) {
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski Gtk::TreeModel::Row row = *(gvs->store->append());
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski row[gvs->columns->name] = _("No document selected");
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski } else if (!gl) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler Gtk::TreeModel::Row row = *(gvs->store->append());
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler row[gvs->columns->name] = _("No gradients in document");
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski } else if (!gvs->gr) {
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski Gtk::TreeModel::Row row = *(gvs->store->append());
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler row[gvs->columns->name] = _("No gradient selected");
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler } else {
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski while (gl) {
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski SPGradient *gr;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gr = SP_GRADIENT(gl->data);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gl = g_slist_remove(gl, gr);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler unsigned long hhssll = sp_gradient_to_hhssll(gr);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler GdkPixbuf *pixb = sp_gradient_to_pixbuf (gr, 64, 18);
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski Glib::ustring label = gr_prepare_label(gr);
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski Gtk::TreeModel::Row row = *(gvs->store->append());
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski row[gvs->columns->name] = label.c_str();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler row[gvs->columns->color] = hhssll;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler row[gvs->columns->refcount] = usageCount[gr];
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler row[gvs->columns->data] = gr;
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski row[gvs->columns->pixbuf] = Glib::wrap(pixb);
7bda77e763c0af49270427593108b66455dfd125Krzysztof Kosinski
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->tree_select_connection.unblock();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler/*
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Return a "HHSSLL" version of the first stop color so we can sort by it
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerunsigned long sp_gradient_to_hhssll(SPGradient *gr)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler SPStop *stop = gr->getFirstStop();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler unsigned long rgba = stop->get_rgba32();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler float hsl[3];
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler sp_color_rgb_to_hsl_floatv (hsl, SP_RGBA32_R_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_B_F(rgba));
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler return ((int)(hsl[0]*100 * 10000)) + ((int)(hsl[1]*100 * 100)) + ((int)(hsl[2]*100 * 1));
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic GSList *get_all_doc_items(GSList *list, SPObject *from, bool onlyvisible, bool onlysensitive, bool ingroups, GSList const *exclude)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler for ( SPObject *child = from->firstChild() ; child; child = child->getNext() ) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (SP_IS_ITEM(child)) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler list = g_slist_prepend(list, SP_ITEM(child));
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (ingroups || SP_IS_ITEM(child)) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler list = get_all_doc_items(list, child, onlyvisible, onlysensitive, ingroups, exclude);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler return list;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler/*
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Return a SPItem's gradient
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic SPGradient * gr_item_get_gradient(SPItem *item, gboolean fillorstroke)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler SPIPaint *item_paint = (fillorstroke) ? &(item->style->fill) : &(item->style->stroke);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (item_paint->isPaintserver()) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler SPPaintServer *item_server = (fillorstroke) ?
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler item->style->getFillPaintServer() : item->style->getStrokePaintServer();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (SP_IS_LINEARGRADIENT(item_server) || SP_IS_RADIALGRADIENT(item_server) ||
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler (SP_IS_GRADIENT(item_server) && SP_GRADIENT(item_server)->getVector()->isSwatch())) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler return SP_GRADIENT(item_server)->getVector();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler return NULL;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler/*
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler * Map each gradient to its usage count for both fill and stroke styles
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlervoid gr_get_usage_counts(SPDocument *doc, std::map<SPGradient *, gint> *mapUsageCount )
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (!doc)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler return;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler Inkscape::Preferences *prefs = Inkscape::Preferences::get();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true);
40742313779ee5e43be93a9191f1c86412cf183bKrzysztof Kosiński bool ingroups = TRUE;
40742313779ee5e43be93a9191f1c86412cf183bKrzysztof Kosiński
40742313779ee5e43be93a9191f1c86412cf183bKrzysztof Kosiński GSList *all_list = get_all_doc_items(NULL, doc->getRoot(), onlyvisible, onlysensitive, ingroups, NULL);
40742313779ee5e43be93a9191f1c86412cf183bKrzysztof Kosiński
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler for (GSList *i = all_list; i != NULL; i = i->next) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler SPItem *item = SP_ITEM(i->data);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (!item->getId())
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler continue;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler SPGradient *gr = NULL;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gr = gr_item_get_gradient(item, true); // fill
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (gr) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler mapUsageCount->count(gr) > 0 ? (*mapUsageCount)[gr] += 1 : (*mapUsageCount)[gr] = 1;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gr = gr_item_get_gradient(item, false); // stroke
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (gr) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler mapUsageCount->count(gr) > 0 ? (*mapUsageCount)[gr] += 1 : (*mapUsageCount)[gr] = 1;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gvs_gradient_release(SPObject */*obj*/, SPGradientVectorSelector *gvs)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler /* Disconnect gradient */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (gvs->gr) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->gradient_release_connection.disconnect();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->gr = NULL;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler /* Rebuild GUI */
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński sp_gvs_rebuild_gui_full(gvs);
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński}
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gvs_defs_release(SPObject */*defs*/, SPGradientVectorSelector *gvs)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->doc = NULL;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->defs_release_connection.disconnect();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->defs_modified_connection.disconnect();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler /* Disconnect gradient as well */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler if (gvs->gr) {
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->gradient_release_connection.disconnect();
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler gvs->gr = NULL;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler }
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler /* Rebuild GUI */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler sp_gvs_rebuild_gui_full(gvs);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gvs_defs_modified(SPObject */*defs*/, guint /*flags*/, SPGradientVectorSelector *gvs)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler /* fixme: We probably have to check some flags here (Lauris) */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler sp_gvs_rebuild_gui_full(gvs);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlervoid SPGradientVectorSelector::setSwatched()
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler swatched = true;
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler sp_gvs_rebuild_gui_full(this);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler/*##################################################################
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler ### Vector Editing Widget
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler ##################################################################*/
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "widgets/sp-color-notebook.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "widgets/widget-sizes.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "xml/node-event-vector.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#include "svg/svg-color.h"
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#define PAD 4
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic GtkWidget *sp_gradient_vector_widget_new(SPGradient *gradient, SPStop *stop);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gradient_vector_widget_load_gradient(GtkWidget *widget, SPGradient *gradient);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic gint sp_gradient_vector_dialog_delete(GtkWidget *widget, GdkEvent *event, GtkWidget *dialog);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#if GTK_CHECK_VERSION(3,0,0)
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gradient_vector_dialog_destroy(GtkWidget *object, gpointer data);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gradient_vector_widget_destroy(GtkWidget *object, gpointer data);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#else
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gradient_vector_dialog_destroy(GtkObject *object, gpointer data);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gradient_vector_widget_destroy(GtkObject *object, gpointer data);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler#endif
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gradient_vector_gradient_release(SPObject *obj, GtkWidget *widget);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gradient_vector_gradient_modified(SPObject *obj, guint flags, GtkWidget *widget);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gradient_vector_color_dragged(SPColorSelector *csel, GObject *object);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void sp_gradient_vector_color_changed(SPColorSelector *csel, GObject *object);
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic void update_stop_list( GtkWidget *vb, SPGradient *gradient, SPStop *new_stop);
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosińskistatic gboolean blocked = FALSE;
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosińskistatic void grad_edit_dia_stop_added_or_removed(Inkscape::XML::Node */*repr*/, Inkscape::XML::Node */*child*/, Inkscape::XML::Node */*ref*/, gpointer data)
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński{
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński GtkWidget *vb = GTK_WIDGET(data);
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński SPGradient *gradient = static_cast<SPGradient *>(g_object_get_data(G_OBJECT(vb), "gradient"));
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński update_stop_list(vb, gradient, NULL);
d1bde559850436556ebee2e70e10f1cfc8aff636Krzysztof Kosiński}
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler//FIXME!!! We must also listen to attr changes on all children (i.e. stops) too,
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler//otherwise the dialog does not reflect undoing color or offset change. This is a major
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler//hassle, unless we have a "one of the descendants changed in some way" signal.
f6df6236fcf18524e049bba12b69704af32eff90Josh Andlerstatic Inkscape::XML::NodeEventVector grad_edit_dia_repr_events =
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler{
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler grad_edit_dia_stop_added_or_removed, /* child_added */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler grad_edit_dia_stop_added_or_removed, /* child_removed */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler NULL, /* attr_changed*/
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler NULL, /* content_changed */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler NULL /* order_changed */
f6df6236fcf18524e049bba12b69704af32eff90Josh Andler};
static void verify_grad(SPGradient *gradient)
{
int i = 0;
SPStop *stop = NULL;
/* count stops */
for ( SPObject *ochild = gradient->firstChild() ; ochild ; ochild = ochild->getNext() ) {
if (SP_IS_STOP(ochild)) {
i++;
stop = SP_STOP(ochild);
}
}
Inkscape::XML::Document *xml_doc;
xml_doc = gradient->getRepr()->document();
if (i < 1) {
Inkscape::CSSOStringStream os;
os << "stop-color: #000000;stop-opacity:" << 1.0 << ";";
Inkscape::XML::Node *child;
child = xml_doc->createElement("svg:stop");
sp_repr_set_css_double(child, "offset", 0.0);
child->setAttribute("style", os.str().c_str());
gradient->getRepr()->addChild(child, NULL);
Inkscape::GC::release(child);
child = xml_doc->createElement("svg:stop");
sp_repr_set_css_double(child, "offset", 1.0);
child->setAttribute("style", os.str().c_str());
gradient->getRepr()->addChild(child, NULL);
Inkscape::GC::release(child);
}
if (i < 2) {
sp_repr_set_css_double(stop->getRepr(), "offset", 0.0);
Inkscape::XML::Node *child = stop->getRepr()->duplicate(gradient->getRepr()->document());
sp_repr_set_css_double(child, "offset", 1.0);
gradient->getRepr()->addChild(child, stop->getRepr());
Inkscape::GC::release(child);
}
}
static void select_stop_in_list( GtkWidget *vb, SPGradient *gradient, SPStop *new_stop)
{
GtkWidget *combo_box = static_cast<GtkWidget *>(g_object_get_data(G_OBJECT(vb), "combo_box"));
int i = 0;
for ( SPObject *ochild = gradient->firstChild() ; ochild ; ochild = ochild->getNext() ) {
if (SP_IS_STOP(ochild)) {
if (ochild == new_stop) {
gtk_combo_box_set_active (GTK_COMBO_BOX(combo_box) , i);
break;
}
i++;
}
}
}
static void update_stop_list( GtkWidget *vb, SPGradient *gradient, SPStop *new_stop)
{
if (!SP_IS_GRADIENT(gradient)) {
return;
}
blocked = TRUE;
/* Clear old list, if there is any */
GtkWidget *combo_box = static_cast<GtkWidget *>(g_object_get_data(G_OBJECT(vb), "combo_box"));
if (!combo_box) {
return;
}
GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo_box)));
if (!store) {
return;
}
gtk_list_store_clear(store);
GtkTreeIter iter;
/* Populate the combobox store */
GSList *sl = NULL;
if ( gradient->hasStops() ) {
for ( SPObject *ochild = gradient->firstChild() ; ochild ; ochild = ochild->getNext() ) {
if (SP_IS_STOP(ochild)) {
sl = g_slist_append(sl, ochild);
}
}
}
if (!sl) {
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, NULL, 1, _("No stops in gradient"), 2, NULL, -1);
gtk_widget_set_sensitive (combo_box, FALSE);
} else {
for (; sl != NULL; sl = sl->next){
if (SP_IS_STOP(sl->data)){
SPStop *stop = SP_STOP(sl->data);
Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(sl->data)->getRepr();
Inkscape::UI::Widget::ColorPreview *cpv = Gtk::manage(new Inkscape::UI::Widget::ColorPreview(stop->get_rgba32()));
GdkPixbuf *pb = cpv->toPixbuf(64, 16);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, pb, 1, repr->attribute("id"), 2, stop, -1);
gtk_widget_set_sensitive (combo_box, FALSE);
}
}
gtk_widget_set_sensitive(combo_box, TRUE);
}
/* Set history */
if (new_stop == NULL) {
gtk_combo_box_set_active (GTK_COMBO_BOX(combo_box) , 0);
} else {
select_stop_in_list(vb, gradient, new_stop);
}
blocked = FALSE;
}
// user selected existing stop from list
static void sp_grad_edit_combo_box_changed (GtkComboBox * /*widget*/, GtkWidget *tbl)
{
SPStop *stop = get_selected_stop(tbl);
if (!stop) {
return;
}
blocked = TRUE;
SPColorSelector *csel = static_cast<SPColorSelector*>(g_object_get_data(G_OBJECT(tbl), "cselector"));
// set its color, from the stored array
csel->base->setColorAlpha( stop->getEffectiveColor(), stop->opacity );
GtkWidget *offspin = GTK_WIDGET(g_object_get_data(G_OBJECT(tbl), "offspn"));
GtkWidget *offslide =GTK_WIDGET(g_object_get_data(G_OBJECT(tbl), "offslide"));
GtkAdjustment *adj = static_cast<GtkAdjustment*>(g_object_get_data(G_OBJECT(tbl), "offset"));
bool isEndStop = false;
SPStop *prev = NULL;
prev = stop->getPrevStop();
if (prev != NULL ) {
gtk_adjustment_set_lower (adj, prev->offset);
} else {
isEndStop = true;
gtk_adjustment_set_lower (adj, 0);
}
SPStop *next = NULL;
next = stop->getNextStop();
if (next != NULL ) {
gtk_adjustment_set_upper (adj, next->offset);
} else {
isEndStop = true;
gtk_adjustment_set_upper (adj, 1.0);
}
//fixme: does this work on all possible input gradients?
if (!isEndStop) {
gtk_widget_set_sensitive(offslide, TRUE);
gtk_widget_set_sensitive(GTK_WIDGET(offspin), TRUE);
} else {
gtk_widget_set_sensitive(offslide, FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(offspin), FALSE);
}
gtk_adjustment_set_value(adj, stop->offset);
gtk_adjustment_changed(adj);
blocked = FALSE;
}
static SPStop *get_selected_stop( GtkWidget *vb)
{
SPStop *stop = NULL;
GtkWidget *combo_box = static_cast<GtkWidget *>(g_object_get_data(G_OBJECT(vb), "combo_box"));
if (combo_box) {
GtkTreeIter iter;
if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX(combo_box), &iter)) {
GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo_box)));
gtk_tree_model_get (GTK_TREE_MODEL(store), &iter, 2, &stop, -1);
}
}
return stop;
}
static void offadjustmentChanged( GtkAdjustment *adjustment, GtkWidget *vb)
{
if (!blocked) {
blocked = TRUE;
SPStop *stop = get_selected_stop(vb);
if (stop) {
stop->offset = gtk_adjustment_get_value (adjustment);
sp_repr_set_css_double(stop->getRepr(), "offset", stop->offset);
DocumentUndo::maybeDone(stop->document, "gradient:stop:offset", SP_VERB_CONTEXT_GRADIENT,
_("Change gradient stop offset"));
}
blocked = FALSE;
}
}
guint32 sp_average_color(guint32 c1, guint32 c2, gdouble p/* = 0.5*/)
{
guint32 r = (guint32) (SP_RGBA32_R_U(c1) * p + SP_RGBA32_R_U(c2) * (1 - p));
guint32 g = (guint32) (SP_RGBA32_G_U(c1) * p + SP_RGBA32_G_U(c2) * (1 - p));
guint32 b = (guint32) (SP_RGBA32_B_U(c1) * p + SP_RGBA32_B_U(c2) * (1 - p));
guint32 a = (guint32) (SP_RGBA32_A_U(c1) * p + SP_RGBA32_A_U(c2) * (1 - p));
return SP_RGBA32_U_COMPOSE(r, g, b, a);
}
static void sp_grd_ed_add_stop(GtkWidget */*widget*/, GtkWidget *vb)
{
SPGradient *gradient = static_cast<SPGradient *>(g_object_get_data(G_OBJECT(vb), "gradient"));
verify_grad(gradient);
SPStop *stop = get_selected_stop(vb);
if (!stop) {
return;
}
Inkscape::XML::Node *new_stop_repr = NULL;
SPStop *next = stop->getNextStop();
if (next == NULL) {
SPStop *prev = stop->getPrevStop();
if (prev != NULL) {
next = stop;
stop = prev;
}
}
if (next != NULL) {
new_stop_repr = stop->getRepr()->duplicate(gradient->getRepr()->document());
gradient->getRepr()->addChild(new_stop_repr, stop->getRepr());
} else {
next = stop;
new_stop_repr = stop->getPrevStop()->getRepr()->duplicate(gradient->getRepr()->document());
gradient->getRepr()->addChild(new_stop_repr, stop->getPrevStop()->getRepr());
}
SPStop *newstop = reinterpret_cast<SPStop *>(gradient->document->getObjectByRepr(new_stop_repr));
newstop->offset = (stop->offset + next->offset) * 0.5 ;
guint32 const c1 = stop->get_rgba32();
guint32 const c2 = next->get_rgba32();
guint32 cnew = sp_average_color(c1, c2);
Inkscape::CSSOStringStream os;
gchar c[64];
sp_svg_write_color(c, sizeof(c), cnew);
gdouble opacity = static_cast<gdouble>(SP_RGBA32_A_F(cnew));
os << "stop-color:" << c << ";stop-opacity:" << opacity <<";";
newstop->getRepr()->setAttribute("style", os.str().c_str());
sp_repr_set_css_double( newstop->getRepr(), "offset", (double)newstop->offset);
sp_gradient_vector_widget_load_gradient(vb, gradient);
Inkscape::GC::release(new_stop_repr);
update_stop_list(GTK_WIDGET(vb), gradient, newstop);
GtkWidget *offspin = GTK_WIDGET(g_object_get_data(G_OBJECT(vb), "offspn"));
GtkWidget *offslide =GTK_WIDGET(g_object_get_data(G_OBJECT(vb), "offslide"));
gtk_widget_set_sensitive(offslide, TRUE);
gtk_widget_set_sensitive(GTK_WIDGET(offspin), TRUE);
DocumentUndo::done(gradient->document, SP_VERB_CONTEXT_GRADIENT,
_("Add gradient stop"));
}
static void sp_grd_ed_del_stop(GtkWidget */*widget*/, GtkWidget *vb)
{
SPGradient *gradient = static_cast<SPGradient *>(g_object_get_data(G_OBJECT(vb), "gradient"));
SPStop *stop = get_selected_stop(vb);
if (!stop) {
return;
}
if (gradient->vector.stops.size() > 2) { // 2 is the minimum
// if we delete first or last stop, move the next/previous to the edge
if (stop->offset == 0) {
SPStop *next = stop->getNextStop();
if (next) {
next->offset = 0;
sp_repr_set_css_double(next->getRepr(), "offset", 0);
}
} else if (stop->offset == 1) {
SPStop *prev = stop->getPrevStop();
if (prev) {
prev->offset = 1;
sp_repr_set_css_double(prev->getRepr(), "offset", 1);
}
}
gradient->getRepr()->removeChild(stop->getRepr());
sp_gradient_vector_widget_load_gradient(vb, gradient);
update_stop_list(GTK_WIDGET(vb), gradient, NULL);
DocumentUndo::done(gradient->document, SP_VERB_CONTEXT_GRADIENT,
_("Delete gradient stop"));
}
}
static GtkWidget * sp_gradient_vector_widget_new(SPGradient *gradient, SPStop *select_stop)
{
GtkWidget *vb, *w, *f, *csel;
g_return_val_if_fail(!gradient || SP_IS_GRADIENT(gradient), NULL);
#if GTK_CHECK_VERSION(3,0,0)
vb = gtk_box_new(GTK_ORIENTATION_VERTICAL, PAD);
gtk_box_set_homogeneous(GTK_BOX(vb), FALSE);
#else
vb = gtk_vbox_new(FALSE, PAD);
#endif
g_signal_connect(G_OBJECT(vb), "destroy", G_CALLBACK(sp_gradient_vector_widget_destroy), NULL);
w = sp_gradient_image_new(gradient);
g_object_set_data(G_OBJECT(vb), "preview", w);
gtk_widget_show(w);
gtk_box_pack_start(GTK_BOX(vb), w, TRUE, TRUE, PAD);
sp_repr_add_listener(gradient->getRepr(), &grad_edit_dia_repr_events, vb);
/* ComboBox of stops with 3 columns,
* The color preview, the label and a pointer to the SPStop
*/
GtkListStore *store = gtk_list_store_new (3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER);
GtkWidget *combo_box = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store));
GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, FALSE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer, "pixbuf", 0, NULL);
gtk_cell_renderer_set_padding(renderer, 5, 0);
renderer = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), renderer, TRUE);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), renderer, "text", 1, NULL);
gtk_widget_show(combo_box);
gtk_box_pack_start(GTK_BOX(vb), combo_box, FALSE, FALSE, 0);
g_object_set_data(G_OBJECT(vb), "combo_box", combo_box);
update_stop_list(GTK_WIDGET(vb), gradient, NULL);
g_signal_connect(G_OBJECT(combo_box), "changed", G_CALLBACK(sp_grad_edit_combo_box_changed), vb);
/* Add and Remove buttons */
#if GTK_CHECK_VERSION(3,0,0)
GtkWidget *hb = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 1);
gtk_box_set_homogeneous(GTK_BOX(hb), FALSE);
#else
GtkWidget *hb = gtk_hbox_new(FALSE, 1);
#endif
// TRANSLATORS: "Stop" means: a "phase" of a gradient
GtkWidget *b = gtk_button_new_with_label(_("Add stop"));
gtk_widget_show(b);
gtk_container_add(GTK_CONTAINER(hb), b);
gtk_widget_set_tooltip_text(b, _("Add another control stop to gradient"));
g_signal_connect(G_OBJECT(b), "clicked", G_CALLBACK(sp_grd_ed_add_stop), vb);
b = gtk_button_new_with_label(_("Delete stop"));
gtk_widget_show(b);
gtk_container_add(GTK_CONTAINER(hb), b);
gtk_widget_set_tooltip_text(b, _("Delete current control stop from gradient"));
g_signal_connect(G_OBJECT(b), "clicked", G_CALLBACK(sp_grd_ed_del_stop), vb);
gtk_widget_show(hb);
gtk_box_pack_start(GTK_BOX(vb),hb, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
/* Offset Slider and stuff */
#if GTK_CHECK_VERSION(3,0,0)
hb = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
gtk_box_set_homogeneous(GTK_BOX(hb), FALSE);
#else
hb = gtk_hbox_new(FALSE, 0);
#endif
/* Label */
GtkWidget *l = gtk_label_new(C_("Gradient","Offset:"));
gtk_misc_set_alignment(GTK_MISC(l), 1.0, 0.5);
gtk_box_pack_start(GTK_BOX(hb),l, FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
gtk_widget_show(l);
/* Adjustment */
GtkAdjustment *Offset_adj = NULL;
Offset_adj= GTK_ADJUSTMENT(gtk_adjustment_new(0.0, 0.0, 1.0, 0.01, 0.01, 0.0));
g_object_set_data(G_OBJECT(vb), "offset", Offset_adj);
SPStop *stop = get_selected_stop(vb);
if (!stop) {
return NULL;
}
gtk_adjustment_set_value(Offset_adj, stop->offset);
/* Slider */
#if GTK_CHECK_VERSION(3,0,0)
GtkWidget *slider = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, Offset_adj);
#else
GtkWidget *slider = gtk_hscale_new(Offset_adj);
#endif
gtk_scale_set_draw_value( GTK_SCALE(slider), FALSE );
gtk_widget_show(slider);
gtk_box_pack_start(GTK_BOX(hb),slider, TRUE, TRUE, AUX_BETWEEN_BUTTON_GROUPS);
g_object_set_data(G_OBJECT(vb), "offslide", slider);
/* Spinbutton */
GtkWidget *sbtn = gtk_spin_button_new(GTK_ADJUSTMENT(Offset_adj), 0.01, 2);
sp_dialog_defocus_on_enter(sbtn);
gtk_widget_show(sbtn);
gtk_box_pack_start(GTK_BOX(hb),sbtn, FALSE, TRUE, AUX_BETWEEN_BUTTON_GROUPS);
g_object_set_data(G_OBJECT(vb), "offspn", sbtn);
if (stop->offset>0 && stop->offset<1) {
gtk_widget_set_sensitive(slider, TRUE);
gtk_widget_set_sensitive(GTK_WIDGET(sbtn), TRUE);
} else {
gtk_widget_set_sensitive(slider, FALSE);
gtk_widget_set_sensitive(GTK_WIDGET(sbtn), FALSE);
}
/* Signals */
g_signal_connect(G_OBJECT(Offset_adj), "value_changed",
G_CALLBACK(offadjustmentChanged), vb);
// g_signal_connect(G_OBJECT(slider), "changed", G_CALLBACK(offsliderChanged), vb);
gtk_widget_show(hb);
gtk_box_pack_start(GTK_BOX(vb), hb, FALSE, FALSE, PAD);
// TRANSLATORS: "Stop" means: a "phase" of a gradient
f = gtk_frame_new(_("Stop Color"));
gtk_widget_show(f);
gtk_box_pack_start(GTK_BOX(vb), f, TRUE, TRUE, PAD);
csel = static_cast<GtkWidget*>(sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK));
g_object_set_data(G_OBJECT(vb), "cselector", csel);
gtk_widget_show(csel);
gtk_container_add(GTK_CONTAINER(f), csel);
g_signal_connect(G_OBJECT(csel), "dragged", G_CALLBACK(sp_gradient_vector_color_dragged), vb);
g_signal_connect(G_OBJECT(csel), "changed", G_CALLBACK(sp_gradient_vector_color_changed), vb);
gtk_widget_show(vb);
sp_gradient_vector_widget_load_gradient(vb, gradient);
if (select_stop) {
select_stop_in_list(GTK_WIDGET(vb), gradient, select_stop);
}
return vb;
}
GtkWidget * sp_gradient_vector_editor_new(SPGradient *gradient, SPStop *stop)
{
if (dlg == NULL) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
dlg = sp_window_new(_("Gradient editor"), TRUE);
if (x == -1000 || y == -1000) {
x = prefs->getInt(prefs_path + "x", -1000);
y = prefs->getInt(prefs_path + "y", -1000);
}
if (w ==0 || h == 0) {
w = prefs->getInt(prefs_path + "w", 0);
h = prefs->getInt(prefs_path + "h", 0);
}
if (x<0) {
x=0;
}
if (y<0) {
y=0;
}
if (x != 0 || y != 0) {
gtk_window_move(reinterpret_cast<GtkWindow *>(dlg), x, y);
} else {
gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
}
if (w && h) {
gtk_window_resize(reinterpret_cast<GtkWindow *>(dlg), w, h);
}
sp_transientize(dlg);
wd.win = dlg;
wd.stop = 0;
INKSCAPE.signal_activate_desktop.connect(sigc::bind(sigc::ptr_fun(&sp_transientize_callback), &wd));
g_signal_connect(G_OBJECT(dlg), "event", G_CALLBACK(sp_dialog_event_handler), dlg);
g_signal_connect(G_OBJECT(dlg), "destroy", G_CALLBACK(sp_gradient_vector_dialog_destroy), dlg);
g_signal_connect(G_OBJECT(dlg), "delete_event", G_CALLBACK(sp_gradient_vector_dialog_delete), dlg);
INKSCAPE.signal_shut_down.connect(
sigc::hide_return(
sigc::bind(sigc::ptr_fun(&sp_gradient_vector_dialog_delete), (GtkWidget *) NULL, (GdkEvent *) NULL, (GtkWidget *) NULL)
));
INKSCAPE.signal_dialogs_hide.connect(sigc::bind(sigc::ptr_fun(&gtk_widget_hide), dlg));
INKSCAPE.signal_dialogs_unhide.connect(sigc::bind(sigc::ptr_fun(&gtk_widget_show), dlg));
gtk_container_set_border_width(GTK_CONTAINER(dlg), PAD);
GtkWidget *wid = static_cast<GtkWidget*>(sp_gradient_vector_widget_new(gradient, stop));
g_object_set_data(G_OBJECT(dlg), "gradient-vector-widget", wid);
/* Connect signals */
gtk_widget_show(wid);
gtk_container_add(GTK_CONTAINER(dlg), wid);
} else {
// FIXME: temp fix for 0.38
// Simply load_gradient into the editor does not work for multi-stop gradients,
// as the stop list and other widgets are in a wrong state and crash readily.
// Instead we just delete the window (by sending the delete signal)
// and call sp_gradient_vector_editor_new again, so it creates the window anew.
GdkEventAny event;
GtkWidget *widget = static_cast<GtkWidget *>(dlg);
event.type = GDK_DELETE;
event.window = gtk_widget_get_window (widget);
event.send_event = TRUE;
g_object_ref(G_OBJECT(event.window));
gtk_main_do_event(reinterpret_cast<GdkEvent*>(&event));
g_object_unref(G_OBJECT(event.window));
g_assert(dlg == NULL);
sp_gradient_vector_editor_new(gradient, stop);
}
return dlg;
}
static void sp_gradient_vector_widget_load_gradient(GtkWidget *widget, SPGradient *gradient)
{
blocked = TRUE;
SPGradient *old;
old = static_cast<SPGradient*>(g_object_get_data(G_OBJECT(widget), "gradient"));
if (old != gradient) {
sigc::connection *release_connection;
sigc::connection *modified_connection;
release_connection = static_cast<sigc::connection *>(g_object_get_data(G_OBJECT(widget), "gradient_release_connection"));
modified_connection = static_cast<sigc::connection *>(g_object_get_data(G_OBJECT(widget), "gradient_modified_connection"));
if (old) {
g_assert( release_connection != NULL );
g_assert( modified_connection != NULL );
release_connection->disconnect();
modified_connection->disconnect();
sp_signal_disconnect_by_data(old, widget);
}
if (gradient) {
if (!release_connection) {
release_connection = new sigc::connection();
}
if (!modified_connection) {
modified_connection = new sigc::connection();
}
*release_connection = gradient->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_gradient_vector_gradient_release), widget));
*modified_connection = gradient->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_gradient_vector_gradient_modified), widget));
} else {
if (release_connection) {
delete release_connection;
release_connection = NULL;
}
if (modified_connection) {
delete modified_connection;
modified_connection = NULL;
}
}
g_object_set_data(G_OBJECT(widget), "gradient_release_connection", release_connection);
g_object_set_data(G_OBJECT(widget), "gradient_modified_connection", modified_connection);
}
g_object_set_data(G_OBJECT(widget), "gradient", gradient);
if (gradient) {
gtk_widget_set_sensitive(widget, TRUE);
gradient->ensureVector();
SPStop *stop = get_selected_stop(widget);
if (!stop) {
return;
}
// get the color selector
SPColorSelector *csel = SP_COLOR_SELECTOR(g_object_get_data(G_OBJECT(widget), "cselector"));
csel->base->setColorAlpha( stop->getEffectiveColor(), stop->opacity );
/* Fill preview */
GtkWidget *w = static_cast<GtkWidget *>(g_object_get_data(G_OBJECT(widget), "preview"));
sp_gradient_image_set_gradient(SP_GRADIENT_IMAGE(w), gradient);
update_stop_list(GTK_WIDGET(widget), gradient, NULL);
// Once the user edits a gradient, it stops being auto-collectable
if (gradient->getRepr()->attribute("inkscape:collect")) {
SPDocument *document = gradient->document;
bool saved = DocumentUndo::getUndoSensitive(document);
DocumentUndo::setUndoSensitive(document, false);
gradient->getRepr()->setAttribute("inkscape:collect", NULL);
DocumentUndo::setUndoSensitive(document, saved);
}
} else { // no gradient, disable everything
gtk_widget_set_sensitive(widget, FALSE);
}
blocked = FALSE;
}
// \FIXME this
#if GTK_CHECK_VERSION(3,0,0)
static void sp_gradient_vector_dialog_destroy(GtkWidget * /*object*/, gpointer /*data*/)
#else
static void sp_gradient_vector_dialog_destroy(GtkObject * /*object*/, gpointer /*data*/)
#endif
{
//sp_signal_disconnect_by_data(INKSCAPE, dlg);
wd.win = dlg = NULL;
wd.stop = 0;
}
static gboolean sp_gradient_vector_dialog_delete(GtkWidget */*widget*/, GdkEvent */*event*/, GtkWidget */*dialog*/)
{
gtk_window_get_position(GTK_WINDOW(dlg), &x, &y);
gtk_window_get_size(GTK_WINDOW(dlg), &w, &h);
if (x<0) {
x=0;
}
if (y<0) {
y=0;
}
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setInt(prefs_path + "x", x);
prefs->setInt(prefs_path + "y", y);
prefs->setInt(prefs_path + "w", w);
prefs->setInt(prefs_path + "h", h);
return FALSE; // which means, go ahead and destroy it
}
/* Widget destroy handler */
#if GTK_CHECK_VERSION(3,0,0)
static void sp_gradient_vector_widget_destroy(GtkWidget *object, gpointer /*data*/)
#else
static void sp_gradient_vector_widget_destroy(GtkObject *object, gpointer /*data*/)
#endif
{
SPObject *gradient = SP_OBJECT(g_object_get_data(G_OBJECT(object), "gradient"));
sigc::connection *release_connection = static_cast<sigc::connection *>(g_object_get_data(G_OBJECT(object), "gradient_release_connection"));
sigc::connection *modified_connection = static_cast<sigc::connection *>(g_object_get_data(G_OBJECT(object), "gradient_modified_connection"));
if (gradient) {
g_assert( release_connection != NULL );
g_assert( modified_connection != NULL );
release_connection->disconnect();
modified_connection->disconnect();
sp_signal_disconnect_by_data(gradient, object);
if (gradient->getRepr()) {
sp_repr_remove_listener_by_data(gradient->getRepr(), object);
}
}
}
static void sp_gradient_vector_gradient_release(SPObject */*object*/, GtkWidget *widget)
{
sp_gradient_vector_widget_load_gradient(widget, NULL);
}
static void sp_gradient_vector_gradient_modified(SPObject *object, guint /*flags*/, GtkWidget *widget)
{
SPGradient *gradient=SP_GRADIENT(object);
if (!blocked) {
blocked = TRUE;
sp_gradient_vector_widget_load_gradient(widget, gradient);
blocked = FALSE;
}
}
static void sp_gradient_vector_color_dragged(SPColorSelector *csel, GObject *object)
{
SPGradient *gradient, *ngr;
if (blocked) {
return;
}
gradient = static_cast<SPGradient*>(g_object_get_data(G_OBJECT(object), "gradient"));
if (!gradient) {
return;
}
blocked = TRUE;
ngr = sp_gradient_ensure_vector_normalized(gradient);
if (ngr != gradient) {
/* Our master gradient has changed */
sp_gradient_vector_widget_load_gradient(GTK_WIDGET(object), ngr);
}
ngr->ensureVector();
SPStop *stop = get_selected_stop(GTK_WIDGET(object));
if (!stop) {
return;
}
csel->base->getColorAlpha(stop->specified_color, stop->opacity);
stop->currentColor = false;
blocked = FALSE;
}
static void sp_gradient_vector_color_changed(SPColorSelector *csel, GObject *object)
{
if (blocked) {
return;
}
SPGradient *gradient = static_cast<SPGradient*>(g_object_get_data(G_OBJECT(object), "gradient"));
if (!gradient) {
return;
}
blocked = TRUE;
SPGradient *ngr = sp_gradient_ensure_vector_normalized(gradient);
if (ngr != gradient) {
/* Our master gradient has changed */
sp_gradient_vector_widget_load_gradient(GTK_WIDGET(object), ngr);
}
ngr->ensureVector();
/* Set start parameters */
/* We rely on normalized vector, i.e. stops HAVE to exist */
g_return_if_fail(ngr->getFirstStop() != NULL);
SPStop *stop = get_selected_stop(GTK_WIDGET(object));
if (!stop) {
return;
}
csel = static_cast<SPColorSelector*>(g_object_get_data(G_OBJECT(object), "cselector"));
SPColor color;
float alpha = 0;
csel->base->getColorAlpha( color, alpha );
sp_repr_set_css_double(stop->getRepr(), "offset", stop->offset);
Inkscape::CSSOStringStream os;
os << "stop-color:" << color.toString() << ";stop-opacity:" << static_cast<gdouble>(alpha) <<";";
stop->getRepr()->setAttribute("style", os.str().c_str());
// g_snprintf(c, 256, "stop-color:#%06x;stop-opacity:%g;", rgb >> 8, static_cast<gdouble>(alpha));
//stop->getRepr()->setAttribute("style", c);
DocumentUndo::done(ngr->document, SP_VERB_CONTEXT_GRADIENT,
_("Change gradient stop color"));
blocked = FALSE;
// Set the color in the selected stop after change
GtkWidget *combo_box = static_cast<GtkWidget *>(g_object_get_data(G_OBJECT(object), "combo_box"));
if (combo_box) {
GtkTreeIter iter;
if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX(combo_box), &iter)) {
GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo_box)));
Inkscape::UI::Widget::ColorPreview *cp = Gtk::manage(new Inkscape::UI::Widget::ColorPreview(stop->get_rgba32()));
GdkPixbuf *pb = cp->toPixbuf(64, 16);
gtk_list_store_set (store, &iter, 0, pb, /*1, repr->attribute("id"),*/ 2, stop, -1);
}
}
}
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :