diff options
| author | John Smith <john.smith7545@yahoo.com> | 2012-06-26 07:47:04 +0000 |
|---|---|---|
| committer | John Smith <removethis.john.q.public@bigmail.com> | 2012-06-26 07:47:04 +0000 |
| commit | 17c1fe80afbaa85bc7d8caf8516a41ec1b89fbf4 (patch) | |
| tree | 1037e8a8fd7b8a60a60e7a74579b54843811c837 | |
| parent | UI. Fix for Bug #817193 (Usability: emphasize gridlines checkbox is using neg... (diff) | |
| download | inkscape-17c1fe80afbaa85bc7d8caf8516a41ec1b89fbf4.tar.gz inkscape-17c1fe80afbaa85bc7d8caf8516a41ec1b89fbf4.zip | |
Fix for 722017 : Better Gradient Window
(bzr r11515)
| -rw-r--r-- | src/id-clash.cpp | 47 | ||||
| -rw-r--r-- | src/id-clash.h | 1 | ||||
| -rw-r--r-- | src/widgets/gradient-selector.cpp | 293 | ||||
| -rw-r--r-- | src/widgets/gradient-selector.h | 54 | ||||
| -rw-r--r-- | src/widgets/gradient-vector.cpp | 191 | ||||
| -rw-r--r-- | src/widgets/gradient-vector.h | 12 | ||||
| -rw-r--r-- | src/widgets/swatch-selector.cpp | 2 |
7 files changed, 422 insertions, 178 deletions
diff --git a/src/id-clash.cpp b/src/id-clash.cpp index e5a40868b..12bb65a26 100644 --- a/src/id-clash.cpp +++ b/src/id-clash.cpp @@ -273,6 +273,53 @@ prevent_id_clashes(SPDocument *imported_doc, SPDocument *current_doc) } /* + * Change the id of a SPObject to new_name + * If there is an id clash then rename to something similar + */ +void rename_id(SPObject *elem, Glib::ustring const &new_name) +{ + gchar *id = g_strdup(new_name.c_str()); + g_strcanon (id, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.:", '_'); + if (!*id || !isalnum (*id)) { + g_message("Invalid Id, will not change."); + return; + } + + SPDocument *current_doc = elem->document; + refmap_type *refmap = new refmap_type; + id_changelist_type id_changes; + find_references(current_doc->getRoot(), refmap); + + std::string old_id(elem->getId()); + std::string new_id(id); + if (id && current_doc->getObjectById(id)) { + // Choose a new ID. + // To try to preserve any meaningfulness that the original ID + // may have had, the new ID is the old ID followed by a hyphen + // and one or more digits. + new_id += '-'; + for (;;) { + new_id += "0123456789"[std::rand() % 10]; + const char *str = new_id.c_str(); + if (current_doc->getObjectById(str) == NULL) + break; + } + } + + // Change to the new ID + elem->getRepr()->setAttribute("id", new_id.c_str()); + // Make a note of this change, if we need to fix up refs to it + if (refmap->find(old_id) != refmap->end()) { + id_changes.push_back(id_changeitem_type(elem, old_id)); + } + + fix_up_refs(refmap, id_changes); + + g_free (id); + delete refmap; +} + +/* Local Variables: mode:c++ c-file-style:"stroustrup" diff --git a/src/id-clash.h b/src/id-clash.h index a76bf5137..de3cd29d3 100644 --- a/src/id-clash.h +++ b/src/id-clash.h @@ -4,6 +4,7 @@ #include "document.h" void prevent_id_clashes(SPDocument *imported_doc, SPDocument *current_doc); +void rename_id(SPObject *elem, Glib::ustring const &newname); #endif /* !SEEN_ID_CLASH_H */ diff --git a/src/widgets/gradient-selector.cpp b/src/widgets/gradient-selector.cpp index 3a8caa28c..2095179ae 100644 --- a/src/widgets/gradient-selector.cpp +++ b/src/widgets/gradient-selector.cpp @@ -21,13 +21,19 @@ #include "document.h" #include "../document-private.h" #include "../gradient-chemistry.h" +#include "inkscape.h" +#include "verbs.h" +#include "helper/action.h" +#include "preferences.h" #include <glibmm/i18n.h> #include <xml/repr.h> #include "gradient-vector.h" - #include "gradient-selector.h" +#include "paint-selector.h" +#include "style.h" +#include "id-clash.h" enum { GRABBED, @@ -37,6 +43,7 @@ enum { LAST_SIGNAL }; + static void sp_gradient_selector_class_init (SPGradientSelectorClass *klass); static void sp_gradient_selector_init (SPGradientSelector *selector); static void sp_gradient_selector_dispose(GObject *object); @@ -45,7 +52,6 @@ static void sp_gradient_selector_dispose(GObject *object); static void sp_gradient_selector_vector_set (SPGradientVectorSelector *gvs, SPGradient *gr, SPGradientSelector *sel); static void sp_gradient_selector_edit_vector_clicked (GtkWidget *w, SPGradientSelector *sel); static void sp_gradient_selector_add_vector_clicked (GtkWidget *w, SPGradientSelector *sel); -static void sp_gradient_selector_spread_changed (GtkComboBox *widget, SPGradientSelector *sel); static GtkVBoxClass *parent_class; static guint signals[LAST_SIGNAL] = {0}; @@ -116,6 +122,7 @@ static void sp_gradient_selector_class_init(SPGradientSelectorClass *klass) static void sp_gradient_selector_init(SPGradientSelector *sel) { sel->safelyInit = true; + sel->blocked = false; new (&sel->nonsolid) std::vector<GtkWidget*>(); sel->mode = SPGradientSelector::MODE_LINEAR; @@ -125,78 +132,89 @@ static void sp_gradient_selector_init(SPGradientSelector *sel) /* Vectors */ sel->vectors = sp_gradient_vector_selector_new (NULL, NULL); - gtk_widget_show (sel->vectors); - gtk_box_pack_start (GTK_BOX (sel), sel->vectors, FALSE, FALSE, 0); - g_signal_connect (G_OBJECT (sel->vectors), "vector_set", G_CALLBACK (sp_gradient_selector_vector_set), sel); + SPGradientVectorSelector *gvs = SP_GRADIENT_VECTOR_SELECTOR(sel->vectors); + sel->store = gvs->store; + sel->columns = gvs->columns; + + sel->treeview = Gtk::manage(new Gtk::TreeView()); + sel->treeview->set_model(gvs->store); + sel->treeview->set_headers_clickable (true); + sel->treeview->set_search_column(1); + sel->icon_renderer = Gtk::manage(new Gtk::CellRendererPixbuf()); + sel->text_renderer = Gtk::manage(new Gtk::CellRendererText()); + + sel->treeview->append_column("Gradient", *sel->icon_renderer); + Gtk::TreeView::Column* icon_column = sel->treeview->get_column(0); + icon_column->add_attribute(sel->icon_renderer->property_pixbuf(), sel->columns->pixbuf); + icon_column->set_sort_column(sel->columns->color); + icon_column->set_clickable(true); + + sel->treeview->append_column("Name", *sel->text_renderer); + Gtk::TreeView::Column* name_column = sel->treeview->get_column(1); + sel->text_renderer->property_editable() = true; + name_column->add_attribute(sel->text_renderer->property_text(), sel->columns->name); + name_column->set_min_width(200); + name_column->set_clickable(true); + name_column->set_resizable(true); + + sel->treeview->append_column("#", sel->columns->refcount); + Gtk::TreeView::Column* count_column = sel->treeview->get_column(2); + count_column->set_clickable(true); + count_column->set_resizable(true); + + sel->treeview->show(); + + icon_column->signal_clicked().connect( sigc::mem_fun(*sel, &SPGradientSelector::onTreeColorColClick) ); + name_column->signal_clicked().connect( sigc::mem_fun(*sel, &SPGradientSelector::onTreeNameColClick) ); + count_column->signal_clicked().connect( sigc::mem_fun(*sel, &SPGradientSelector::onTreeCountColClick) ); + + gvs->tree_select_connection = sel->treeview->get_selection()->signal_changed().connect( sigc::mem_fun(*sel, &SPGradientSelector::onTreeSelection) ); + sel->text_renderer->signal_edited().connect( sigc::mem_fun(*sel, &SPGradientSelector::onTreeEdited) ); + + sel->scrolled_window = Gtk::manage(new Gtk::ScrolledWindow()); + sel->scrolled_window->add(*sel->treeview); + sel->scrolled_window->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + sel->scrolled_window->set_shadow_type(Gtk::SHADOW_IN); + sel->scrolled_window->set_size_request(0, 150); + sel->scrolled_window->show(); + + gtk_box_pack_start (GTK_BOX (sel), GTK_WIDGET(sel->scrolled_window->gobj()), TRUE, TRUE, 4); + /* Create box for buttons */ #if GTK_CHECK_VERSION(3,0,0) GtkWidget *hb = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_set_homogeneous(GTK_BOX(hb), FALSE); #else - GtkWidget *hb = gtk_hbox_new( FALSE, 0 ); + GtkWidget *hb = gtk_hbox_new( FALSE, 2 ); #endif sel->nonsolid.push_back(hb); gtk_box_pack_start( GTK_BOX(sel), hb, FALSE, FALSE, 0 ); - sel->add = gtk_button_new_with_label (_("Duplicate")); + sel->add = gtk_button_new (); + gtk_button_set_image((GtkButton*)sel->add , gtk_image_new_from_stock ( GTK_STOCK_ADD, GTK_ICON_SIZE_SMALL_TOOLBAR ) ); + sel->nonsolid.push_back(sel->add); - gtk_box_pack_start (GTK_BOX (hb), sel->add, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hb), sel->add, FALSE, FALSE, 0); + g_signal_connect (G_OBJECT (sel->add), "clicked", G_CALLBACK (sp_gradient_selector_add_vector_clicked), sel); gtk_widget_set_sensitive (sel->add, FALSE); + gtk_button_set_relief(GTK_BUTTON(sel->add), GTK_RELIEF_NONE); + gtk_widget_set_tooltip_text( sel->add, _("Create a duplicate gradient")); + + sel->edit = gtk_button_new (); + gtk_button_set_image((GtkButton*)sel->edit , gtk_image_new_from_stock ( GTK_STOCK_EDIT, GTK_ICON_SIZE_SMALL_TOOLBAR ) ); - sel->edit = gtk_button_new_with_label (_("Edit...")); sel->nonsolid.push_back(sel->edit); - gtk_box_pack_start (GTK_BOX (hb), sel->edit, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hb), sel->edit, FALSE, FALSE, 0); g_signal_connect (G_OBJECT (sel->edit), "clicked", G_CALLBACK (sp_gradient_selector_edit_vector_clicked), sel); gtk_widget_set_sensitive (sel->edit, FALSE); + gtk_button_set_relief(GTK_BUTTON(sel->edit), GTK_RELIEF_NONE); + gtk_widget_set_tooltip_text( sel->edit, _("Edit gradient")); gtk_widget_show_all(hb); - /* Spread selector */ -#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 - sel->nonsolid.push_back(hb); - gtk_widget_show(hb); - gtk_box_pack_start( GTK_BOX(sel), hb, FALSE, FALSE, 0 ); - -// The GtkComboBoxText API only appeared in Gtk 2.24 but Inkscape supports -// builds for Gtk >= 2.20. -// Older versions need to use now-deprecated parts of -// the GtkComboBox API instead. -#if GTK_CHECK_VERSION(2,24,0) - sel->spread = gtk_combo_box_text_new (); - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (sel->spread), _("none")); - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (sel->spread), _("reflected")); - gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (sel->spread), _("direct")); -#else - sel->spread = gtk_combo_box_new_text (); - gtk_combo_box_append_text (GTK_COMBO_BOX (sel->spread), _("none")); - gtk_combo_box_append_text (GTK_COMBO_BOX (sel->spread), _("reflected")); - gtk_combo_box_append_text (GTK_COMBO_BOX (sel->spread), _("direct")); -#endif - sel->nonsolid.push_back(sel->spread); - gtk_widget_show(sel->spread); - gtk_box_pack_end( GTK_BOX(hb), sel->spread, FALSE, FALSE, 0 ); - gtk_widget_set_tooltip_text( sel->spread, - // TRANSLATORS: for info, see http://www.w3.org/TR/2000/CR-SVG-20000802/pservers.html#LinearGradientSpreadMethodAttribute - _("Whether to fill with flat color beyond the ends of the gradient vector " - "(spreadMethod=\"pad\"), or repeat the gradient in the same direction " - "(spreadMethod=\"repeat\"), or repeat the gradient in alternating opposite " - "directions (spreadMethod=\"reflect\")")); - - g_signal_connect (G_OBJECT (sel->spread), "changed", - G_CALLBACK (sp_gradient_selector_spread_changed), sel); - - sel->spreadLbl = gtk_label_new( _("Repeat:") ); - sel->nonsolid.push_back(sel->spreadLbl); - gtk_widget_show( sel->spreadLbl ); - gtk_box_pack_end( GTK_BOX(hb), sel->spreadLbl, FALSE, FALSE, 4 ); } static void sp_gradient_selector_dispose(GObject *object) @@ -209,11 +227,27 @@ static void sp_gradient_selector_dispose(GObject *object) sel->nonsolid.~vector<GtkWidget*>(); } + if (sel->icon_renderer) { + delete sel->icon_renderer; + sel->icon_renderer = NULL; + } + if (sel->text_renderer) { + delete sel->text_renderer; + sel->text_renderer = NULL; + } + if (((GObjectClass *) (parent_class))->dispose) { (* ((GObjectClass *) (parent_class))->dispose) (object); } } +void SPGradientSelector::setSpread(SPGradientSpread spread) +{ + gradientSpread = spread; + //gtk_combo_box_set_active (GTK_COMBO_BOX(this->spread), gradientSpread); +} + + GtkWidget * sp_gradient_selector_new (void) { @@ -245,12 +279,6 @@ void SPGradientSelector::setUnits(SPGradientUnits units) gradientUnits = units; } -void SPGradientSelector::setSpread(SPGradientSpread spread) -{ - gradientSpread = spread; - gtk_combo_box_set_active (GTK_COMBO_BOX(this->spread), gradientSpread); -} - SPGradientUnits SPGradientSelector::getUnits() { return gradientUnits; @@ -261,6 +289,92 @@ SPGradientSpread SPGradientSelector::getSpread() return gradientSpread; } +void SPGradientSelector::onTreeEdited( const Glib::ustring& path_string, const Glib::ustring& new_text) +{ + Gtk::TreePath path(path_string); + Gtk::TreeModel::iterator iter = store->get_iter(path); + + if( iter ) + { + Gtk::TreeModel::Row row = *iter; + if ( row ) { + SPObject* obj = row[columns->data]; + if ( obj ) { + if (!new_text.empty() && new_text != row[columns->name]) { + rename_id(obj, new_text ); + } + row[columns->name] = gr_prepare_label(obj); + } + } + } +} + +void SPGradientSelector::onTreeColorColClick() { + Gtk::TreeView::Column* column = treeview->get_column(0); + column->set_sort_column(columns->color); +} + +void SPGradientSelector::onTreeNameColClick() { + Gtk::TreeView::Column* column = treeview->get_column(1); + column->set_sort_column(columns->name); +} + + +void SPGradientSelector::onTreeCountColClick() { + Gtk::TreeView::Column* column = treeview->get_column(2); + column->set_sort_column(columns->refcount); +} + + +void SPGradientSelector::onTreeSelection() +{ + if (!treeview) { + return; + } + + if (blocked) { + return; + } + + const Glib::RefPtr<Gtk::TreeSelection> sel = treeview->get_selection(); + if (!sel) { + return; + } + + SPGradient *obj = NULL; + /* Single selection */ + Gtk::TreeModel::iterator iter = sel->get_selected(); + if ( iter ) { + Gtk::TreeModel::Row row = *iter; + obj = row[columns->data]; + } + + if (obj) { + sp_gradient_selector_vector_set (NULL, (SPGradient*)obj, this); + } +} + +bool SPGradientSelector::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPGradient *vector) +{ + bool found = false; + + Gtk::TreeModel::Row row = *iter; + if ( vector == row[columns->data] ) + { + treeview->scroll_to_row(path, 0.5); + Glib::RefPtr<Gtk::TreeSelection> select = treeview->get_selection(); + select->select(iter); + found = true; + } + + return found; +} + +void SPGradientSelector::selectGradientInTree(SPGradient *vector) +{ + store->foreach( sigc::bind<SPGradient*>(sigc::mem_fun(*this, &SPGradientSelector::_checkForSelected), vector) ); +} + void SPGradientSelector::setVector(SPDocument *doc, SPGradient *vector) { g_return_if_fail(!vector || SP_IS_GRADIENT(vector)); @@ -272,6 +386,8 @@ void SPGradientSelector::setVector(SPDocument *doc, SPGradient *vector) sp_gradient_vector_selector_set_gradient(SP_GRADIENT_VECTOR_SELECTOR(vectors), doc, vector); + selectGradientInTree(vector); + if (vector) { if ( (mode == MODE_SWATCH) && vector->isSwatch() ) { if ( vector->isSolid() ) { @@ -309,42 +425,51 @@ SPGradient *SPGradientSelector::getVector() return SP_GRADIENT_VECTOR_SELECTOR(vectors)->gr; } + static void -sp_gradient_selector_vector_set (SPGradientVectorSelector */*gvs*/, SPGradient *gr, SPGradientSelector *sel) +sp_gradient_selector_vector_set (SPGradientVectorSelector *gvs, SPGradient *gr, SPGradientSelector *sel) { - static gboolean blocked = FALSE; - if (!blocked) { - blocked = TRUE; + if (!sel->blocked) { + sel->blocked = TRUE; gr = sp_gradient_ensure_vector_normalized (gr); sel->setVector((gr) ? gr->document : 0, gr); g_signal_emit (G_OBJECT (sel), signals[CHANGED], 0, gr); - blocked = FALSE; + sel->blocked = FALSE; + } } static void sp_gradient_selector_edit_vector_clicked (GtkWidget */*w*/, SPGradientSelector *sel) { - GtkWidget *dialog; - - /* fixme: */ - dialog = sp_gradient_vector_editor_new (SP_GRADIENT_VECTOR_SELECTOR (sel->vectors)->gr); - - gtk_widget_show (dialog); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if (prefs->getBool("/dialogs/gradienteditor/showlegacy", true)) { + // Legacy gradient dialog + GtkWidget *dialog; + dialog = sp_gradient_vector_editor_new (SP_GRADIENT_VECTOR_SELECTOR (sel->vectors)->gr); + gtk_widget_show (dialog); + } else { + // Invoke the gradient tool + Inkscape::Verb *verb = Inkscape::Verb::get( SP_VERB_CONTEXT_GRADIENT ); + if ( verb ) { + SPAction *action = verb->get_action( ( Inkscape::UI::View::View * ) SP_ACTIVE_DESKTOP); + if ( action ) { + sp_action_perform( action, NULL ); + } + } + } } static void sp_gradient_selector_add_vector_clicked (GtkWidget */*w*/, SPGradientSelector *sel) { - SPDocument *doc = sp_gradient_vector_selector_get_document ( - SP_GRADIENT_VECTOR_SELECTOR (sel->vectors)); + SPDocument *doc = sp_gradient_vector_selector_get_document (SP_GRADIENT_VECTOR_SELECTOR (sel->vectors)); if (!doc) return; - SPGradient *gr = sp_gradient_vector_selector_get_gradient( - SP_GRADIENT_VECTOR_SELECTOR (sel->vectors)); + SPGradient *gr = sp_gradient_vector_selector_get_gradient( SP_GRADIENT_VECTOR_SELECTOR (sel->vectors)); Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node *repr = NULL; @@ -367,18 +492,18 @@ sp_gradient_selector_add_vector_clicked (GtkWidget */*w*/, SPGradientSelector *s doc->getDefs()->getRepr()->addChild(repr, NULL); - gr = static_cast<SPGradient *>(doc->getObjectByRepr(repr)); - sp_gradient_vector_selector_set_gradient( - SP_GRADIENT_VECTOR_SELECTOR (sel->vectors), doc, gr); + Glib::ustring old_id = gr->getId(); - Inkscape::GC::release(repr); -} + gr = (SPGradient *) doc->getObjectByRepr(repr); -static void -sp_gradient_selector_spread_changed (GtkComboBox *widget, SPGradientSelector *sel) -{ - sel->gradientSpread = (SPGradientSpread) gtk_combo_box_get_active (GTK_COMBO_BOX(widget)); - g_signal_emit (G_OBJECT (sel), signals[CHANGED], 0); + // Rename the new gradients id to be similar to the cloned gradients + rename_id(gr, old_id); + + sp_gradient_vector_selector_set_gradient( SP_GRADIENT_VECTOR_SELECTOR (sel->vectors), doc, gr); + + sel->selectGradientInTree(gr); + + Inkscape::GC::release(repr); } /* diff --git a/src/widgets/gradient-selector.h b/src/widgets/gradient-selector.h index d957f7baf..f7cc3cc14 100644 --- a/src/widgets/gradient-selector.h +++ b/src/widgets/gradient-selector.h @@ -17,10 +17,19 @@ #include <glib.h> #include <gtk/gtk.h> + +#include <gtkmm/entry.h> +#include <gtkmm/label.h> +#include <gtkmm/table.h> +#include <gtkmm/liststore.h> +#include <gtkmm/treeview.h> +#include <gtkmm/scrolledwindow.h> + #include <vector> #include "sp-gradient.h" #include "sp-gradient-spread.h" #include "sp-gradient-units.h" +#include "gradient-image.h" class SPGradient; @@ -49,24 +58,61 @@ struct SPGradientSelector { /* Vector selector */ GtkWidget *vectors; + /* Tree */ + bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPGradient *vector); + void onTreeSelection(); + void onTreeEdited( const Glib::ustring& path_string, const Glib::ustring& new_text); + void onTreeNameColClick(); + void onTreeColorColClick(); + void onTreeCountColClick(); + + Gtk::TreeView *treeview; + Gtk::ScrolledWindow *scrolled_window; + class ModelColumns : public Gtk::TreeModel::ColumnRecord + { + public: + ModelColumns() + { + add(name); + add(refcount); + add(color); + add(data); + add(pixbuf); + } + virtual ~ModelColumns() {} + + Gtk::TreeModelColumn<Glib::ustring> name; + Gtk::TreeModelColumn<unsigned long> color; + Gtk::TreeModelColumn<gint> refcount; + Gtk::TreeModelColumn<SPGradient*> data; + Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf> > pixbuf; + + }; + + ModelColumns *columns; + Glib::RefPtr<Gtk::ListStore> store; + Gtk::CellRendererPixbuf* icon_renderer; + Gtk::CellRendererText* text_renderer; + /* Editing buttons */ GtkWidget *edit; GtkWidget *add; + GtkWidget *merge; /* Position widget */ GtkWidget *position; - /* Spread selector */ - GtkWidget *spread; - GtkWidget *spreadLbl; - bool safelyInit; + bool blocked; + std::vector<GtkWidget*> nonsolid; void setMode(SelectorMode mode); void setUnits(SPGradientUnits units); void setSpread(SPGradientSpread spread); void setVector(SPDocument *doc, SPGradient *vector); + void selectGradientInTree(SPGradient *vector); + SPGradientUnits getUnits(); SPGradientSpread getSpread(); SPGradient *getVector(); diff --git a/src/widgets/gradient-vector.cpp b/src/widgets/gradient-vector.cpp index c875ab61c..db8c76b9b 100644 --- a/src/widgets/gradient-vector.cpp +++ b/src/widgets/gradient-vector.cpp @@ -30,11 +30,13 @@ #include <gtk/gtk.h> #include "macros.h" #include <glibmm/i18n.h> +#include <set> #include "../widgets/gradient-image.h" #include "../inkscape.h" #include "../document-private.h" #include "../gradient-chemistry.h" #include "../helper/window.h" +#include "io/resource.h" #include "xml/repr.h" @@ -42,6 +44,12 @@ #include "../preferences.h" #include "svg/css-ostringstream.h" #include "sp-stop.h" +#include "selection-chemistry.h" +#include "style.h" +#include "sp-linear-gradient.h" +#include "sp-radial-gradient.h" +#include "desktop.h" +#include "layer-manager.h" #include <sigc++/functors/ptr_fun.h> #include <sigc++/adaptors/bind.h> @@ -68,8 +76,9 @@ static void sp_gvs_defs_release(SPObject *defs, SPGradientVectorSelector *gvs); static void sp_gvs_defs_modified(SPObject *defs, guint flags, SPGradientVectorSelector *gvs); static void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs); -static void gr_combo_box_changed (GtkComboBox *widget, SPGradientVectorSelector *gvs); static SPStop *get_selected_stop( GtkWidget *vb); +void gr_get_usage_counts(SPDocument *doc, std::map<SPGradient *, gint> *mapUsageCount ); +unsigned long sp_gradient_to_hhssll(SPGradient *gr); static GtkVBoxClass *parent_class; static guint signals[LAST_SIGNAL] = {0}; @@ -141,22 +150,9 @@ static void sp_gradient_vector_selector_init(SPGradientVectorSelector *gvs) new (&gvs->defs_release_connection) sigc::connection(); new (&gvs->defs_modified_connection) sigc::connection(); - gvs->store = gtk_list_store_new (3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER); - gvs->combo_box = gtk_combo_box_new_with_model (GTK_TREE_MODEL (gvs->store)); - gvs->combo_connection = g_signal_connect (G_OBJECT (gvs->combo_box), "changed", G_CALLBACK (gr_combo_box_changed), gvs); - - GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (gvs->combo_box), renderer, FALSE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (gvs->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 (gvs->combo_box), renderer, TRUE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (gvs->combo_box), renderer, "text", 1, NULL); - gtk_cell_renderer_set_padding(renderer, 0, 0); - - gtk_widget_show(gvs->combo_box); - gtk_box_pack_start(GTK_BOX(gvs), gvs->combo_box, TRUE, TRUE, 0); + gvs->columns = new SPGradientSelector::ModelColumns(); + gvs->store = Gtk::ListStore::create(*gvs->columns); + new (&gvs->tree_select_connection) sigc::connection(); } @@ -170,6 +166,7 @@ static void sp_gradient_vector_selector_destroy(GtkObject *object) if (gvs->gr) { gvs->gradient_release_connection.disconnect(); + gvs->tree_select_connection.disconnect(); gvs->gr = NULL; } @@ -182,6 +179,7 @@ static void sp_gradient_vector_selector_destroy(GtkObject *object) gvs->gradient_release_connection.~connection(); gvs->defs_release_connection.~connection(); gvs->defs_modified_connection.~connection(); + gvs->tree_select_connection.~connection(); #if GTK_CHECK_VERSION(3,0,0) if ((reinterpret_cast<GtkWidgetClass *>(parent_class))->destroy) { @@ -281,9 +279,13 @@ SPGradient *sp_gradient_vector_selector_get_gradient(SPGradientVectorSelector *g Glib::ustring gr_prepare_label (SPObject *obj) { - const gchar *id = obj->defaultLabel(); - if (strlen(id) > 15 && (!strncmp (id, "#linearGradient", 15) || !strncmp (id, "#radialGradient", 15))) - return gr_ellipsize_text (g_strdup_printf ("#%s", id+15), 35); + const gchar *id = obj->label() ? obj->label() : obj->getId(); + if (!id) { + id = obj->getRepr()->name(); + } + + if (strlen(id) > 14 && (!strncmp (id, "linearGradient", 14) || !strncmp (id, "radialGradient", 14))) + return gr_ellipsize_text (g_strdup_printf ("%s", id+14), 35); return gr_ellipsize_text (id, 35); } @@ -303,9 +305,11 @@ Glib::ustring gr_ellipsize_text(Glib::ustring const &src, size_t maxlen) static void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs) { + + gvs->tree_select_connection.block(); + /* Clear old list, if there is any */ - gtk_list_store_clear(gvs->store); - GtkTreeIter iter; + gvs->store->clear(); /* Pick up all gradients with vectors */ GSList *gl = NULL; @@ -320,102 +324,124 @@ static void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs) } gl = g_slist_reverse(gl); - gint pos = 0; + /* Get usage count of all the gradients */ + std::map<SPGradient *, gint> usageCount; + gr_get_usage_counts(gvs->doc, &usageCount); if (!gvs->doc) { - gtk_list_store_append (gvs->store, &iter); - gtk_list_store_set (gvs->store, &iter, 0, NULL, 1, _("No document selected"), 2, NULL, -1); - gtk_widget_set_sensitive (gvs->combo_box, FALSE); + Gtk::TreeModel::Row row = *(gvs->store->append()); + row[gvs->columns->name] = _("No document selected"); } else if (!gl) { - gtk_list_store_append (gvs->store, &iter); - gtk_list_store_set (gvs->store, &iter, 0, NULL, 1, _("No gradients in document"), 2, NULL, -1); - gtk_widget_set_sensitive (gvs->combo_box, FALSE); + Gtk::TreeModel::Row row = *(gvs->store->append()); + row[gvs->columns->name] = _("No gradients in document"); } else if (!gvs->gr) { - gtk_list_store_append (gvs->store, &iter); - gtk_list_store_set (gvs->store, &iter, 0, NULL, 1, _("No gradient selected"), 2, NULL, -1); - gtk_widget_set_sensitive (gvs->combo_box, FALSE); + Gtk::TreeModel::Row row = *(gvs->store->append()); + row[gvs->columns->name] = _("No gradient selected"); } else { - gint idx = 0; while (gl) { SPGradient *gr; gr = SP_GRADIENT(gl->data); gl = g_slist_remove(gl, gr); - /* We have to know: */ - /* Gradient destroy */ - /* Gradient name change */ - - Glib::ustring label = gr_prepare_label(gr); + unsigned long hhssll = sp_gradient_to_hhssll(gr); GdkPixbuf *pixb = sp_gradient_to_pixbuf (gr, 64, 18); - gtk_list_store_append (gvs->store, &iter); - gtk_list_store_set (gvs->store, &iter, 0, pixb, 1, label.c_str(), 2, gr, -1); + Glib::ustring label = gr_prepare_label(gr); + + Gtk::TreeModel::Row row = *(gvs->store->append()); + row[gvs->columns->name] = label.c_str(); + row[gvs->columns->color] = hhssll; + row[gvs->columns->refcount] = usageCount[gr]; + row[gvs->columns->data] = gr; + row[gvs->columns->pixbuf] = Glib::wrap(pixb); - if (gr == gvs->gr) { - pos = idx; - } - idx += 1; } - gtk_widget_set_sensitive (gvs->combo_box, TRUE); } - /* Block signal to prevent recursive loop */ - g_signal_handler_block(G_OBJECT (gvs->combo_box), gvs->combo_connection); + gvs->tree_select_connection.unblock(); - /* Set selected */ - gtk_combo_box_set_active (GTK_COMBO_BOX(gvs->combo_box) , pos); +} + +/* + * Return a "HHSSLL" version of the first stop color so we can sort by it + */ +unsigned long sp_gradient_to_hhssll(SPGradient *gr) +{ + SPStop *stop = gr->getFirstStop(); + unsigned long rgba = sp_stop_get_rgba32(stop); + float hsl[3]; + sp_color_rgb_to_hsl_floatv (hsl, SP_RGBA32_R_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_B_F(rgba)); - g_signal_handler_unblock(G_OBJECT (gvs->combo_box), gvs->combo_connection); + return ((int)(hsl[0]*100 * 10000)) + ((int)(hsl[1]*100 * 100)) + ((int)(hsl[2]*100 * 1)); } -static void gr_combo_box_changed (GtkComboBox *widget, SPGradientVectorSelector *gvs) +GSList *get_all_doc_items(GSList *list, SPObject *from, bool onlyvisible, bool onlysensitive, bool ingroups, GSList const *exclude) { - GtkTreeIter iter; - if (!gtk_combo_box_get_active_iter (widget, &iter)) { - return; + for ( SPObject *child = from->firstChild() ; child; child = child->getNext() ) { + if (SP_IS_ITEM(child)) { + list = g_slist_prepend(list, SP_ITEM(child)); + } + + if (ingroups || SP_IS_ITEM(child)) { + list = get_all_doc_items(list, child, onlyvisible, onlysensitive, ingroups, exclude); + } } - SPGradient *gr = NULL; - gtk_tree_model_get (GTK_TREE_MODEL(gvs->store), &iter, 2, &gr, -1); + return list; +} - if (gr) { +/* + * Return a SPItem's gradient + */ +static SPGradient * gr_item_get_gradient(SPItem *item, gboolean fillorstroke) +{ + SPIPaint *item_paint = (fillorstroke) ? &(item->style->fill) : &(item->style->stroke); + if (item_paint->isPaintserver()) { - SPGradient *norm = sp_gradient_ensure_vector_normalized(gr); - if (norm != gr) { - //g_print("SPGradientVectorSelector: become %s after normalization\n", norm->getId()); - /* But be careful that we do not have gradient saved anywhere else */ - //g_object_set_data(G_OBJECT(mi), "gradient", norm); - gtk_list_store_set (gvs->store, &iter, 2, norm, -1); - } + SPPaintServer *item_server = (fillorstroke) ? + item->style->getFillPaintServer() : item->style->getStrokePaintServer(); - /* fixme: Really we would want to use _set_vector */ - /* Detach old */ - if (gvs->gr) { - gvs->gradient_release_connection.disconnect(); - gvs->gr = NULL; - } - /* Attach new */ - if (norm) { - gvs->gradient_release_connection = norm->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_gvs_gradient_release), gvs)); - gvs->gr = norm; + if (SP_IS_LINEARGRADIENT(item_server) || SP_IS_RADIALGRADIENT(item_server) || + (SP_IS_GRADIENT(item_server) && SP_GRADIENT(item_server)->getVector()->isSwatch())) { + + return SP_GRADIENT(item_server)->getVector(); } + } - g_signal_emit(G_OBJECT(gvs), signals[VECTOR_SET], 0, norm); + return NULL; +} - if (norm != gr) { - /* We do extra undo push here */ - /* If handler has already done it, it is just NOP */ - // FIXME: looks like this is never a valid undo step, consider removing this - DocumentUndo::done(norm->document, SP_VERB_CONTEXT_GRADIENT, - /* TODO: annotate */ "gradient-vector.cpp:350"); - } +/* + * Map each gradient to its usage count for both fill and stroke styles + */ +void gr_get_usage_counts(SPDocument *doc, std::map<SPGradient *, gint> *mapUsageCount ) +{ + if (!doc) + return; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); + bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); + bool ingroups = TRUE; + GSList *all_list = get_all_doc_items(NULL, doc->getRoot(), onlyvisible, onlysensitive, ingroups, NULL); + for (GSList *i = all_list; i != NULL; i = i->next) { + SPItem *item = SP_ITEM(i->data); + SPGradient *gr = NULL; + gr = gr_item_get_gradient(item, true); // fill + if (gr) { + mapUsageCount->count(gr) > 0 ? (*mapUsageCount)[gr] += 1 : (*mapUsageCount)[gr] = 1; + } + gr = gr_item_get_gradient(item, false); // stroke + if (gr) { + mapUsageCount->count(gr) > 0 ? (*mapUsageCount)[gr] += 1 : (*mapUsageCount)[gr] = 1; + } } } + static void sp_gvs_gradient_release(SPObject */*obj*/, SPGradientVectorSelector *gvs) { /* Disconnect gradient */ @@ -448,7 +474,6 @@ static void sp_gvs_defs_release(SPObject */*defs*/, SPGradientVectorSelector *gv static void sp_gvs_defs_modified(SPObject */*defs*/, guint /*flags*/, SPGradientVectorSelector *gvs) { /* fixme: We probably have to check some flags here (Lauris) */ - sp_gvs_rebuild_gui_full(gvs); } diff --git a/src/widgets/gradient-vector.h b/src/widgets/gradient-vector.h index 9a26ab046..1ed6c6c46 100644 --- a/src/widgets/gradient-vector.h +++ b/src/widgets/gradient-vector.h @@ -16,11 +16,13 @@ */ #include <glib.h> +#include <gtkmm/liststore.h> #include <stddef.h> #include <sigc++/connection.h> #include <gtk/gtk.h> +#include "gradient-selector.h" #define SP_TYPE_GRADIENT_VECTOR_SELECTOR (sp_gradient_vector_selector_get_type ()) #define SP_GRADIENT_VECTOR_SELECTOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SP_TYPE_GRADIENT_VECTOR_SELECTOR, SPGradientVectorSelector)) @@ -43,16 +45,14 @@ struct SPGradientVectorSelector { SPDocument *doc; SPGradient *gr; - /* ComboBox of gradient vectors */ - GtkWidget *combo_box; - GtkListStore *store; + /* Gradient vectors store */ + Glib::RefPtr<Gtk::ListStore> store; + SPGradientSelector::ModelColumns *columns; sigc::connection gradient_release_connection; sigc::connection defs_release_connection; sigc::connection defs_modified_connection; - - gulong combo_connection; - + sigc::connection tree_select_connection; void setSwatched(); }; diff --git a/src/widgets/swatch-selector.cpp b/src/widgets/swatch-selector.cpp index 5de71c95e..524072cf0 100644 --- a/src/widgets/swatch-selector.cpp +++ b/src/widgets/swatch-selector.cpp @@ -182,7 +182,7 @@ void SwatchSelector::setVector(SPDocument */*doc*/, SPGradient *vector) _csel->base->setColor( color ); gtk_widget_show_all( GTK_WIDGET(_csel) ); } else { - gtk_widget_hide( GTK_WIDGET(_csel) ); + //gtk_widget_hide( GTK_WIDGET(_csel) ); } /* |
