From 9ffede11acaf9769bb1889702dda5c49e86db43f Mon Sep 17 00:00:00 2001 From: Fridrich Strba Date: Mon, 9 Jul 2012 15:34:46 -0500 Subject: Add support for libvisio Fixed bugs: - https://launchpad.net/bugs/1015572 (bzr r11533.1.1) --- src/Makefile.am | 2 ++ src/extension/init.cpp | 6 ++++++ src/extension/internal/Makefile_insert | 5 +++++ 3 files changed, 13 insertions(+) (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index c27af0800..fc1065b34 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,6 +51,7 @@ all_libs = \ $(PYTHON_LIBS) \ $(INKBOARD_LIBS) \ $(LIBWPG_LIBS) \ + $(LIBVISIO_LIBS) \ $(DBUS_LIBS) \ $(GDL_LIBS) \ $(IMAGEMAGICK_LIBS) @@ -74,6 +75,7 @@ INCLUDES = \ $(IMAGEMAGICK_CFLAGS) \ $(INKBOARD_CFLAGS) \ $(LIBWPG_CFLAGS) \ + $(LIBVISIO_CFLAGS) \ $(DBUS_CFLAGS) \ $(GDL_CFLAGS) \ $(XFT_CFLAGS) \ diff --git a/src/extension/init.cpp b/src/extension/init.cpp index b0732568f..d59c2b2e3 100644 --- a/src/extension/init.cpp +++ b/src/extension/init.cpp @@ -53,6 +53,9 @@ #ifdef WITH_LIBWPG #include "internal/wpg-input.h" #endif +#ifdef WITH_LIBVISIO +#include "internal/vsd-input.h" +#endif #include "preferences.h" #include "io/sys.h" #ifdef WITH_DBUS @@ -183,6 +186,9 @@ init() #ifdef WITH_LIBWPG Internal::WpgInput::init(); #endif +#ifdef WITH_LIBVISIO + Internal::VsdInput::init(); +#endif /* Effects */ Internal::BlurEdge::init(); diff --git a/src/extension/internal/Makefile_insert b/src/extension/internal/Makefile_insert index 06fa275cb..9e5b4bd7e 100644 --- a/src/extension/internal/Makefile_insert +++ b/src/extension/internal/Makefile_insert @@ -4,7 +4,12 @@ if WITH_LIBWPG ink_common_sources += \ extension/internal/wpg-input.cpp \ extension/internal/wpg-input.h +endif +if WITH_LIBVISIO +ink_common_sources += \ + extension/internal/vsd-input.cpp \ + extension/internal/vsd-input.h endif if USE_IMAGE_MAGICK -- cgit v1.2.3 From 157767bdd321e70ae9b871d5342689d56090e22e Mon Sep 17 00:00:00 2001 From: Fridrich Strba Date: Mon, 9 Jul 2012 16:31:20 -0500 Subject: Added Visio Files (bzr r11533.1.2) --- src/extension/internal/vsd-input.cpp | 289 +++++++++++++++++++++++++++++++++++ src/extension/internal/vsd-input.h | 54 +++++++ 2 files changed, 343 insertions(+) create mode 100644 src/extension/internal/vsd-input.cpp create mode 100644 src/extension/internal/vsd-input.h (limited to 'src') diff --git a/src/extension/internal/vsd-input.cpp b/src/extension/internal/vsd-input.cpp new file mode 100644 index 000000000..6d71ce72a --- /dev/null +++ b/src/extension/internal/vsd-input.cpp @@ -0,0 +1,289 @@ +/* + * This file came from libwpg as a source, their utility wpg2svg + * specifically. It has been modified to work as an Inkscape extension. + * The Inkscape extension code is covered by this copyright, but the + * rest is covered by the one bellow. + * + * Authors: + * Fridrich Strba (fridrich.strba@bluewin.ch) + * + * Copyright (C) 2012 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + * + */ + +#include +#include "config.h" + +#include "vsd-input.h" + +#ifdef WITH_LIBVISIO + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "extension/system.h" +#include "extension/input.h" +#include "document.h" + +#include "document-private.h" +#include "document-undo.h" +#include "inkscape.h" + +#include "dialogs/dialog-events.h" +#include +#include "ui/widget/spinbutton.h" +#include "ui/widget/frame.h" +#include + +#include + +#include "svg-view.h" +#include "svg-view-widget.h" + +namespace Inkscape { +namespace Extension { +namespace Internal { + + +class VsdImportDialog : public Gtk::Dialog { +public: + VsdImportDialog(const std::vector &vec); + virtual ~VsdImportDialog(); + + bool showDialog(); + unsigned getSelectedPage(); + void getImportSettings(Inkscape::XML::Node *prefs); + +private: + void _setPreviewPage(unsigned page); + + // Signal handlers +#if !WITH_GTKMM_3_0 + bool _onExposePreview(GdkEventExpose *event); +#endif + + void _onPageNumberChanged(); + + class Gtk::Button * cancelbutton; + class Gtk::Button * okbutton; + class Gtk::Label * _labelSelect; + class Inkscape::UI::Widget::SpinButton * _pageNumberSpin; + class Gtk::Label * _labelTotalPages; + class Gtk::VBox * vbox1; + class Gtk::VBox * vbox2; + class Gtk::Widget * _previewArea; + + const std::vector &_vec; // Document to be imported + unsigned _current_page; // Current selected page + int _preview_width, _preview_height; // Size of the preview area +}; + +VsdImportDialog::VsdImportDialog(const std::vector &vec) + : _vec(vec), _current_page(1) +{ + int num_pages = _vec.size(); + if ( num_pages <= 1 ) + return; + cancelbutton = Gtk::manage(new class Gtk::Button(Gtk::StockID("gtk-cancel"))); + okbutton = Gtk::manage(new class Gtk::Button(Gtk::StockID("gtk-ok"))); + _labelSelect = Gtk::manage(new class Gtk::Label(_("Select page:"))); + + // Page number +#if WITH_GTKMM_3_0 + Glib::RefPtr _pageNumberSpin_adj = Gtk::Adjustment::create(1, 1, _vec.size(), 1, 10, 0); + _pageNumberSpin = Gtk::manage(new Inkscape::UI::Widget::SpinButton(_pageNumberSpin_adj, 1, 1)); +#else + Gtk::Adjustment *_pageNumberSpin_adj = Gtk::manage( + new class Gtk::Adjustment(1, 1, _vec.size(), 1, 10, 0)); + _pageNumberSpin = Gtk::manage(new class Inkscape::UI::Widget::SpinButton(*_pageNumberSpin_adj, 1, 1)); +#endif + _labelTotalPages = Gtk::manage(new class Gtk::Label()); + gchar *label_text = g_strdup_printf(_("out of %i"), num_pages); + _labelTotalPages->set_label(label_text); + g_free(label_text); + + vbox1 = Gtk::manage(new class Gtk::VBox(false, 4)); + SPDocument *doc = SPDocument::createNewDocFromMem(_vec[0].cstr(), strlen(_vec[0].cstr()), 0); + _previewArea = Glib::wrap(sp_svg_view_widget_new(doc)); + + vbox2 = Gtk::manage(new class Gtk::VBox(false, 4)); + cancelbutton->set_can_focus(); + cancelbutton->set_can_default(); + cancelbutton->set_relief(Gtk::RELIEF_NORMAL); + okbutton->set_can_focus(); + okbutton->set_can_default(); + okbutton->set_relief(Gtk::RELIEF_NORMAL); + this->get_action_area()->property_layout_style().set_value(Gtk::BUTTONBOX_END); + _labelSelect->set_line_wrap(false); + _labelSelect->set_use_markup(false); + _labelSelect->set_selectable(false); + _pageNumberSpin->set_can_focus(); + _pageNumberSpin->set_update_policy(Gtk::UPDATE_ALWAYS); + _pageNumberSpin->set_numeric(true); + _pageNumberSpin->set_digits(0); + _pageNumberSpin->set_wrap(false); + _labelTotalPages->set_line_wrap(false); + _labelTotalPages->set_use_markup(false); + _labelTotalPages->set_selectable(false); + vbox2->pack_start(*_previewArea, Gtk::PACK_SHRINK, 0); + this->get_vbox()->set_homogeneous(false); + this->get_vbox()->set_spacing(0); + this->get_vbox()->pack_start(*vbox2); + this->set_title(_("Page Selector")); + this->set_modal(true); + sp_transientize((GtkWidget *)this->gobj()); //Make transient + this->property_window_position().set_value(Gtk::WIN_POS_NONE); + this->set_resizable(true); + this->property_destroy_with_parent().set_value(false); + this->get_action_area()->add(*_labelSelect); + this->add_action_widget(*_pageNumberSpin, -7); + this->get_action_area()->add(*_labelTotalPages); + this->add_action_widget(*cancelbutton, -6); + this->add_action_widget(*okbutton, -5); + cancelbutton->show(); + okbutton->show(); + _labelSelect->show(); + _pageNumberSpin->show(); + _labelTotalPages->show(); + vbox1->show(); + _previewArea->show(); + vbox2->show(); + + // Connect signals + _pageNumberSpin_adj->signal_value_changed().connect(sigc::mem_fun(*this, &VsdImportDialog::_onPageNumberChanged)); +} + +VsdImportDialog::~VsdImportDialog() {} + +bool VsdImportDialog::showDialog() +{ + show(); + gint b = run(); + hide(); + if ( b == Gtk::RESPONSE_OK ) { + return TRUE; + } else { + return FALSE; + } +} + +unsigned VsdImportDialog::getSelectedPage() +{ + return _current_page; +} + +void VsdImportDialog::_onPageNumberChanged() +{ + int page = _pageNumberSpin->get_value_as_int(); + _current_page = CLAMP(page, 1, _vec.size()); + _setPreviewPage(_current_page); +} + +/** + * \brief Renders the given page's thumbnail + */ +void VsdImportDialog::_setPreviewPage(unsigned page) +{ + SPDocument *doc = SPDocument::createNewDocFromMem(_vec[page-1].cstr(), strlen(_vec[page-1].cstr()), 0); + Gtk::Widget * tmpPreviewArea = Glib::wrap(sp_svg_view_widget_new(doc)); + std::swap(_previewArea, tmpPreviewArea); + if (tmpPreviewArea) { + _previewArea->set_size_request( tmpPreviewArea->get_width(), tmpPreviewArea->get_height() ); + delete tmpPreviewArea; + } + vbox2->pack_start(*_previewArea, Gtk::PACK_SHRINK, 0); + _previewArea->show_now(); +} + +SPDocument *VsdInput::open(Inkscape::Extension::Input * /*mod*/, const gchar * uri) +{ + WPXFileStream input(uri); + + if (!libvisio::VisioDocument::isSupported(&input)) { + return NULL; + } + + libvisio::VSDStringVector output; + if (!libvisio::VisioDocument::generateSVG(&input, output)) { + return NULL; + } + + if (output.empty()) { + return NULL; + } + + std::vector tmpSVGOutput; + for (unsigned i=0; i\n\n"); + tmpString.append(output[i]); + tmpSVGOutput.push_back(tmpString); + } + + unsigned page_num = 1; + + // If only one page is present, import that one without bothering user + if (tmpSVGOutput.size() > 1) { + VsdImportDialog *dlg = 0; + if (inkscape_use_gui()) { + dlg = new VsdImportDialog(tmpSVGOutput); + if (!dlg->showDialog()) { + delete dlg; + return NULL; + } + } + + // Get needed page + if (dlg) { + page_num = dlg->getSelectedPage(); + if (page_num < 1) + page_num = 1; + if (page_num > tmpSVGOutput.size()) + page_num = tmpSVGOutput.size(); + } + } + + SPDocument * doc = SPDocument::createNewDocFromMem(tmpSVGOutput[page_num-1].cstr(), strlen(tmpSVGOutput[page_num-1].cstr()), TRUE); + return doc; +} + +#include "clear-n_.h" + +void VsdInput::init(void) +{ + Inkscape::Extension::build_from_mem( + "\n" + "" N_("VSD Input") "\n" + "org.inkscape.input.vsd\n" + "\n" + ".vsd\n" + "application/vnd.visio\n" + "" N_("Microsoft Visio Diagram (*.vsd)") "\n" + "" N_("File format used by Microsoft Visio 6 and later") "\n" + "\n" + "", new VsdInput()); +} // init + +} } } /* namespace Inkscape, Extension, Implementation */ +#endif /* WITH_LIBVISIO */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/extension/internal/vsd-input.h b/src/extension/internal/vsd-input.h new file mode 100644 index 000000000..acc52debf --- /dev/null +++ b/src/extension/internal/vsd-input.h @@ -0,0 +1,54 @@ +/* + * This code abstracts the libwpg interfaces into the Inkscape + * input extension interface. + * + * Authors: + * Fridrich Strba (fridrich.strba@bluewin.ch) + * + * Copyright (C) 2012 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef __EXTENSION_INTERNAL_VSDOUTPUT_H__ +#define __EXTENSION_INTERNAL_VSDOUTPUT_H__ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef WITH_LIBVISIO + +#include + +#include "../implementation/implementation.h" + +namespace Inkscape { +namespace Extension { +namespace Internal { + +class VsdInput : public Inkscape::Extension::Implementation::Implementation { + VsdInput () { }; +public: + SPDocument *open( Inkscape::Extension::Input *mod, + const gchar *uri ); + static void init( void ); + +}; + +} } } /* namespace Inkscape, Extension, Implementation */ + +#endif /* WITH_LIBVISIO */ +#endif /* __EXTENSION_INTERNAL_VSDOUTPUT_H__ */ + + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : -- cgit v1.2.3 From 702260c47ccb58ed7ed38971504b955d69048149 Mon Sep 17 00:00:00 2001 From: Alvin Penner Date: Mon, 17 Sep 2012 18:40:45 -0400 Subject: fix typo in marker bbox calculation (Bug 1051131) Fixed bugs: - https://launchpad.net/bugs/1051131 (bzr r11670) --- src/sp-shape.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp index f27b3c9db..a9a9c7781 100644 --- a/src/sp-shape.cpp +++ b/src/sp-shape.cpp @@ -614,7 +614,7 @@ Geom::OptRect SPShape::sp_shape_bbox(SPItem const *item, Geom::Affine const &tra tr = Geom::Scale(style->stroke_width.computed) * tr; } tr = marker_item->transform * marker->c2p * tr * transform; - bbox |= marker_item->visualBounds(); + bbox |= marker_item->visualBounds(tr); } } } -- cgit v1.2.3 From 979d809bbbe2d3ed1fc5a296c8f99f5d8c395f4b Mon Sep 17 00:00:00 2001 From: John Smith Date: Tue, 18 Sep 2012 08:44:30 +0900 Subject: Fix for 165865 : Fix marker color on duplicate (bzr r11671) --- src/marker.cpp | 33 +++++++++++++ src/marker.h | 2 +- src/widgets/stroke-marker-selector.cpp | 8 +--- src/widgets/stroke-marker-selector.h | 5 +- src/widgets/stroke-style.cpp | 86 ++++++++++++---------------------- src/widgets/stroke-style.h | 15 ++++-- 6 files changed, 80 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/marker.cpp b/src/marker.cpp index a5681e180..45582caa4 100644 --- a/src/marker.cpp +++ b/src/marker.cpp @@ -27,6 +27,7 @@ #include "marker.h" #include "document.h" #include "document-private.h" +#include "preferences.h" struct SPMarkerView { SPMarkerView *next; @@ -727,6 +728,38 @@ const gchar *generate_marker(GSList *reprs, Geom::Rect bounds, SPDocument *docum return mark_id; } +SPObject *sp_marker_fork_if_necessary(SPObject *marker) +{ + if (marker->hrefcount < 2) { + return marker; + } + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + gboolean colorStock = prefs->getBool("/options/markers/colorStockMarkers", true); + gboolean colorCustom = prefs->getBool("/options/markers/colorCustomMarkers", false); + const gchar *stock = marker->getRepr()->attribute("inkscape:isstock"); + gboolean isStock = (!stock || !strcmp(stock,"true")); + + if (isStock ? !colorStock : !colorCustom) { + return marker; + } + + SPDocument *doc = marker->document; + Inkscape::XML::Document *xml_doc = doc->getReprDoc(); + // Turn off garbage-collectable or it might be collected before we can use it + marker->getRepr()->setAttribute("inkscape:collect", NULL); + Inkscape::XML::Node *mark_repr = marker->getRepr()->duplicate(xml_doc); + doc->getDefs()->getRepr()->addChild(mark_repr, NULL); + if (!mark_repr->attribute("inkscape:stockid")) { + mark_repr->setAttribute("inkscape:stockid", mark_repr->attribute("id")); + } + marker->getRepr()->setAttribute("inkscape:collect", "always"); + + SPObject *marker_new = static_cast(doc->getObjectByRepr(mark_repr)); + Inkscape::GC::release(mark_repr); + return marker_new; +} + /* Local Variables: mode:c++ diff --git a/src/marker.h b/src/marker.h index 6fdb82aa3..e8d2dd9a1 100644 --- a/src/marker.h +++ b/src/marker.h @@ -90,6 +90,6 @@ Inkscape::DrawingItem *sp_marker_show_instance (SPMarker *marker, Inkscape::Draw Geom::Affine const &base, float linewidth); void sp_marker_hide (SPMarker *marker, unsigned int key); const gchar *generate_marker (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move); - +SPObject *sp_marker_fork_if_necessary(SPObject *marker); #endif diff --git a/src/widgets/stroke-marker-selector.cpp b/src/widgets/stroke-marker-selector.cpp index 0016dcf1f..206f166f9 100644 --- a/src/widgets/stroke-marker-selector.cpp +++ b/src/widgets/stroke-marker-selector.cpp @@ -45,9 +45,10 @@ static Inkscape::UI::Cache::SvgPreview svg_preview_cache; -MarkerComboBox::MarkerComboBox(gchar const *id) : +MarkerComboBox::MarkerComboBox(gchar const *id, int l) : Gtk::ComboBox(), combo_id(id), + loc(l), updating(false), markerCount(0) { @@ -256,11 +257,6 @@ const gchar * MarkerComboBox::get_active_marker_uri() return marker; } -bool MarkerComboBox::isSelectedStock() -{ - return get_active()->get_value(marker_columns.stock); -} - void MarkerComboBox::set_active_history() { const gchar *markid = get_active()->get_value(marker_columns.marker); diff --git a/src/widgets/stroke-marker-selector.h b/src/widgets/stroke-marker-selector.h index 14c5ad758..02038ea42 100644 --- a/src/widgets/stroke-marker-selector.h +++ b/src/widgets/stroke-marker-selector.h @@ -32,7 +32,7 @@ class Adjustment; class MarkerComboBox : public Gtk::ComboBox { public: - MarkerComboBox(gchar const *id); + MarkerComboBox(gchar const *id, int loc); ~MarkerComboBox(); void setDesktop(SPDesktop *desktop); @@ -45,14 +45,15 @@ public: const gchar *get_active_marker_uri(); bool update() { return updating; }; gchar const *get_id() { return combo_id; }; - bool isSelectedStock(); void update_marker_image(gchar const *mname); + int get_loc() { return loc; }; private: Glib::RefPtr marker_store; gchar const *combo_id; + int loc; bool updating; guint markerCount; SPDesktop *desktop; diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp index 2c39945f7..5f686881f 100644 --- a/src/widgets/stroke-style.cpp +++ b/src/widgets/stroke-style.cpp @@ -291,7 +291,7 @@ StrokeStyle::StrokeStyle() : // TRANSLATORS: Path markers are an SVG feature that allows you to attach arbitrary shapes // (arrowheads, bullets, faces, whatever) to the start, end, or middle nodes of a path. - startMarkerCombo = manage(new MarkerComboBox("marker-start")); + startMarkerCombo = manage(new MarkerComboBox("marker-start", SP_MARKER_LOC_START)); spw_label(table, _("_Start Markers:"), 0, i, startMarkerCombo); startMarkerCombo->set_tooltip_text(_("Start Markers are drawn on the first node of a path or shape")); startMarkerConn = startMarkerCombo->signal_changed().connect( @@ -301,7 +301,7 @@ StrokeStyle::StrokeStyle() : table->attach(*startMarkerCombo, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast(0), 0, 0); i++; - midMarkerCombo = manage(new MarkerComboBox("marker-mid")); + midMarkerCombo = manage(new MarkerComboBox("marker-mid", SP_MARKER_LOC_MID)); spw_label(table, _("_Mid Markers:"), 0, i, midMarkerCombo); midMarkerCombo->set_tooltip_text(_("Mid Markers are drawn on every node of a path or shape except the first and last nodes")); midMarkerConn = midMarkerCombo->signal_changed().connect( @@ -311,7 +311,7 @@ StrokeStyle::StrokeStyle() : table->attach(*midMarkerCombo, 1, 4, i, i+1, (Gtk::EXPAND | Gtk::FILL), static_cast(0), 0, 0); i++; - endMarkerCombo = manage(new MarkerComboBox("marker-end")); + endMarkerCombo = manage(new MarkerComboBox("marker-end", SP_MARKER_LOC_END)); spw_label(table, _("_End Markers:"), 0, i, endMarkerCombo); endMarkerCombo->set_tooltip_text(_("End Markers are drawn on the last node of a path or shape")); endMarkerConn = endMarkerCombo->signal_changed().connect( @@ -429,11 +429,7 @@ StrokeStyle::markerSelectCB(MarkerComboBox *marker_combo, StrokeStyle *spw, SPMa if (selrepr) { sp_repr_css_change_recursive(selrepr, css, "style"); SPObject *markerObj = getMarkerObj(marker, document); - if (!marker_combo->isSelectedStock()) { - // If arrow, marker will already be forked - markerObj = spw->forkMarker(item, markerObj, marker_combo); - } - spw->setMarkerColor(item, markerObj, marker_combo); + spw->setMarkerColor(markerObj, marker_combo->get_loc(), item); } item->requestModified(SP_OBJECT_MODIFIED_FLAG); @@ -570,74 +566,46 @@ StrokeStyle::selectionChangedCB() } /* - * Make a new copy of a marker, set as auto collectable - * Set the referencing items url to the new marker + * Fork marker if necessary and set the referencing items url to the new marker * Return the new marker */ SPObject * -StrokeStyle::forkMarker(SPItem *item, SPObject *marker, MarkerComboBox *marker_combo) +StrokeStyle::forkMarker(SPObject *marker, int loc, SPItem *item) { - if (!item || !marker) { return NULL; } - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - gboolean colorStock = prefs->getBool("/options/markers/colorStockMarkers", true); - gboolean colorCustom = prefs->getBool("/options/markers/colorCustomMarkers", false); - const gchar *stock = marker->getRepr()->attribute("inkscape:isstock"); - gboolean isStock = (!stock || !strcmp(stock,"true")); - gchar const *combo_id = marker_combo->get_id(); - - if (isStock ? !colorStock : !colorCustom) { - return marker; - } - + gchar const *marker_id = SPMarkerNames[loc].key; /* - * Optimization - * If this item already has this marker elsewhere (start/mid or end), + * Optimization when all the references to this marker are from this item * then we can reuse it and dont need to fork */ - SPCSSAttr *css = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS); Glib::ustring urlId = Glib::ustring::format("url(#", marker->getRepr()->attribute("id"), ")"); - const gchar *markers[3] = { "marker-start", "marker-mid", "marker-end" }; - //gboolean exists = false; - for (int i = 0; i < 3; i++) { - if (!strcmp(marker_combo->get_id(), markers[i])) { - continue; - } - const char *urlMark = sp_repr_css_property(css, markers[i], ""); - if (!strcmp(urlId.c_str(), urlMark)) { - return marker; + unsigned int refs = 0; + for (int i = SP_MARKER_LOC_START; i < SP_MARKER_LOC_QTY; i++) { + if (item->style->marker[i].set && !strcmp(urlId.c_str(), item->style->marker[i].value)) { + refs++; } } + if (marker->hrefcount <= refs) { + return marker; + } - - SPDocument *doc = SP_ACTIVE_DOCUMENT; - SPDefs *defs = doc->getDefs(); - Inkscape::XML::Document *xml_doc = doc->getReprDoc(); - // Turn off garbage-collectable or it might be collected before we can use it - marker->getRepr()->setAttribute("inkscape:collect", NULL); - Inkscape::XML::Node *mark_repr = marker->getRepr()->duplicate(xml_doc); - defs->getRepr()->addChild(mark_repr, NULL); - gchar const *markid = marker->getRepr()->attribute("inkscape:stockid") ? marker->getRepr()->attribute("inkscape:stockid") : marker->getRepr()->attribute("id"); - mark_repr->setAttribute("inkscape:stockid", markid); + marker = sp_marker_fork_if_necessary(marker); // Update the items url to new marker + Inkscape::XML::Node *mark_repr = marker->getRepr(); SPCSSAttr *css_item = sp_repr_css_attr_new(); - sp_repr_css_set_property(css_item, combo_id, g_strconcat("url(#", mark_repr->attribute("id"), ")", NULL)); + sp_repr_css_set_property(css_item, marker_id, g_strconcat("url(#", mark_repr->attribute("id"), ")", NULL)); sp_repr_css_change_recursive(item->getRepr(), css_item, "style"); - // privates are garbage-collectable - mark_repr->setAttribute("inkscape:collect", "always"); - marker->getRepr()->setAttribute("inkscape:collect", "always"); - Inkscape::GC::release(mark_repr); sp_repr_css_attr_unref(css_item); css_item = 0; - return doc->getObjectById(mark_repr->attribute("id")); + return marker; } /** @@ -650,7 +618,7 @@ StrokeStyle::forkMarker(SPItem *item, SPObject *marker, MarkerComboBox *marker_c * */ void -StrokeStyle::setMarkerColor(SPItem *item, SPObject *marker, MarkerComboBox *marker_combo) +StrokeStyle::setMarkerColor(SPObject *marker, int loc, SPItem *item) { if (!item || !marker) { @@ -667,6 +635,9 @@ StrokeStyle::setMarkerColor(SPItem *item, SPObject *marker, MarkerComboBox *mark return; } + // Check if we need to fork this marker + marker = forkMarker(marker, loc, item); + Inkscape::XML::Node *repr = marker->getRepr()->firstChild(); if (!repr) { return; @@ -674,9 +645,9 @@ StrokeStyle::setMarkerColor(SPItem *item, SPObject *marker, MarkerComboBox *mark // Current line style SPCSSAttr *css_item = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS); - const char *lstroke = getItemColorForMarker(item, FOR_STROKE, marker_combo); + const char *lstroke = getItemColorForMarker(item, FOR_STROKE, loc); const char *lstroke_opacity = sp_repr_css_property(css_item, "stroke-opacity", "1"); - const char *lfill = getItemColorForMarker(item, FOR_FILL, marker_combo); + const char *lfill = getItemColorForMarker(item, FOR_FILL, loc); const char *lfill_opacity = sp_repr_css_property(css_item, "fill-opacity", "1"); // Current marker style @@ -725,7 +696,7 @@ StrokeStyle::setMarkerColor(SPItem *item, SPObject *marker, MarkerComboBox *mark * If its a gradient, then return first or last stop color */ const char * -StrokeStyle::getItemColorForMarker(SPItem *item, Inkscape::PaintTarget fill_or_stroke, MarkerComboBox *marker_combo) +StrokeStyle::getItemColorForMarker(SPItem *item, Inkscape::PaintTarget fill_or_stroke, int loc) { SPCSSAttr *css_item = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS); const char *color; @@ -736,11 +707,12 @@ StrokeStyle::getItemColorForMarker(SPItem *item, Inkscape::PaintTarget fill_or_s if (!strncmp (color, "url(", 4)) { // If the item has a gradient use the first stop color for the marker + SPGradient *grad = getGradient(item, fill_or_stroke); if (grad) { SPGradient *vector = grad->getVector(FALSE); SPStop *stop = vector->getFirstStop(); - if (marker_combo == endMarkerCombo) { + if (loc == SP_MARKER_LOC_END) { stop = sp_last_stop(vector); } if (stop) { @@ -1231,7 +1203,7 @@ StrokeStyle::updateAllMarkers(GSList const *objects) gboolean update = prefs->getBool("/options/markers/colorUpdateMarkers", true); if (update) { - setMarkerColor(SP_ITEM(object), marker, combo); + setMarkerColor(marker, combo->get_loc(), SP_ITEM(object)); SPDocument *document = sp_desktop_document(desktop); DocumentUndo::done(document, SP_VERB_DIALOG_FILL_STROKE, diff --git a/src/widgets/stroke-style.h b/src/widgets/stroke-style.h index 546880bc2..d437f7e12 100644 --- a/src/widgets/stroke-style.h +++ b/src/widgets/stroke-style.h @@ -67,6 +67,15 @@ class Widget; class Container; } +struct { gchar const *key; gint value; } const SPMarkerNames[] = { + {"marker-all", SP_MARKER_LOC}, + {"marker-start", SP_MARKER_LOC_START}, + {"marker-mid", SP_MARKER_LOC_MID}, + {"marker-end", SP_MARKER_LOC_END}, + {"", SP_MARKER_LOC_QTY}, + {NULL, -1} +}; + /** * Creates an instance of a paint style widget. */ @@ -106,9 +115,9 @@ private: void setCapButtons(Gtk::ToggleButton *active); void scaleLine(); void setScaledDash(SPCSSAttr *css, int ndash, double *dash, double offset, double scale); - void setMarkerColor(SPItem *item, SPObject *marker, MarkerComboBox *marker_combo); - SPObject *forkMarker(SPItem *item, SPObject *marker, MarkerComboBox *marker_combo); - const char *getItemColorForMarker(SPItem *item, Inkscape::PaintTarget fill_or_stroke, MarkerComboBox *marker_combo); + void setMarkerColor(SPObject *marker, int loc, SPItem *item); + SPObject *forkMarker(SPObject *marker, int loc, SPItem *item); + const char *getItemColorForMarker(SPItem *item, Inkscape::PaintTarget fill_or_stroke, int loc); Gtk::RadioButton * makeRadioButton(Gtk::RadioButton *tb, char const *icon, Gtk::HBox *hb, gchar const *key, gchar const *data); -- cgit v1.2.3 From 83ec27bee0c7b09dc0f89dc878eafec027236d6f Mon Sep 17 00:00:00 2001 From: John Smith Date: Tue, 18 Sep 2012 10:06:04 +0900 Subject: Fix for 979567 : Object context menu (right-click) acts on bottom-most instead of top-most object under cursor position (bzr r11672) --- src/event-context.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/event-context.cpp b/src/event-context.cpp index 848865b95..2c9ed1abd 100644 --- a/src/event-context.cpp +++ b/src/event-context.cpp @@ -691,9 +691,11 @@ static gint sp_event_context_private_root_handler( int const wheel_scroll = prefs->getIntLimited( "/options/wheelscroll/value", 40, 0, 1000); +#if GTK_CHECK_VERSION(3,0,0) // Size of smooth-scrolls (only used in GTK+ 3) gdouble delta_x = 0; gdouble delta_y = 0; +#endif /* shift + wheel, pan left--right */ if (event->scroll.state & GDK_SHIFT_MASK) { @@ -1059,10 +1061,18 @@ static void set_event_location(SPDesktop *desktop, GdkEvent *event) { * Create popup menu and tell Gtk to show it. */ void sp_event_root_menu_popup(SPDesktop *desktop, SPItem *item, GdkEvent *event) { + + // It seems the param item is the SPItem at the bottom of the z-order + // Using the same function call used on left click in sp_select_context_item_handler() to get top of z-order + // fixme: sp_canvas_arena should set the top z-order object as arena->active + item = sp_event_context_find_item (desktop, + Geom::Point(event->button.x, event->button.y), FALSE, FALSE); + /* fixme: This is not what I want but works for now (Lauris) */ if (event->type == GDK_KEY_PRESS) { item = sp_desktop_selection(desktop)->singleItem(); } + ContextMenu* CM = new ContextMenu(desktop, item); CM->show(); -- cgit v1.2.3 From fed4cf9a7438a2e0d6833618bd769b684397a483 Mon Sep 17 00:00:00 2001 From: John Smith Date: Tue, 18 Sep 2012 14:15:41 +0900 Subject: Fix for 1051434 : occasional crash when selecting disjoint path with markers (bzr r11673) --- src/document.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/document.cpp b/src/document.cpp index 5eaab3eca..9efd9d923 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -865,6 +865,9 @@ SPObject *SPDocument::getObjectById(Glib::ustring const &id) const SPObject *SPDocument::getObjectById(gchar const *id) const { g_return_val_if_fail(id != NULL, NULL); + if (!priv || !priv->iddef) { + return NULL; + } GQuark idq = g_quark_from_string(id); gpointer rv = g_hash_table_lookup(priv->iddef, GINT_TO_POINTER(idq)); -- cgit v1.2.3 From 9c19df4215cc73bf82049f7527cb2e85fc15d881 Mon Sep 17 00:00:00 2001 From: John Smith Date: Tue, 18 Sep 2012 14:22:47 +0900 Subject: Fix for 818628 : DBUS Metadata for error domain warning when using File>New (bzr r11674) --- src/extension/dbus/application-interface.cpp | 41 ++++++++++++++++++++++++++++ src/extension/dbus/application-interface.h | 17 ++++++++++++ src/extension/dbus/dbus-init.cpp | 3 -- src/extension/dbus/dbus-init.h | 1 + src/extension/dbus/document-interface.cpp | 37 +------------------------ src/extension/dbus/document-interface.h | 14 +--------- 6 files changed, 61 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/application-interface.cpp b/src/extension/dbus/application-interface.cpp index a652b7c96..8ee7bd12f 100644 --- a/src/extension/dbus/application-interface.cpp +++ b/src/extension/dbus/application-interface.cpp @@ -39,6 +39,9 @@ application_interface_class_init (ApplicationInterfaceClass *klass) static void application_interface_init (ApplicationInterface *object) { + dbus_g_error_domain_register (INKSCAPE_ERROR, + NULL, + INKSCAPE_TYPE_ERROR); } @@ -48,6 +51,44 @@ application_interface_new (void) return (ApplicationInterface*)g_object_new (TYPE_APPLICATION_INTERFACE, NULL); } +/* + * Error stuff... + * + * To add a new error type, edit here and in the .h InkscapeError enum. + */ +GQuark +inkscape_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("inkscape_error"); + + return quark; +} + +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType inkscape_error_get_type(void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = + { + + ENUM_ENTRY(INKSCAPE_ERROR_SELECTION, "Incompatible_Selection"), + ENUM_ENTRY(INKSCAPE_ERROR_OBJECT, "Incompatible_Object"), + ENUM_ENTRY(INKSCAPE_ERROR_VERB, "Failed_Verb"), + ENUM_ENTRY(INKSCAPE_ERROR_OTHER, "Generic_Error"), + { 0, 0, 0 } + }; + + etype = g_enum_register_static("InkscapeError", values); + } + + return etype; +} + /**************************************************************************** DESKTOP FUNCTIONS ****************************************************************************/ diff --git a/src/extension/dbus/application-interface.h b/src/extension/dbus/application-interface.h index e782bd1ad..88219a6b0 100644 --- a/src/extension/dbus/application-interface.h +++ b/src/extension/dbus/application-interface.h @@ -45,6 +45,23 @@ struct _ApplicationInterfaceClass { GObjectClass parent; }; + +typedef enum +{ + INKSCAPE_ERROR_SELECTION, + INKSCAPE_ERROR_OBJECT, + INKSCAPE_ERROR_VERB, + INKSCAPE_ERROR_OTHER +} InkscapeError; + + + +#define INKSCAPE_ERROR (inkscape_error_quark ()) +#define INKSCAPE_TYPE_ERROR (inkscape_error_get_type ()) + +GQuark inkscape_error_quark (void); +GType inkscape_error_get_type (void); + /**************************************************************************** DESKTOP FUNCTIONS ****************************************************************************/ diff --git a/src/extension/dbus/dbus-init.cpp b/src/extension/dbus/dbus-init.cpp index 1b6baa979..9ff6897e5 100644 --- a/src/extension/dbus/dbus-init.cpp +++ b/src/extension/dbus/dbus-init.cpp @@ -128,9 +128,6 @@ dbus_init_desktop_interface (SPDesktop * dt) DBusGConnection *connection; DBusGProxy *proxy; DocumentInterface *obj; - dbus_g_error_domain_register (INKSCAPE_ERROR, - NULL, - INKSCAPE_TYPE_ERROR); std::string name("/org/inkscape/desktop_"); std::stringstream out; diff --git a/src/extension/dbus/dbus-init.h b/src/extension/dbus/dbus-init.h index 4b07acfb4..025011f28 100644 --- a/src/extension/dbus/dbus-init.h +++ b/src/extension/dbus/dbus-init.h @@ -12,6 +12,7 @@ #include "desktop.h" + namespace Inkscape { namespace Extension { namespace Dbus { diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index c67234b34..66d1c5dfa 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -17,6 +17,7 @@ #include "file.h" //IO #include "document-interface.h" +#include "application-interface.h" #include #include #include "desktop-handles.h" //sp_desktop_document() @@ -320,43 +321,7 @@ document_interface_new (void) return (DocumentInterface*)g_object_new (TYPE_DOCUMENT_INTERFACE, NULL); } -/* - * Error stuff... - * - * To add a new error type, edit here and in the .h InkscapeError enum. - */ -GQuark -inkscape_error_quark (void) -{ - static GQuark quark = 0; - if (!quark) - quark = g_quark_from_static_string ("inkscape_error"); - - return quark; -} - -#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } -GType inkscape_error_get_type(void) -{ - static GType etype = 0; - - if (etype == 0) { - static const GEnumValue values[] = - { - - ENUM_ENTRY(INKSCAPE_ERROR_SELECTION, "Incompatible_Selection"), - ENUM_ENTRY(INKSCAPE_ERROR_OBJECT, "Incompatible_Object"), - ENUM_ENTRY(INKSCAPE_ERROR_VERB, "Failed_Verb"), - ENUM_ENTRY(INKSCAPE_ERROR_OTHER, "Generic_Error"), - { 0, 0, 0 } - }; - - etype = g_enum_register_static("InkscapeError", values); - } - - return etype; -} /**************************************************************************** MISC FUNCTIONS diff --git a/src/extension/dbus/document-interface.h b/src/extension/dbus/document-interface.h index e7e55cb7d..5fcbb919b 100644 --- a/src/extension/dbus/document-interface.h +++ b/src/extension/dbus/document-interface.h @@ -56,19 +56,7 @@ struct _DocumentInterfaceClass { GObjectClass parent; }; -typedef enum -{ - INKSCAPE_ERROR_SELECTION, - INKSCAPE_ERROR_OBJECT, - INKSCAPE_ERROR_VERB, - INKSCAPE_ERROR_OTHER -} InkscapeError; - -#define INKSCAPE_ERROR (inkscape_error_quark ()) -#define INKSCAPE_TYPE_ERROR (inkscape_error_get_type ()) - -GQuark inkscape_error_quark (void); -GType inkscape_error_get_type (void); + struct DBUSPoint { int x; -- cgit v1.2.3 From 64ca7777062dde4c20c3535a21317e74f487eda7 Mon Sep 17 00:00:00 2001 From: John Smith Date: Tue, 18 Sep 2012 21:21:58 +0900 Subject: Fix for 168164 : Fix precision of font size (bzr r11675) --- src/widgets/text-toolbar.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp index dcfd109d8..db9abc4c8 100644 --- a/src/widgets/text-toolbar.cpp +++ b/src/widgets/text-toolbar.cpp @@ -1222,13 +1222,16 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ int unit = prefs->getInt("/options/font/unitType", SP_CSS_UNIT_PT); double size = sp_style_css_size_px_to_units(query->font_size.computed, unit); - gchar size_text[G_ASCII_DTOSTR_BUF_SIZE]; - g_ascii_dtostr (size_text, sizeof (size_text), size); + //gchar size_text[G_ASCII_DTOSTR_BUF_SIZE]; + //g_ascii_dtostr (size_text, sizeof (size_text), size); + + Inkscape::CSSOStringStream os; + os << size; Ink_ComboBoxEntry_Action* fontSizeAction = INK_COMBOBOXENTRY_ACTION( g_object_get_data( tbl, "TextFontSizeAction" ) ); sp_text_set_sizes(GTK_LIST_STORE(ink_comboboxentry_action_get_model(fontSizeAction)), unit); - ink_comboboxentry_action_set_active_text( fontSizeAction, size_text ); + ink_comboboxentry_action_set_active_text( fontSizeAction, os.str().c_str() ); Glib::ustring tooltip = Glib::ustring::format("Font size (", sp_style_get_css_unit_string(unit), ")"); ink_comboboxentry_action_set_tooltip ( fontSizeAction, tooltip.c_str()); -- cgit v1.2.3 From 891ab5f239c03c2f3867d9445f070bc53f9d70b6 Mon Sep 17 00:00:00 2001 From: John Smith Date: Wed, 19 Sep 2012 09:49:35 +0900 Subject: Fix for 900602 : Enter key returns focus to canvas for Font family selector (bzr r11676) --- src/ink-comboboxentry-action.cpp | 69 ++++++++++++++++++++++++++++++++++++++-- src/ink-comboboxentry-action.h | 4 ++- src/widgets/text-toolbar.cpp | 15 +++++++-- 3 files changed, 82 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ink-comboboxentry-action.cpp b/src/ink-comboboxentry-action.cpp index 869296f87..6e6071654 100644 --- a/src/ink-comboboxentry-action.cpp +++ b/src/ink-comboboxentry-action.cpp @@ -27,6 +27,7 @@ #include #include +#include #include "ink-comboboxentry-action.h" @@ -42,6 +43,7 @@ static gint check_comma_separated_text( Ink_ComboBoxEntry_Action* action ); static void combo_box_changed_cb( GtkComboBox* widget, gpointer data ); static void entry_activate_cb( GtkEntry* widget, gpointer data ); static gboolean match_selected_cb( GtkEntryCompletion* widget, GtkTreeModel* model, GtkTreeIter* iter, gpointer data ); +static gboolean keypress_cb( GtkWidget *widget, GdkEventKey *event, gpointer data ); enum { PROP_MODEL = 1, @@ -50,7 +52,8 @@ enum { PROP_ENTRY_WIDTH, PROP_EXTRA_WIDTH, PROP_CELL_DATA_FUNC, - PROP_POPUP + PROP_POPUP, + PROP_FOCUS_WIDGET }; enum { @@ -105,6 +108,11 @@ static void ink_comboboxentry_action_set_property (GObject *object, guint proper action->popup = g_value_get_boolean( value ); break; + case PROP_FOCUS_WIDGET: + action->focusWidget = (GtkWidget*)g_value_get_pointer( value ); + break; + + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -145,6 +153,11 @@ static void ink_comboboxentry_action_get_property (GObject *object, guint proper g_value_set_boolean (value, action->popup); break; + case PROP_FOCUS_WIDGET: + g_value_set_pointer (value, action->focusWidget); + break; + + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -240,6 +253,13 @@ static void ink_comboboxentry_action_class_init (Ink_ComboBoxEntry_ActionClass * false, (GParamFlags)G_PARAM_READWRITE)); + g_object_class_install_property( gobject_class, + PROP_FOCUS_WIDGET, + g_param_spec_pointer( "focus-widget", + "Focus Widget", + "The widget to return focus to", + (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); + // We need to know when GtkComboBoxEvent or Menu ready for reading signals[CHANGED] = g_signal_new( "changed", G_TYPE_FROM_CLASS(klass), @@ -269,6 +289,7 @@ static void ink_comboboxentry_action_init (Ink_ComboBoxEntry_Action *action) action->popup = false; action->warning = NULL; action->altx_name = NULL; + action->focusWidget = NULL; } GType ink_comboboxentry_action_get_type () @@ -306,7 +327,8 @@ Ink_ComboBoxEntry_Action *ink_comboboxentry_action_new (const gchar *name, GtkTreeModel *model, gint entry_width, gint extra_width, - void *cell_data_func ) + void *cell_data_func, + GtkWidget *focusWidget) { g_return_val_if_fail (name != NULL, NULL); @@ -319,6 +341,7 @@ Ink_ComboBoxEntry_Action *ink_comboboxentry_action_new (const gchar *name, "entry_width", entry_width, "extra_width", extra_width, "cell_data_func", cell_data_func, + "focus-widget", focusWidget, NULL); } @@ -415,6 +438,7 @@ GtkWidget* create_tool_item( GtkAction* action ) // Add signal for GtkEntry to check if finished typing. g_signal_connect( G_OBJECT(child), "activate", G_CALLBACK(entry_activate_cb), action ); + g_signal_connect( G_OBJECT(child), "key-press-event", G_CALLBACK(keypress_cb), action ); } @@ -561,6 +585,7 @@ void ink_comboboxentry_action_popup_enable( Ink_ComboBoxEntry_Action* action ) { g_signal_connect (G_OBJECT (action->entry_completion), "match-selected", G_CALLBACK (match_selected_cb), action ); + } } @@ -764,3 +789,43 @@ static gboolean match_selected_cb( GtkEntryCompletion* /*widget*/, GtkTreeModel* return false; } +void ink_comboboxentry_action_defocus( Ink_ComboBoxEntry_Action* action ) +{ + if ( action->focusWidget ) { + gtk_widget_grab_focus( action->focusWidget ); + } +} + +gboolean keypress_cb( GtkWidget *widget, GdkEventKey *event, gpointer data ) +{ + gboolean wasConsumed = FALSE; /* default to report event not consumed */ + guint key = 0; + Ink_ComboBoxEntry_Action* action = INK_COMBOBOXENTRY_ACTION( data ); + gdk_keymap_translate_keyboard_state( gdk_keymap_get_for_display( gdk_display_get_default() ), + event->hardware_keycode, (GdkModifierType)event->state, + 0, &key, 0, 0, 0 ); + + switch ( key ) { + + // TODO Add bindings for Esc/Tab/LeftTab + case GDK_KEY_Escape: + { + //gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget), action->private_data->lastVal ); + ink_comboboxentry_action_defocus( action ); + wasConsumed = TRUE; + } + break; + + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + { + ink_comboboxentry_action_defocus( action ); + //wasConsumed = TRUE; + } + break; + + + } + + return wasConsumed; +} diff --git a/src/ink-comboboxentry-action.h b/src/ink-comboboxentry-action.h index 95306bcaa..7d4093f4e 100644 --- a/src/ink-comboboxentry-action.h +++ b/src/ink-comboboxentry-action.h @@ -59,6 +59,7 @@ struct _Ink_ComboBoxEntry_Action { gboolean popup; // Do we pop-up an entry-completion dialog? gchar *warning; // Text for warning that entry isn't in list. gchar *altx_name; // Target for Alt-X keyboard shortcut. + GtkWidget *focusWidget; }; @@ -74,7 +75,8 @@ Ink_ComboBoxEntry_Action *ink_comboboxentry_action_new ( const gchar *name, GtkTreeModel *model, gint entry_width = -1, gint extra_width = -1, - gpointer cell_data_func = NULL ); + gpointer cell_data_func = NULL, + GtkWidget* focusWidget = NULL); GtkTreeModel *ink_comboboxentry_action_get_model( Ink_ComboBoxEntry_Action* action ); GtkComboBox *ink_comboboxentry_action_get_comboboxentry( Ink_ComboBoxEntry_Action* action ); diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp index db9abc4c8..60ede002f 100644 --- a/src/widgets/text-toolbar.cpp +++ b/src/widgets/text-toolbar.cpp @@ -1464,7 +1464,8 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje GTK_TREE_MODEL(model), -1, // Entry width 50, // Extra list width - (gpointer)cell_data_func ); // Cell layout + (gpointer)cell_data_func,// Cell layout + GTK_WIDGET(desktop->canvas)); // Focus widget ink_comboboxentry_action_popup_enable( act ); // Enable entry completion gchar *const warning = _("Font not found on system"); ink_comboboxentry_action_set_warning( act, warning ); // Show icon with tooltip if missing font @@ -1498,7 +1499,11 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje _(tooltip.c_str()), NULL, GTK_TREE_MODEL(model_size), - 4 ); // Width in characters + 4, // Width in characters + 0, // Extra list width + NULL, // Cell layout + GTK_WIDGET(desktop->canvas)); // Focus widget + g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(sp_text_fontsize_value_changed), holder ); gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); g_object_set_data( holder, "TextFontSizeAction", act ); @@ -1513,7 +1518,11 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje _("Font style"), NULL, GTK_TREE_MODEL(model_style), - 12 ); // Width in characters + 12, // Width in characters + 0, // Extra list width + NULL, // Cell layout + GTK_WIDGET(desktop->canvas)); // Focus widget + g_signal_connect( G_OBJECT(act), "changed", G_CALLBACK(sp_text_fontstyle_value_changed), holder ); gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); g_object_set_data( holder, "TextFontStyleAction", act ); -- cgit v1.2.3 From bf7c3e8d98b557cb64447804399797d93e1cedc0 Mon Sep 17 00:00:00 2001 From: John Smith Date: Wed, 19 Sep 2012 10:52:19 +0900 Subject: Fix for 643150 : Auto-palette swatches duplicated on copy and paste (bzr r11677) --- src/document.cpp | 29 ++++++++++++++++++++++++++--- src/file.cpp | 9 +++------ src/id-clash.cpp | 28 ++++++++++++++++++++++++++++ src/id-clash.h | 1 + src/ink-comboboxentry-action.cpp | 2 +- src/sp-gradient.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/sp-gradient.h | 1 + 7 files changed, 96 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/document.cpp b/src/document.cpp index 9efd9d923..e28356969 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1453,10 +1453,33 @@ void SPDocument::importDefs(SPDocument *source) prevent_id_clashes(source, this); for (Inkscape::XML::Node *def = defs->firstChild() ; def ; def = def->next()) { - Inkscape::XML::Node * dup = def->duplicate(this->getReprDoc()); - target_defs->appendChild(dup); - Inkscape::GC::release(dup); + + // Prevent duplicates of solid swatches by checking if equivalent swatch already exists + gboolean duplicate = false; + SPObject *src = source->getObjectByRepr(def); + if (src && SP_IS_GRADIENT(src)) { + SPGradient *gr = SP_GRADIENT(src); + if (gr->isSolid() || gr->getVector()->isSolid()) { + for (SPObject *trg = this->getDefs()->firstChild() ; trg ; trg = trg->getNext()) { + if (trg && SP_IS_GRADIENT(trg) && src != trg) { + if (gr->isEquivalent(SP_GRADIENT(trg))) { + // Change object references to the existing equivalent gradient + change_def_references(src, trg); + duplicate = true; + break; + } + } + } + } + } + + if (!duplicate) { + Inkscape::XML::Node * dup = def->duplicate(this->getReprDoc()); + target_defs->appendChild(dup); + Inkscape::GC::release(dup); + } } + } /* diff --git a/src/file.cpp b/src/file.cpp index dcdae1700..778306d5d 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -1142,6 +1142,8 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri, place_to_insert = in_doc->getRoot(); } + in_doc->importDefs(doc); + // Construct a new object representing the imported image, // and insert it into the current document. SPObject *new_obj = NULL; @@ -1162,12 +1164,7 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri, // don't lose top-level defs or style elements else if (child->getRepr()->type() == Inkscape::XML::ELEMENT_NODE) { const gchar *tag = child->getRepr()->name(); - if (!strcmp(tag, "svg:defs")) { - for ( SPObject *x = child->firstChild(); x; x = x->getNext() ) { - in_defs->getRepr()->addChild(x->getRepr()->duplicate(xml_in_doc), last_def); - } - } - else if (!strcmp(tag, "svg:style")) { + if (!strcmp(tag, "svg:style")) { in_doc->getRoot()->appendChildRepr(child->getRepr()->duplicate(xml_in_doc)); } } diff --git a/src/id-clash.cpp b/src/id-clash.cpp index d8299652b..05a3149fc 100644 --- a/src/id-clash.cpp +++ b/src/id-clash.cpp @@ -26,6 +26,7 @@ #include "xml/node.h" #include "xml/repr.h" #include "sp-root.h" +#include "sp-gradient.h" typedef enum { REF_HREF, REF_STYLE, REF_URL, REF_CLIPBOARD } ID_REF_TYPE; @@ -291,6 +292,33 @@ prevent_id_clashes(SPDocument *imported_doc, SPDocument *current_doc) delete refmap; } +/* + * Change any references of svg:def from_obj into to_obj + */ +void +change_def_references(SPObject *from_obj, SPObject *to_obj) +{ + refmap_type *refmap = new refmap_type; + id_changelist_type id_changes; + SPDocument *current_doc = from_obj->document; + std::string old_id(from_obj->getId()); + + find_references(current_doc->getRoot(), refmap); + + refmap_type::const_iterator pos = refmap->find(old_id); + if (pos != refmap->end()) { + std::list::const_iterator it; + const std::list::const_iterator it_end = pos->second.end(); + for (it = pos->second.begin(); it != it_end; ++it) { + if (it->type == REF_STYLE) { + sp_style_set_property_url(it->elem, it->attr, to_obj, false); + } + } + } + + delete refmap; +} + /* * Change the id of a SPObject to new_name * If there is an id clash then rename to something similar diff --git a/src/id-clash.h b/src/id-clash.h index de3cd29d3..f93bd3d72 100644 --- a/src/id-clash.h +++ b/src/id-clash.h @@ -5,6 +5,7 @@ void prevent_id_clashes(SPDocument *imported_doc, SPDocument *current_doc); void rename_id(SPObject *elem, Glib::ustring const &newname); +void change_def_references(SPObject *replace_obj, SPObject *with_obj); #endif /* !SEEN_ID_CLASH_H */ diff --git a/src/ink-comboboxentry-action.cpp b/src/ink-comboboxentry-action.cpp index 6e6071654..99a48ae5d 100644 --- a/src/ink-comboboxentry-action.cpp +++ b/src/ink-comboboxentry-action.cpp @@ -807,7 +807,7 @@ gboolean keypress_cb( GtkWidget *widget, GdkEventKey *event, gpointer data ) switch ( key ) { - // TODO Add bindings for Esc/Tab/LeftTab + // TODO Add bindings for Tab/LeftTab case GDK_KEY_Escape: { //gtk_spin_button_set_value( GTK_SPIN_BUTTON(widget), action->private_data->lastVal ); diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index 262c35db1..5efa3c84f 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -346,6 +346,41 @@ void SPGradient::setSwatch( bool swatch ) } } + +/** + * return true if this gradient is "equivalent" to that gradient. + * Equivalent meaning they have the same stop count, same stop colors and same stop opacity + * @param that - A gradient to compare this to + */ +gboolean SPGradient::isEquivalent(SPGradient *that) +{ + //TODO Make this work for mesh gradients + + if (this->getStopCount() != that->getStopCount()) + return FALSE; + + if (this->hasStops() != that->hasStops()) + return FALSE; + + if (!this->getVector() || !that->getVector()) + return FALSE; + + SPStop *as = this->getVector()->getFirstStop(); + SPStop *bs = that->getVector()->getFirstStop(); + + while (as && bs) { + if (!as->getEffectiveColor().isClose(bs->getEffectiveColor(), 0.001) || + as->offset != bs->offset) { + return FALSE; + } + as = as->getNextStop(); + bs = bs->getNextStop(); + } + + return TRUE; +} + + /** * Return stop's color as 32bit value. */ @@ -2211,6 +2246,7 @@ sp_meshgradient_repr_write(SPMeshGradient *mg) mg->array.write( mg ); } + /* Local Variables: mode:c++ diff --git a/src/sp-gradient.h b/src/sp-gradient.h index 61b459eee..a21a413f4 100644 --- a/src/sp-gradient.h +++ b/src/sp-gradient.h @@ -143,6 +143,7 @@ public: SPStop* getFirstStop(); int getStopCount() const; + gboolean isEquivalent(SPGradient *b); /** Mesh Gradients **************/ -- cgit v1.2.3 From e399f5cabc2a4ec7ef739cabfbc9b8284307ba32 Mon Sep 17 00:00:00 2001 From: John Smith Date: Wed, 19 Sep 2012 11:48:33 +0900 Subject: Fix for 509891 : User defined linear gradient angle (bzr r11678) --- src/gradient-chemistry.cpp | 46 +++++++++++++++++++++++++++++++--- src/ui/dialog/inkscape-preferences.cpp | 5 ++++ src/ui/dialog/inkscape-preferences.h | 1 + 3 files changed, 48 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index 6b1376fb5..34934f75b 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -20,6 +20,9 @@ #include <2geom/transforms.h> #include <2geom/bezier-curve.h> +#include <2geom/crossing.h> +#include <2geom/line.h> +#include <2geom/angle.h> #include "style.h" #include "document-private.h" @@ -355,10 +358,45 @@ SPGradient *sp_gradient_reset_to_userspace(SPGradient *gr, SPItem *item) g_free(c); } } else if (SP_IS_LINEARGRADIENT(gr)) { - sp_repr_set_svg_double(repr, "x1", (center - Geom::Point(width/2, 0))[Geom::X]); - sp_repr_set_svg_double(repr, "y1", (center - Geom::Point(width/2, 0))[Geom::Y]); - sp_repr_set_svg_double(repr, "x2", (center + Geom::Point(width/2, 0))[Geom::X]); - sp_repr_set_svg_double(repr, "y2", (center + Geom::Point(width/2, 0))[Geom::Y]); + + // Assume horizontal gradient by default (as per SVG 1.1) + Geom::Point pStart = center - Geom::Point(width/2, 0); + Geom::Point pEnd = center + Geom::Point(width/2, 0); + + // Get the preferred gradient angle from prefs + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + double angle = prefs->getDouble("/dialogs/gradienteditor/angle", 0.0); + + if (angle != 0.0) { + + Geom::Line grl(center, Geom::deg_to_rad(angle)); + Geom::LineSegment bbl1(bbox->corner(0), bbox->corner(1)); + Geom::LineSegment bbl2(bbox->corner(1), bbox->corner(2)); + Geom::LineSegment bbl3(bbox->corner(2), bbox->corner(3)); + Geom::LineSegment bbl4(bbox->corner(3), bbox->corner(0)); + + // Find where our gradient line intersects the bounding box. + if (intersection(bbl1, grl)) { + pStart = bbl1.pointAt((*intersection(bbl1, grl)).ta); + pEnd = bbl3.pointAt((*intersection(bbl3, grl)).ta); + if (intersection(bbl1, grl.ray(grl.angle()))) { + std::swap(pStart, pEnd); + } + } else if (intersection(bbl2, grl)) { + pStart = bbl2.pointAt((*intersection(bbl2, grl)).ta); + pEnd = bbl4.pointAt((*intersection(bbl4, grl)).ta); + if (intersection(bbl2, grl.ray(grl.angle()))) { + std::swap(pStart, pEnd); + } + } + + } + + sp_repr_set_svg_double(repr, "x1", pStart[Geom::X]); + sp_repr_set_svg_double(repr, "y1", pStart[Geom::Y]); + sp_repr_set_svg_double(repr, "x2", pEnd[Geom::X]); + sp_repr_set_svg_double(repr, "y2", pEnd[Geom::Y]); + } else { // Mesh // THIS IS BEING CALLED TWICE WHENEVER A NEW GRADIENT IS CREATED, WRITING HERE CAUSES PROBLEMS diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 7ee2aa444..9182aaad1 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -478,6 +478,11 @@ void InkscapePreferences::initPageTools() _page_gradient.add_line( false, "", _misc_gradienteditor, "", _("When on, the Gradient Edit button in the Fill & Stroke dialog will show the legacy Gradient Editor dialog, when off the Gradient Tool will be used"), true); + _misc_gradientangle.init("/dialogs/gradienteditor/angle", -359, 359, 1, 90, 0, false, false); + _page_gradient.add_line( false, _("Linear gradient _angle:"), _misc_gradientangle, "", + _("Default angle of new linear gradients in degrees (clockwise from horizontal"), false); + + //Dropper this->AddPage(_page_dropper, _("Dropper"), iter_tools, PREFS_PAGE_TOOLS_DROPPER); this->AddSelcueCheckbox(_page_dropper, "/tools/dropper", true); diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h index 948a3f87b..f4bfe5565 100644 --- a/src/ui/dialog/inkscape-preferences.h +++ b/src/ui/dialog/inkscape-preferences.h @@ -300,6 +300,7 @@ protected: UI::Widget::PrefCheckButton _misc_default_metadata; UI::Widget::PrefCheckButton _misc_forkvectors; UI::Widget::PrefCheckButton _misc_gradienteditor; + UI::Widget::PrefSpinButton _misc_gradientangle; UI::Widget::PrefCheckButton _misc_scripts; UI::Widget::PrefCheckButton _misc_namedicon_delay; -- cgit v1.2.3 From 75ac11e8ff98a2509abcb9f4dea395fd9339f9de Mon Sep 17 00:00:00 2001 From: John Smith Date: Wed, 19 Sep 2012 12:43:35 +0900 Subject: Fix for 638943 : feComponentTransfer resource add causing CRITICAL messages in effect Poster Paint (bzr r11679) --- src/filters/componenttransfer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/filters/componenttransfer.cpp b/src/filters/componenttransfer.cpp index 99d8616f4..8cc388dd0 100644 --- a/src/filters/componenttransfer.cpp +++ b/src/filters/componenttransfer.cpp @@ -100,7 +100,7 @@ sp_feComponentTransfer_build(SPObject *object, SPDocument *document, Inkscape::X /*LOAD ATTRIBUTES FROM REPR HERE*/ //do we need this? - document->addResource("feComponentTransfer", object); + //document->addResource("feComponentTransfer", object); } static void sp_feComponentTransfer_children_modified(SPFeComponentTransfer *sp_componenttransfer) -- cgit v1.2.3 From 5462d876b6405529c3edd063d7dc18cad398c5ae Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Thu, 20 Sep 2012 08:15:42 +0200 Subject: Preferences. New Bitmap Override file resolution option, by Daniel Wagenaar. (bzr r11681) --- src/extension/internal/gdkpixbuf-input.cpp | 9 +++++---- src/ui/dialog/inkscape-preferences.cpp | 3 +++ src/ui/dialog/inkscape-preferences.h | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/extension/internal/gdkpixbuf-input.cpp b/src/extension/internal/gdkpixbuf-input.cpp index 6e6038993..abfad518f 100644 --- a/src/extension/internal/gdkpixbuf-input.cpp +++ b/src/extension/internal/gdkpixbuf-input.cpp @@ -80,6 +80,7 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri) double width = gdk_pixbuf_get_width(pb); double height = gdk_pixbuf_get_height(pb); double defaultxdpi = prefs->getDouble("/dialogs/import/defaultxdpi/value", PX_PER_IN); + bool forcexdpi = prefs->getBool("/dialogs/import/forcexdpi"); ImageResolution *ir = 0; double xscale = 1; double yscale = 1; @@ -91,9 +92,9 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri) xscale = 72.0 / (double)dpi; } } else { - if (!ir) + if (!ir && !forcexdpi) ir = new ImageResolution(uri); - if (ir->ok()) + if (ir && ir->ok()) xscale = 900.0 / floor(10.*ir->x() + .5); // round-off to 0.1 dpi else xscale = 90.0 / defaultxdpi; @@ -107,9 +108,9 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri) yscale = 72.0 / (double)dpi; } } else { - if (!ir) + if (!ir && !forcexdpi) ir = new ImageResolution(uri); - if (ir->ok()) + if (ir && ir->ok()) yscale = 900.0 / floor(10.*ir->y() + .5); // round-off to 0.1 dpi else yscale = 90.0 / defaultxdpi; diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 9182aaad1..62f48cce0 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -1394,6 +1394,9 @@ void InkscapePreferences::initPageBitmaps() _importexport_import_res.init("/dialogs/import/defaultxdpi/value", 0.0, 6000.0, 1.0, 1.0, PX_PER_IN, true, false); _page_bitmaps.add_line( false, _("Default _import resolution:"), _importexport_import_res, _("dpi"), _("Default bitmap resolution (in dots per inch) for bitmap import"), false); + _importexport_import_res_override.init(_("Override file resolution"), "/dialogs/import/forcexdpi", false); + _page_bitmaps.add_line( false, "", _importexport_import_res_override, "", + _("Use default bitmap resolution in favor of information from file")); this->AddPage(_page_bitmaps, _("Bitmaps"), PREFS_PAGE_BITMAPS); } diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h index f4bfe5565..d60035515 100644 --- a/src/ui/dialog/inkscape-preferences.h +++ b/src/ui/dialog/inkscape-preferences.h @@ -290,6 +290,7 @@ protected: UI::Widget::PrefSpinButton _importexport_export_res; UI::Widget::PrefSpinButton _importexport_import_res; + UI::Widget::PrefCheckButton _importexport_import_res_override; UI::Widget::PrefSlider _snap_delay; UI::Widget::PrefSlider _snap_weight; UI::Widget::PrefCheckButton _font_dialog; -- cgit v1.2.3 From d99ebfe27cca750966d0483360394a3039cb365e Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Thu, 20 Sep 2012 16:11:29 +0200 Subject: Fix for Bug #944787 (The command to follow link does not work). (bzr r11684) --- src/interface.cpp | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/interface.cpp b/src/interface.cpp index b10ba3077..710211fe7 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -1766,15 +1766,16 @@ void ContextMenu::MakeItemMenu (void) AddSeparator(); /* Select item */ - mi = manage(new Gtk::MenuItem(_("_Select This"),1)); - if (_desktop->selection->includes(_item)) { - mi->set_sensitive(FALSE); - } else { - mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ItemSelectThis)); + if (Inkscape::Verb::getbyid( "org.inkscape.followlink" )) { + mi = manage(new Gtk::MenuItem(_("_Select This"),1)); + if (_desktop->selection->includes(_item)) { + mi->set_sensitive(FALSE); + } else { + mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ItemSelectThis)); + } + mi->show(); + append(*mi); } - mi->show(); - append(*mi); - mi = manage(new Gtk::MenuItem(_("Select Same"))); @@ -2034,7 +2035,18 @@ void ContextMenu::AnchorLinkProperties(void) void ContextMenu::AnchorLinkFollow(void) { - /* shell out to an external browser here */ + + if (_desktop->selection->isEmpty()) { + _desktop->selection->set(_item); + } + // Opening the selected links with a python extension + Inkscape::Verb *verb = Inkscape::Verb::getbyid( "org.inkscape.followlink" ); + if (verb) { + SPAction *action = verb->get_action(_desktop); + if (action) { + sp_action_perform(action, NULL); + } + } } void ContextMenu::AnchorLinkRemove(void) -- cgit v1.2.3 From bac4df147de363a0774548acd63d367a09ab50d3 Mon Sep 17 00:00:00 2001 From: Kris De Gussem Date: Thu, 20 Sep 2012 22:40:55 +0200 Subject: some memleak fixes (Bug #1043571) (bzr r11686) --- src/attribute-rel-util.cpp | 17 +++++++---------- src/attribute-rel-util.h | 2 +- src/extension/dbus/document-interface.cpp | 20 ++++++++++++++------ src/id-clash.cpp | 7 +++---- src/preferences.cpp | 12 ++++++------ src/sp-object.cpp | 10 ++-------- src/style.cpp | 12 +++++------- src/style.h | 2 +- src/ui/widget/style-swatch.cpp | 17 ++++++++--------- src/xml/repr-css.cpp | 29 +++++++++++------------------ src/xml/repr.h | 2 +- src/xml/simple-node.cpp | 7 ++----- 12 files changed, 61 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/src/attribute-rel-util.cpp b/src/attribute-rel-util.cpp index 239e359e2..cf94c0c1e 100644 --- a/src/attribute-rel-util.cpp +++ b/src/attribute-rel-util.cpp @@ -128,17 +128,13 @@ void sp_attribute_clean_style(Node *repr, unsigned int flags) { // Find element's style SPCSSAttr *css = sp_repr_css_attr( repr, "style" ); - sp_attribute_clean_style(repr, css, flags); - // g_warning( "sp_repr_write_stream_element(): Final style:" ); - //sp_repr_css_print( css ); - // Convert css node's properties data to string and set repr node's attribute "style" to that string. // sp_repr_css_set( repr, css, "style"); // Don't use as it will cause loop. - gchar *value = sp_repr_css_write_string(css); - repr->setAttribute("style", value); - if (value) g_free (value); + Glib::ustring value; + sp_repr_css_write_string(css, value); + repr->setAttribute("style", value.c_str()); sp_repr_css_attr_unref( css ); } @@ -147,7 +143,7 @@ void sp_attribute_clean_style(Node *repr, unsigned int flags) { /** * Clean CSS style on an element. */ -gchar * sp_attribute_clean_style(Node *repr, gchar const *string, unsigned int flags) { +Glib::ustring sp_attribute_clean_style(Node *repr, gchar const *string, unsigned int flags) { g_return_val_if_fail (repr != NULL, NULL); g_return_val_if_fail (repr->type() == Inkscape::XML::ELEMENT_NODE, NULL); @@ -155,11 +151,12 @@ gchar * sp_attribute_clean_style(Node *repr, gchar const *string, unsigned int f SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_attr_add_from_string( css, string ); sp_attribute_clean_style(repr, css, flags); - gchar* string_cleaned = sp_repr_css_write_string( css ); + Glib::ustring string_cleaned; + sp_repr_css_write_string (css, string_cleaned); sp_repr_css_attr_unref( css ); - return string_cleaned; + return string_cleaned; } diff --git a/src/attribute-rel-util.h b/src/attribute-rel-util.h index d9d270a13..449a66d9e 100644 --- a/src/attribute-rel-util.h +++ b/src/attribute-rel-util.h @@ -61,7 +61,7 @@ void sp_attribute_clean_style(Node *repr, unsigned int flags); /** * Clean style properties for one style string. */ -gchar* sp_attribute_clean_style(Node *repr, gchar const *string, unsigned int flags); +Glib::ustring sp_attribute_clean_style(Node *repr, gchar const *string, unsigned int flags); /** * Clean style properties for one CSS. diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index 66d1c5dfa..56d1dfdbd 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -223,11 +223,12 @@ dbus_create_node (SPDesktop *desk, const gchar *type) */ gchar *finish_create_shape (DocumentInterface *object, GError ** /*error*/, Inkscape::XML::Node *newNode, gchar *desc) { - SPCSSAttr *style = sp_desktop_get_style(object->desk, TRUE); if (style) { - newNode->setAttribute("style", sp_repr_css_write_string(style), TRUE); + Glib::ustring str; + sp_repr_css_write_string(style, str); + newNode->setAttribute("style", str.c_str(), TRUE); } else { newNode->setAttribute("style", "fill:#0000ff;fill-opacity:1;stroke:#c900b9;stroke-width:0;stroke-miterlimit:0;stroke-opacity:1;stroke-dasharray:none", TRUE); @@ -530,7 +531,7 @@ gchar *document_interface_node(DocumentInterface *object, gchar *type, GError ** } /**************************************************************************** - ENVIORNMENT FUNCTIONS + ENVIRONMENT FUNCTIONS ****************************************************************************/ gdouble document_interface_document_get_width (DocumentInterface *object) @@ -547,7 +548,9 @@ document_interface_document_get_height (DocumentInterface *object) gchar *document_interface_document_get_css(DocumentInterface *object, GError ** /*error*/) { SPCSSAttr *current = (object->desk)->current; - return sp_repr_css_write_string(current); + Glib::ustring str; + sp_repr_css_write_string(current, str); + return (str.empty() ? NULL : g_strdup (str.c_str())); } gboolean document_interface_document_merge_css(DocumentInterface *object, @@ -768,7 +771,9 @@ document_interface_modify_css (DocumentInterface *object, gchar *shape, SPCSSAttr * oldstyle = sp_repr_css_attr (node, style); sp_repr_css_set_property(oldstyle, cssattrb, newval); - node->setAttribute (style, sp_repr_css_write_string (oldstyle), TRUE); + Glib::ustring str; + sp_repr_css_write_string (oldstyle, str); + node->setAttribute (style, str.c_str(), TRUE); return TRUE; } @@ -791,7 +796,10 @@ document_interface_merge_css (DocumentInterface *object, gchar *shape, SPCSSAttr * oldstyle = sp_repr_css_attr (node, style); sp_repr_css_merge(oldstyle, newstyle); - node->setAttribute (style, sp_repr_css_write_string (oldstyle), TRUE); + Glib::ustring str; + sp_repr_css_write_string (oldstyle, str); + node->setAttribute (style, str.c_str(), TRUE); + return TRUE; } diff --git a/src/id-clash.cpp b/src/id-clash.cpp index 05a3149fc..7a1e000fb 100644 --- a/src/id-clash.cpp +++ b/src/id-clash.cpp @@ -260,10 +260,9 @@ fix_up_refs(const refmap_type *refmap, const id_changelist_type &id_changes) gchar *url = g_strdup_printf("url(#%s)", obj->getId()); sp_repr_css_set_property(style, it->attr, url); g_free(url); - gchar *style_string = sp_repr_css_write_string(style); - it->elem->getRepr()->setAttribute("style", style_string); - g_free(style_string); - + Glib::ustring style_string; + sp_repr_css_write_string(style, style_string); + it->elem->getRepr()->setAttribute("style", style_string.c_str()); } else { g_assert(0); // shouldn't happen } diff --git a/src/preferences.cpp b/src/preferences.cpp index 4615fd6e1..1f985a629 100644 --- a/src/preferences.cpp +++ b/src/preferences.cpp @@ -489,18 +489,18 @@ void Preferences::setString(Glib::ustring const &pref_path, Glib::ustring const void Preferences::setStyle(Glib::ustring const &pref_path, SPCSSAttr *style) { - gchar *css_str = sp_repr_css_write_string(style); - _setRawValue(pref_path, css_str); - g_free(css_str); + Glib::ustring css_str; + sp_repr_css_write_string(style, css_str); + _setRawValue(pref_path, css_str.c_str()); } void Preferences::mergeStyle(Glib::ustring const &pref_path, SPCSSAttr *style) { SPCSSAttr *current = getStyle(pref_path); sp_repr_css_merge(current, style); - gchar *css_str = sp_repr_css_write_string(current); - _setRawValue(pref_path, css_str); - g_free(css_str); + Glib::ustring css_str; + sp_repr_css_write_string(current, css_str); + _setRawValue(pref_path, css_str.c_str()); sp_repr_css_attr_unref(current); } diff --git a/src/sp-object.cpp b/src/sp-object.cpp index 892c89a15..9ceeaf262 100644 --- a/src/sp-object.cpp +++ b/src/sp-object.cpp @@ -1031,15 +1031,9 @@ Inkscape::XML::Node * SPObject::sp_object_private_write(SPObject *object, Inksca if( prefs->getBool("/options/svgoutput/check_on_editing") ) { unsigned int flags = sp_attribute_clean_get_prefs(); - gchar *s_cleaned = sp_attribute_clean_style( repr, s, flags ); - - // g_warning("SPObject::sp_object_private_write: %s", object->getId() ); - // g_warning(" old: :%s:", repr->attribute("style") ); - // g_warning(" new: :%s:", s ); - // g_warning(" cleaned: :%s:", s_cleaned ); - + Glib::ustring s_cleaned = sp_attribute_clean_style( repr, s, flags ); g_free( s ); - s = s_cleaned; + s = (s_cleaned.empty() ? NULL : g_strdup (s_cleaned.c_str())); } if( s == NULL || strcmp(s,"") == 0 ) { diff --git a/src/style.cpp b/src/style.cpp index 2facc86d8..616474298 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -3890,10 +3890,9 @@ sp_style_write_istring(gchar *p, gint const len, gchar const *const key, if (val->inherit) { res = g_snprintf(p, len, "%s:inherit;", key); } else { - gchar *val_quoted = css2_escape_quote(val->value); - if (val_quoted) { - res = g_snprintf(p, len, "%s:%s;", key, val_quoted); - g_free (val_quoted); + Glib::ustring val_quoted = css2_escape_quote(val->value); + if (~val_quoted.empty()) { + res = g_snprintf(p, len, "%s:%s;", key, val_quoted.c_str()); } } } @@ -4710,8 +4709,7 @@ attribute_unquote(gchar const *val) /** * Quote and/or escape string for writing to CSS (style=). Returned value must be g_free'd. */ -gchar * -css2_escape_quote(gchar const *val) { +Glib::ustring css2_escape_quote(gchar const *val) { Glib::ustring t; bool quote = false; @@ -4755,7 +4753,7 @@ css2_escape_quote(gchar const *val) { t.push_back('\''); } - return (t.empty() ? NULL : g_strdup (t.c_str())); + return t; } /* diff --git a/src/style.h b/src/style.h index 576167645..7c64ea3d8 100644 --- a/src/style.h +++ b/src/style.h @@ -617,7 +617,7 @@ void sp_style_unset_property_attrs(SPObject *o); void sp_style_set_property_url (SPObject *item, gchar const *property, SPObject *linked, bool recursive); gchar *attribute_unquote(gchar const *val); -gchar *css2_escape_quote(gchar const *val); +Glib::ustring css2_escape_quote(gchar const *val); #endif // SEEN_SP_STYLE_H diff --git a/src/ui/widget/style-swatch.cpp b/src/ui/widget/style-swatch.cpp index 1ee26e803..857ae7019 100644 --- a/src/ui/widget/style-swatch.cpp +++ b/src/ui/widget/style-swatch.cpp @@ -227,8 +227,7 @@ StyleSwatch::setWatchedTool(const char *path, bool synthesize) } -void -StyleSwatch::setStyle(SPCSSAttr *css) +void StyleSwatch::setStyle(SPCSSAttr *css) { if (_css) sp_repr_css_attr_unref (_css); @@ -239,18 +238,18 @@ StyleSwatch::setStyle(SPCSSAttr *css) _css = sp_repr_css_attr_new(); sp_repr_css_merge(_css, css); - gchar const *css_string = sp_repr_css_write_string (_css); + Glib::ustring css_string; + sp_repr_css_write_string (_css, css_string); SPStyle *temp_spstyle = sp_style_new(SP_ACTIVE_DOCUMENT); - if (css_string) - sp_style_merge_from_style_string (temp_spstyle, css_string); - + if (~css_string.empty()) { + sp_style_merge_from_style_string (temp_spstyle, css_string.c_str()); + } + setStyle (temp_spstyle); - sp_style_unref (temp_spstyle); } -void -StyleSwatch::setStyle(SPStyle *query) +void StyleSwatch::setStyle(SPStyle *query) { _place[SS_FILL].remove(); _place[SS_STROKE].remove(); diff --git a/src/xml/repr-css.cpp b/src/xml/repr-css.cpp index 594ac83c6..7fba4d7c6 100644 --- a/src/xml/repr-css.cpp +++ b/src/xml/repr-css.cpp @@ -270,10 +270,9 @@ double sp_repr_css_double_property(SPCSSAttr *css, gchar const *name, double def /** * Write a style attribute string from a list of properties stored in an SPCSAttr object. */ -gchar *sp_repr_css_write_string(SPCSSAttr *css) +void sp_repr_css_write_string(SPCSSAttr *css, Glib::ustring &str) { - Glib::ustring buffer; - + str.clear(); for ( List iter = css->attributeList() ; iter ; ++iter ) { @@ -281,26 +280,21 @@ gchar *sp_repr_css_write_string(SPCSSAttr *css) continue; } - buffer.append(g_quark_to_string(iter->key)); - buffer.push_back(':'); + str.append(g_quark_to_string(iter->key)); + str.push_back(':'); if (!strcmp(g_quark_to_string(iter->key), "font-family") || !strcmp(g_quark_to_string(iter->key), "-inkscape-font-specification")) { // we only quote font-family/font-specification, as SPStyle does - gchar *val_quoted = css2_escape_quote (iter->value); - if (val_quoted) { - buffer.append(val_quoted); - g_free (val_quoted); - } + Glib::ustring val_quoted = css2_escape_quote (iter->value); + str.append(val_quoted); } else { - buffer.append(iter->value); // unquoted + str.append(iter->value); // unquoted } if (rest(iter)) { - buffer.push_back(';'); + str.push_back(';'); } } - - return (buffer.empty() ? NULL : g_strdup (buffer.c_str())); } /** @@ -312,7 +306,8 @@ void sp_repr_css_set(Node *repr, SPCSSAttr *css, gchar const *attr) g_assert(css != NULL); g_assert(attr != NULL); - gchar *value = sp_repr_css_write_string(css); + Glib::ustring value; + sp_repr_css_write_string(css, value); /* * If the new value is different from the old value, this will sometimes send a signal via @@ -320,9 +315,7 @@ void sp_repr_css_set(Node *repr, SPCSSAttr *css, gchar const *attr) * SPObject::sp_object_repr_attr_changed and thus updates the object's SPStyle. This update * results in another call to repr->setAttribute(). */ - repr->setAttribute(attr, value); - - if (value) g_free (value); + repr->setAttribute(attr, value.c_str()); } /** diff --git a/src/xml/repr.h b/src/xml/repr.h index 86a798e3e..debd0f489 100644 --- a/src/xml/repr.h +++ b/src/xml/repr.h @@ -79,7 +79,7 @@ void sp_repr_css_unset_property(SPCSSAttr *css, gchar const *name); bool sp_repr_css_property_is_unset(SPCSSAttr *css, gchar const *name); double sp_repr_css_double_property(SPCSSAttr *css, gchar const *name, double defval); -gchar *sp_repr_css_write_string(SPCSSAttr *css); +void sp_repr_css_write_string(SPCSSAttr *css, Glib::ustring &str); void sp_repr_css_set(Inkscape::XML::Node *repr, SPCSSAttr *css, gchar const *key); void sp_repr_css_merge(SPCSSAttr *dst, SPCSSAttr *src); void sp_repr_css_attr_add_from_string(SPCSSAttr *css, const gchar *data); diff --git a/src/xml/simple-node.cpp b/src/xml/simple-node.cpp index c197d648b..55bd28afe 100644 --- a/src/xml/simple-node.cpp +++ b/src/xml/simple-node.cpp @@ -318,8 +318,7 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_ // Check usefulness of attributes on elements in the svg namespace, optionally don't add them to tree. Glib::ustring element = g_quark_to_string(_name); - //g_warning("setAttribute: %s: %s: %s", element.c_str(), name, value); - + // g_message("setAttribute: %s: %s: %s", element.c_str(), name, value); gchar* cleaned_value = g_strdup( value ); // Only check elements in SVG name space and don't block setting attribute to NULL. @@ -347,7 +346,7 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_ // tree (and thus has no parent), default values will not be tested. if( !strcmp( name, "style" ) && (flags >= SP_ATTR_CLEAN_STYLE_WARN) ) { g_free( cleaned_value ); - cleaned_value = sp_attribute_clean_style( this, value, flags ); + cleaned_value = const_cast(sp_attribute_clean_style( this, value, flags ).c_str()); // if( g_strcmp0( value, cleaned_value ) ) { // g_warning( "SimpleNode::setAttribute: %s", id.c_str() ); // g_warning( " original: %s", value); @@ -401,9 +400,7 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_ _observers.notifyAttributeChanged(*this, key, old_value, new_value); //g_warning( "setAttribute notified: %s: %s: %s: %s", name, element.c_str(), old_value, new_value ); } - g_free( cleaned_value ); - } void SimpleNode::addChild(Node *generic_child, Node *generic_ref) { -- cgit v1.2.3 From 3d71bbcdde6255ee9e587124aaccf58dd8741ed6 Mon Sep 17 00:00:00 2001 From: su_v Date: Fri, 21 Sep 2012 14:24:26 +0200 Subject: Fix for bug #1053024: set current layer from template in new blank document after closing last window Fixed bugs: - https://launchpad.net/bugs/1053024 (bzr r11689) --- src/interface.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/interface.cpp b/src/interface.cpp index 710211fe7..acd56f8da 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -322,6 +322,7 @@ sp_ui_close_view(GtkWidget */*widget*/) SPDocument *doc = SPDocument::createNewDoc( templateUri.c_str() , TRUE, true ); dt->change_document(doc); sp_namedview_window_from_document(dt); + sp_namedview_update_layers_from_document(dt); return; } -- cgit v1.2.3 From 5ab9fc74c53a9e59dd4f46a1f8ff027f878e7836 Mon Sep 17 00:00:00 2001 From: John Smith Date: Sat, 22 Sep 2012 10:43:42 +0900 Subject: Fix for 1014988 : Add gimp spin scale widget (bzr r11690) --- src/ui/widget/Makefile_insert | 4 + src/ui/widget/gimpspinscale.c | 1089 +++++++++++++++++++++++++++++++++++++++++ src/ui/widget/gimpspinscale.h | 76 +++ src/ui/widget/spin-scale.cpp | 248 ++++++++++ src/ui/widget/spin-scale.h | 117 +++++ 5 files changed, 1534 insertions(+) create mode 100644 src/ui/widget/gimpspinscale.c create mode 100644 src/ui/widget/gimpspinscale.h create mode 100644 src/ui/widget/spin-scale.cpp create mode 100644 src/ui/widget/spin-scale.h (limited to 'src') diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert index 8589f16b0..bbda64648 100644 --- a/src/ui/widget/Makefile_insert +++ b/src/ui/widget/Makefile_insert @@ -19,6 +19,8 @@ ink_common_sources += \ ui/widget/entry.h \ ui/widget/filter-effect-chooser.h \ ui/widget/filter-effect-chooser.cpp \ + ui/widget/gimpspinscale.c \ + ui/widget/gimpspinscale.h \ ui/widget/frame.cpp \ ui/widget/frame.h \ ui/widget/imageicon.cpp \ @@ -62,6 +64,8 @@ ink_common_sources += \ ui/widget/selected-style.cpp \ ui/widget/spinbutton.h \ ui/widget/spinbutton.cpp \ + ui/widget/spin-scale.h \ + ui/widget/spin-scale.cpp \ ui/widget/spin-slider.h \ ui/widget/spin-slider.cpp \ ui/widget/style-subject.h \ diff --git a/src/ui/widget/gimpspinscale.c b/src/ui/widget/gimpspinscale.c new file mode 100644 index 000000000..1b7ac7bfe --- /dev/null +++ b/src/ui/widget/gimpspinscale.c @@ -0,0 +1,1089 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpspinscale.c + * Copyright (C) 2010 Michael Natterer + * 2012 Øyvind Kolås + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "gimpspinscale.h" + + +enum +{ + PROP_0, + PROP_LABEL, + PROP_FOCUS_WIDGET +}; + +typedef enum +{ + TARGET_NUMBER, + TARGET_UPPER, + TARGET_LOWER +#if WITH_GTKMM_3_0 + ,TARGET_NONE +#endif +} SpinScaleTarget; + +typedef enum +{ + APPEARANCE_FULL = 1, /* Full size suitable for tablets */ + APPEARANCE_COMPACT, /* Compact, suitable for desktops with mouse control */ +} SpinScaleAppearance; + +typedef struct _GimpSpinScalePrivate GimpSpinScalePrivate; + +struct _GimpSpinScalePrivate +{ + gchar *label; + + gboolean scale_limits_set; + gdouble scale_lower; + gdouble scale_upper; + gdouble gamma; + + PangoLayout *layout; + gboolean changing_value; + gboolean relative_change; + gdouble start_x; + gdouble start_value; + + GtkWidget* focusWidget; + gboolean transferFocus; + SpinScaleAppearance appearanceMode; +}; + +#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + GIMP_TYPE_SPIN_SCALE, \ + GimpSpinScalePrivate)) + + +static void gimp_spin_scale_dispose (GObject *object); +static void gimp_spin_scale_finalize (GObject *object); +static void gimp_spin_scale_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_spin_scale_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static void gimp_spin_scale_style_set (GtkWidget *widget, + GtkStyle *prev_style); + +#if WITH_GTKMM_3_0 +static void gimp_spin_scale_get_preferred_width (GtkWidget *widget, + gint *minimum_width, + gint *natural_width); +static void gimp_spin_scale_get_preferred_height (GtkWidget *widget, + gint *minimum_width, + gint *natural_width); +static gboolean gimp_spin_scale_draw (GtkWidget *widget, + cairo_t *cr); +#else +static void gimp_spin_scale_size_request (GtkWidget *widget, + GtkRequisition *requisition); + +static gboolean gimp_spin_scale_expose (GtkWidget *widget, + GdkEventExpose *event); +#endif + +static gboolean gimp_spin_scale_button_press (GtkWidget *widget, + GdkEventButton *event); +static gboolean gimp_spin_scale_button_release (GtkWidget *widget, + GdkEventButton *event); +static gboolean gimp_spin_scale_motion_notify (GtkWidget *widget, + GdkEventMotion *event); +static gboolean gimp_spin_scale_leave_notify (GtkWidget *widget, + GdkEventCrossing *event); +static gboolean gimp_spin_scale_keypress( GtkWidget *widget, + GdkEventKey *event); + +static void gimp_spin_scale_defocus( GtkSpinButton *spin_button ); + +static void gimp_spin_scale_value_changed (GtkSpinButton *spin_button); + + +G_DEFINE_TYPE (GimpSpinScale, gimp_spin_scale, GTK_TYPE_SPIN_BUTTON); + +#define parent_class gimp_spin_scale_parent_class + + +static void +gimp_spin_scale_class_init (GimpSpinScaleClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GtkSpinButtonClass *spin_button_class = GTK_SPIN_BUTTON_CLASS (klass); + + object_class->dispose = gimp_spin_scale_dispose; + object_class->finalize = gimp_spin_scale_finalize; + object_class->set_property = gimp_spin_scale_set_property; + object_class->get_property = gimp_spin_scale_get_property; + + widget_class->style_set = gimp_spin_scale_style_set; +#if WITH_GTKMM_3_0 + widget_class->get_preferred_width = gimp_spin_scale_get_preferred_width; + widget_class->get_preferred_height = gimp_spin_scale_get_preferred_height; + widget_class->draw = gimp_spin_scale_draw; +#else + widget_class->size_request = gimp_spin_scale_size_request; + widget_class->expose_event = gimp_spin_scale_expose; +#endif + widget_class->button_press_event = gimp_spin_scale_button_press; + widget_class->button_release_event = gimp_spin_scale_button_release; + widget_class->motion_notify_event = gimp_spin_scale_motion_notify; + widget_class->leave_notify_event = gimp_spin_scale_leave_notify; + widget_class->key_press_event = gimp_spin_scale_keypress; + + spin_button_class->value_changed = gimp_spin_scale_value_changed; + + g_object_class_install_property (object_class, PROP_LABEL, + g_param_spec_string ("label", NULL, NULL, + NULL, + G_PARAM_READWRITE)); + + g_type_class_add_private (klass, sizeof (GimpSpinScalePrivate)); +} + +static void +gimp_spin_scale_init (GimpSpinScale *scale) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (scale); + + gtk_entry_set_alignment (GTK_ENTRY (scale), 1.0); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (scale), TRUE); + + private->gamma = 1.0; + private->focusWidget = NULL; + private->transferFocus = FALSE; + private->appearanceMode = APPEARANCE_COMPACT; +} + +static void +gimp_spin_scale_dispose (GObject *object) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (object); + + if (private->layout) + { + g_object_unref (private->layout); + private->layout = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gimp_spin_scale_finalize (GObject *object) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (object); + + if (private->label) + { + g_free (private->label); + private->label = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gimp_spin_scale_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (object); + + switch (property_id) + { + case PROP_LABEL: + g_free (private->label); + private->label = g_value_dup_string (value); + if (private->layout) + { + g_object_unref (private->layout); + private->layout = NULL; + } + gtk_widget_queue_resize (GTK_WIDGET (object)); + break; + + case PROP_FOCUS_WIDGET: + { + /* TODO unhook prior */ + private->focusWidget = (GtkWidget*)g_value_get_pointer( value ); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_spin_scale_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (object); + + switch (property_id) + { + case PROP_LABEL: + g_value_set_string (value, private->label); + break; + + case PROP_FOCUS_WIDGET: + g_value_set_pointer( value, private->focusWidget ); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +void +gimp_spin_scale_set_focuswidget( GtkWidget *scale, GtkWidget* widget ) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (scale); + + /* TODO unhook prior */ + + private->focusWidget = widget; +} + +void +gimp_spin_scale_set_appearance( GtkWidget *widget, const gchar *appearance) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); + + if ( strcmp("full", appearance) == 0 ) { + private->appearanceMode = APPEARANCE_FULL; + } else if ( strcmp("compact", appearance) == 0 ) { + private->appearanceMode = APPEARANCE_COMPACT; + } +} + +static void +#if WITH_GTKMM_3_0 +gimp_spin_scale_get_preferred_width (GtkWidget *widget, + gint *minimum_width, + gint *natural_width) +#else +gimp_spin_scale_size_request (GtkWidget *widget, + GtkRequisition *requisition) +#endif +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); + GtkStyle *style = gtk_widget_get_style (widget); + PangoContext *context = gtk_widget_get_pango_context (widget); + PangoFontMetrics *metrics; + +#if WITH_GTKMM_3_0 + GTK_WIDGET_CLASS (parent_class)->get_preferred_width (widget, + minimum_width, + natural_width); +#else + gint height; + GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition); +#endif + + metrics = pango_context_get_metrics (context, style->font_desc, + pango_context_get_language (context)); + +#if WITH_GTKMM_3_0 +#else + height = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) + + pango_font_metrics_get_descent (metrics)); + + if (private->appearanceMode == APPEARANCE_COMPACT) { + requisition->height += 1; + } else { + requisition->height += height; + } + +#endif + + + if (private->label) + { + gint char_width; + gint digit_width; + gint char_pixels; + + char_width = pango_font_metrics_get_approximate_char_width (metrics); + digit_width = pango_font_metrics_get_approximate_digit_width (metrics); + char_pixels = PANGO_PIXELS (MAX (char_width, digit_width)); + +#if WITH_GTKMM_3_0 + *minimum_width += char_pixels * 3; + *natural_width += char_pixels * 3; +#else + /* ~3 chars for the ellipses */ + requisition->width += char_pixels * 3; +#endif + + } + + pango_font_metrics_unref (metrics); +} + +#if WITH_GTKMM_3_0 +static void +gimp_spin_scale_get_preferred_height (GtkWidget *widget, + gint *minimum_height, + gint *natural_height) +{ + GtkStyle *style = gtk_widget_get_style (widget); + PangoContext *context = gtk_widget_get_pango_context (widget); + PangoFontMetrics *metrics; + //gint height; + + GTK_WIDGET_CLASS (parent_class)->get_preferred_height (widget, + minimum_height, + natural_height); + + metrics = pango_context_get_metrics (context, style->font_desc, + pango_context_get_language (context)); + + //height = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) + + // pango_font_metrics_get_descent (metrics)); + + *minimum_height += 1; + *natural_height += 1; + + pango_font_metrics_unref (metrics); +} +#endif + +static void +gimp_spin_scale_style_set (GtkWidget *widget, + GtkStyle *prev_style) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); + + GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style); + + if (private->layout) + { + g_object_unref (private->layout); + private->layout = NULL; + } +} + + +static gboolean + +#if WITH_GTKMM_3_0 + gimp_spin_scale_draw (GtkWidget *widget, cairo_t *cr) +#else + gimp_spin_scale_expose (GtkWidget *widget, GdkEventExpose *event) +#endif +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); + GtkStyle *style = gtk_widget_get_style (widget); + + +#if WITH_GTKMM_3_0 + GtkAllocation allocation; + + cairo_save (cr); + GTK_WIDGET_CLASS (parent_class)->draw (widget, cr); + cairo_restore (cr); + + gtk_widget_get_allocation (widget, &allocation); + + +#else + cairo_t *cr; + gint w; + + GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event); + + cr = gdk_cairo_create (event->window); + gdk_cairo_region (cr, event->region); + cairo_clip (cr); + + w = gdk_window_get_width (event->window); + +#endif + + cairo_set_line_width (cr, 1.0); + + +#if WITH_GTKMM_3_0 + if (private->label) + { + GdkRectangle text_area; + gint minimum_width; + gint natural_width; +#else + if (private->label && + gtk_widget_is_drawable (widget) && + event->window == gtk_entry_get_text_window (GTK_ENTRY (widget))) + { + GtkRequisition requisition; + GtkAllocation allocation; +#endif + + PangoRectangle logical; + gint layout_offset_x; + gint layout_offset_y; + +#if WITH_GTKMM_3_0 + gtk_entry_get_text_area (GTK_ENTRY (widget), &text_area); + + GTK_WIDGET_CLASS (parent_class)->get_preferred_width (widget, + &minimum_width, + &natural_width); +#else + GTK_WIDGET_CLASS (parent_class)->size_request (widget, &requisition); + gtk_widget_get_allocation (widget, &allocation); +#endif + + if (! private->layout) + { + private->layout = gtk_widget_create_pango_layout (widget, + private->label); + pango_layout_set_ellipsize (private->layout, PANGO_ELLIPSIZE_END); + } + + pango_layout_set_width (private->layout, + PANGO_SCALE * +#if WITH_GTKMM_3_0 + (allocation.width - minimum_width + 10)); +#else + (allocation.width - requisition.width + 10)); +#endif + pango_layout_get_pixel_extents (private->layout, NULL, &logical); + + gtk_entry_get_layout_offsets (GTK_ENTRY (widget), NULL, &layout_offset_y); + + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) +#if WITH_GTKMM_3_0 + layout_offset_x = text_area.x + text_area.width - logical.width - 4; +#else + layout_offset_x = w - logical.width - 4; +#endif + else + layout_offset_x = 4; + + layout_offset_x -= logical.x; + +#if WITH_GTKMM_3_0 + cairo_move_to (cr, layout_offset_x, text_area.y + layout_offset_y-3); +#else + cairo_move_to (cr, layout_offset_x, layout_offset_y-3); +#endif + + gdk_cairo_set_source_color (cr, + &style->text[gtk_widget_get_state (widget)]); + + pango_cairo_show_layout (cr, private->layout); + } + +#if WITH_GTKMM_3_0 +#else + cairo_destroy (cr); +#endif + + return FALSE; +} + +#if WITH_GTKMM_3_0 +/* Returns TRUE if a translation should be done */ +static gboolean +gtk_widget_get_translation_to_window (GtkWidget *widget, + GdkWindow *window, + int *x, + int *y) +{ + GdkWindow *w, *widget_window; + + if (!gtk_widget_get_has_window (widget)) + { + GtkAllocation allocation; + + gtk_widget_get_allocation (widget, &allocation); + + *x = -allocation.x; + *y = -allocation.y; + } + else + { + *x = 0; + *y = 0; + } + + widget_window = gtk_widget_get_window (widget); + + for (w = window; w && w != widget_window; w = gdk_window_get_parent (w)) + { + int wx, wy; + gdk_window_get_position (w, &wx, &wy); + *x += wx; + *y += wy; + } + + if (w == NULL) + { + *x = 0; + *y = 0; + return FALSE; + } + + return TRUE; +} + +static void +gimp_spin_scale_event_to_widget_coords (GtkWidget *widget, + GdkWindow *window, + gdouble event_x, + gdouble event_y, + gint *widget_x, + gint *widget_y) +{ + gint tx, ty; + + if (gtk_widget_get_translation_to_window (widget, window, &tx, &ty)) + { + event_x += tx; + event_y += ty; + } + + *widget_x = event_x; + *widget_y = event_y; +} +#endif + +static SpinScaleTarget +gimp_spin_scale_get_target (GtkWidget *widget, + gdouble x, + gdouble y) +{ + GtkAllocation allocation; + PangoRectangle logical; + gint layout_x; + gint layout_y; + + gtk_widget_get_allocation (widget, &allocation); + gtk_entry_get_layout_offsets (GTK_ENTRY (widget), &layout_x, &layout_y); + pango_layout_get_pixel_extents (gtk_entry_get_layout (GTK_ENTRY (widget)), + NULL, &logical); + +#if WITH_GTKMM_3_0 + GdkRectangle text_area; + gtk_entry_get_text_area (GTK_ENTRY (widget), &text_area); + + if (x >= text_area.x && x < text_area.width && + y >= text_area.y && y < text_area.height) + { + x -= text_area.x; + y -= text_area.y; + + if (x > layout_x && x < layout_x + logical.width && + y > layout_y && y < layout_y + logical.height) + { + return TARGET_NUMBER; + } + else if (y > text_area.height / 2) + { + return TARGET_LOWER; + } + + return TARGET_UPPER; + } + + return TARGET_NONE; +#else + if (x > layout_x && x < layout_x + logical.width && + y > layout_y && y < layout_y + logical.height) + { + return TARGET_NUMBER; + } + + else if (y > allocation.height / 2) + { + return TARGET_LOWER; + } + return TARGET_UPPER; +#endif +} + +static void +gimp_spin_scale_get_limits (GimpSpinScale *scale, + gdouble *lower, + gdouble *upper) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (scale); + + if (private->scale_limits_set) + { + *lower = private->scale_lower; + *upper = private->scale_upper; + } + else + { + GtkSpinButton *spin_button = GTK_SPIN_BUTTON (scale); + GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin_button); + + *lower = gtk_adjustment_get_lower (adjustment); + *upper = gtk_adjustment_get_upper (adjustment); + } +} + +static void +gimp_spin_scale_change_value (GtkWidget *widget, + gdouble x) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); + GtkSpinButton *spin_button = GTK_SPIN_BUTTON (widget); + GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin_button); + gdouble lower; + gdouble upper; + gdouble value; +#if WITH_GTKMM_3_0 +#else +#endif +#if WITH_GTKMM_3_0 + GdkRectangle text_area; + gtk_entry_get_text_area (GTK_ENTRY (widget), &text_area); + gimp_spin_scale_get_limits (GIMP_SPIN_SCALE (widget), &lower, &upper); +#else + GdkWindow *text_window = gtk_entry_get_text_window (GTK_ENTRY (widget)); + gint width; + + gimp_spin_scale_get_limits (GIMP_SPIN_SCALE (widget), &lower, &upper); + width = gdk_window_get_width (text_window); + +#endif + + + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) +#if WITH_GTKMM_3_0 + x = text_area.width - x; +#else + x = width - x; +#endif + + + if (private->relative_change) + { + gdouble diff; + gdouble step; + + +#if WITH_GTKMM_3_0 + step = (upper - lower) / text_area.width / 10.0; +#else + step = (upper - lower) / width / 10.0; +#endif + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) + +#if WITH_GTKMM_3_0 + diff = x - (text_area.width - private->start_x); +#else + diff = x - (width - private->start_x); +#endif + else + diff = x - private->start_x; + + value = (private->start_value + diff * step); + } + else + { + gdouble fraction; + + +#if WITH_GTKMM_3_0 + fraction = x / (gdouble) text_area.width; +#else + fraction = x / (gdouble) width; +#endif + if (fraction > 0.0) + fraction = pow (fraction, private->gamma); + + value = fraction * (upper - lower) + lower; + } + + gtk_adjustment_set_value (adjustment, value); +} + +static gboolean +gimp_spin_scale_button_press (GtkWidget *widget, + GdkEventButton *event) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); + + private->changing_value = FALSE; + private->relative_change = FALSE; + +#if WITH_GTKMM_3_0 + gint x, y; + gimp_spin_scale_event_to_widget_coords (widget, event->window, + event->x, event->y, + &x, &y); + switch (gimp_spin_scale_get_target (widget, x, y)) + { + case TARGET_UPPER: + private->changing_value = TRUE; + + gtk_widget_grab_focus (widget); + + gimp_spin_scale_change_value (widget, x); + + return TRUE; + + case TARGET_LOWER: + private->changing_value = TRUE; + + gtk_widget_grab_focus (widget); + + private->relative_change = TRUE; + private->start_x = x; + private->start_value = gtk_adjustment_get_value (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (widget))); + + return TRUE; + + default: + break; + } +#else + if (event->window == gtk_entry_get_text_window (GTK_ENTRY (widget))) + { + switch (gimp_spin_scale_get_target (widget, event->x, event->y)) + { + case TARGET_UPPER: + private->changing_value = TRUE; + + gtk_widget_grab_focus (widget); + + gimp_spin_scale_change_value (widget, event->x); + + return TRUE; + + case TARGET_LOWER: + private->changing_value = TRUE; + + gtk_widget_grab_focus (widget); + + private->relative_change = TRUE; + private->start_x = event->x; + private->start_value = gtk_adjustment_get_value (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (widget))); + + return TRUE; + + default: + break; + } + } +#endif + + return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event); +} + +static gboolean +gimp_spin_scale_button_release (GtkWidget *widget, + GdkEventButton *event) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); +#if WITH_GTKMM_3_0 + gint x, y; + + gimp_spin_scale_event_to_widget_coords (widget, event->window, + event->x, event->y, + &x, &y); +#endif + + if (private->changing_value) + { + private->changing_value = FALSE; +#if WITH_GTKMM_3_0 + gimp_spin_scale_change_value (widget, x); +#else + gimp_spin_scale_change_value (widget, event->x); +#endif + return TRUE; + } + + return GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event); +} + +static gboolean +gimp_spin_scale_motion_notify (GtkWidget *widget, + GdkEventMotion *event) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); +#if WITH_GTKMM_3_0 + gint x, y; + + gimp_spin_scale_event_to_widget_coords (widget, event->window, + event->x, event->y, + &x, &y); +#endif + + if (private->changing_value) + { +#if WITH_GTKMM_3_0 + gimp_spin_scale_change_value (widget, x); +#else + gimp_spin_scale_change_value (widget, event->x); +#endif + + return TRUE; + } + + GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event); + + if (! (event->state & + (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) +#if WITH_GTKMM_3_0 +#else + && event->window == gtk_entry_get_text_window (GTK_ENTRY (widget)) +#endif + ) + { + GdkDisplay *display = gtk_widget_get_display (widget); + GdkCursor *cursor = NULL; + +#if WITH_GTKMM_3_0 + switch (gimp_spin_scale_get_target (widget, x, y)) +#else + switch (gimp_spin_scale_get_target (widget, event->x, event->y)) +#endif + { + case TARGET_NUMBER: + cursor = gdk_cursor_new_for_display (display, GDK_XTERM); + break; + + case TARGET_UPPER: + cursor = gdk_cursor_new_for_display (display, GDK_SB_UP_ARROW); + break; + + case TARGET_LOWER: + cursor = gdk_cursor_new_for_display (display, GDK_SB_H_DOUBLE_ARROW); + break; + + default: + break; + } + + +#if WITH_GTKMM_3_0 + if (cursor) + { + gdk_window_set_cursor (event->window, cursor); + g_object_unref (cursor); + } +#else + gdk_window_set_cursor (event->window, cursor); + gdk_cursor_unref (cursor); +#endif + } + + return FALSE; +} + +static gboolean +gimp_spin_scale_leave_notify (GtkWidget *widget, + GdkEventCrossing *event) +{ + gdk_window_set_cursor (event->window, NULL); + + return GTK_WIDGET_CLASS (parent_class)->leave_notify_event (widget, event); +} + +gboolean gimp_spin_scale_keypress( GtkWidget *widget, GdkEventKey *event) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); + guint key = 0; + gdk_keymap_translate_keyboard_state( gdk_keymap_get_for_display( gdk_display_get_default() ), + event->hardware_keycode, (GdkModifierType)event->state, + 0, &key, 0, 0, 0 ); + + switch ( key ) { + + case GDK_KEY_Escape: + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + { + private->transferFocus = TRUE; + gimp_spin_scale_defocus( GTK_SPIN_BUTTON(widget) ); + } + break; + + } + + return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); +} + +static void +gimp_spin_scale_defocus( GtkSpinButton *spin_button ) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (spin_button); + + if ( private->transferFocus ) { + if ( private->focusWidget ) { + gtk_widget_grab_focus( private->focusWidget ); + } + } +} + +static void +gimp_spin_scale_value_changed (GtkSpinButton *spin_button) +{ + GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin_button); + GimpSpinScalePrivate *private = GET_PRIVATE (spin_button); + gdouble lower; + gdouble upper; + gdouble value; + + gimp_spin_scale_get_limits (GIMP_SPIN_SCALE (spin_button), &lower, &upper); + + value = CLAMP (gtk_adjustment_get_value (adjustment), lower, upper); + + + gtk_entry_set_progress_fraction (GTK_ENTRY (spin_button), + pow ((value - lower) / (upper - lower), + 1.0 / private->gamma)); + + // TODO - Allow scrollwheel to change value then return focus, + // but clicks/keypress should keep focus in the control + //if ( gtk_widget_has_focus( GTK_WIDGET(spin_button) ) ) { + // gimp_spin_scale_defocus( spin_button ); + //} +} + + +/* public functions */ + +GtkWidget * +gimp_spin_scale_new (GtkAdjustment *adjustment, + const gchar *label, + gint digits) +{ + g_return_val_if_fail (GTK_IS_ADJUSTMENT (adjustment), NULL); + + return g_object_new (GIMP_TYPE_SPIN_SCALE, + "adjustment", adjustment, + "label", label, + "digits", digits, + NULL); +} + +void +gimp_spin_scale_set_scale_limits (GimpSpinScale *scale, + gdouble lower, + gdouble upper) +{ + GimpSpinScalePrivate *private; + GtkSpinButton *spin_button; + GtkAdjustment *adjustment; + + g_return_if_fail (GIMP_IS_SPIN_SCALE (scale)); + + private = GET_PRIVATE (scale); + spin_button = GTK_SPIN_BUTTON (scale); + adjustment = gtk_spin_button_get_adjustment (spin_button); + + g_return_if_fail (lower >= gtk_adjustment_get_lower (adjustment)); + g_return_if_fail (upper <= gtk_adjustment_get_upper (adjustment)); + + private->scale_limits_set = TRUE; + private->scale_lower = lower; + private->scale_upper = upper; + private->gamma = 1.0; + + gimp_spin_scale_value_changed (spin_button); +} + +void +gimp_spin_scale_set_gamma (GimpSpinScale *scale, + gdouble gamma) +{ + GimpSpinScalePrivate *private; + + g_return_if_fail (GIMP_IS_SPIN_SCALE (scale)); + + private = GET_PRIVATE (scale); + + private->gamma = gamma; + + gimp_spin_scale_value_changed (GTK_SPIN_BUTTON (scale)); +} + +gdouble +gimp_spin_scale_get_gamma (GimpSpinScale *scale) +{ + GimpSpinScalePrivate *private; + + g_return_val_if_fail (GIMP_IS_SPIN_SCALE (scale), 1.0); + + private = GET_PRIVATE (scale); + + return private->gamma; +} + +void +gimp_spin_scale_unset_scale_limits (GimpSpinScale *scale) +{ + GimpSpinScalePrivate *private; + + g_return_if_fail (GIMP_IS_SPIN_SCALE (scale)); + + private = GET_PRIVATE (scale); + + private->scale_limits_set = FALSE; + private->scale_lower = 0.0; + private->scale_upper = 0.0; + + gimp_spin_scale_value_changed (GTK_SPIN_BUTTON (scale)); +} + +gboolean +gimp_spin_scale_get_scale_limits (GimpSpinScale *scale, + gdouble *lower, + gdouble *upper) +{ + GimpSpinScalePrivate *private; + + g_return_val_if_fail (GIMP_IS_SPIN_SCALE (scale), FALSE); + + private = GET_PRIVATE (scale); + + if (lower) + *lower = private->scale_lower; + + if (upper) + *upper = private->scale_upper; + + return private->scale_limits_set; +} diff --git a/src/ui/widget/gimpspinscale.h b/src/ui/widget/gimpspinscale.h new file mode 100644 index 000000000..ad63625ac --- /dev/null +++ b/src/ui/widget/gimpspinscale.h @@ -0,0 +1,76 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpspinscale.h + * Copyright (C) 2010 Michael Natterer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __GIMP_SPIN_SCALE_H__ +#define __GIMP_SPIN_SCALE_H__ + +#ifndef WITH_GIMP +#include +#endif + +G_BEGIN_DECLS + +#define GIMP_TYPE_SPIN_SCALE (gimp_spin_scale_get_type ()) +#define GIMP_SPIN_SCALE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_SPIN_SCALE, GimpSpinScale)) +#define GIMP_SPIN_SCALE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_SPIN_SCALE, GimpSpinScaleClass)) +#define GIMP_IS_SPIN_SCALE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_SPIN_SCALE)) +#define GIMP_IS_SPIN_SCALE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_SPIN_SCALE)) +#define GIMP_SPIN_SCALE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_SPIN_SCALE, GimpSpinScaleClass)) + + +typedef struct _GimpSpinScale GimpSpinScale; +typedef struct _GimpSpinScaleClass GimpSpinScaleClass; + +struct _GimpSpinScale +{ + GtkSpinButton parent_instance; +}; + +struct _GimpSpinScaleClass +{ + GtkSpinButtonClass parent_class; +}; + + +GType gimp_spin_scale_get_type (void) G_GNUC_CONST; + +GtkWidget * gimp_spin_scale_new (GtkAdjustment *adjustment, + const gchar *label, + gint digits); + +void gimp_spin_scale_set_scale_limits (GimpSpinScale *scale, + gdouble lower, + gdouble upper); +void gimp_spin_scale_unset_scale_limits (GimpSpinScale *scale); +gboolean gimp_spin_scale_get_scale_limits (GimpSpinScale *scale, + gdouble *lower, + gdouble *upper); + +void gimp_spin_scale_set_gamma (GimpSpinScale *scale, + gdouble gamma); +gdouble gimp_spin_scale_get_gamma (GimpSpinScale *scale); + +void gimp_spin_scale_set_focuswidget( GtkWidget *scale, GtkWidget* widget ); + +void gimp_spin_scale_set_appearance( GtkWidget *scale, const gchar *appearance); + +G_END_DECLS + +#endif /* __GIMP_SPIN_SCALE_H__ */ diff --git a/src/ui/widget/spin-scale.cpp b/src/ui/widget/spin-scale.cpp new file mode 100644 index 000000000..00c575568 --- /dev/null +++ b/src/ui/widget/spin-scale.cpp @@ -0,0 +1,248 @@ +/* + * Author: + * + * Copyright (C) 2012 Author + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#include +#include +#include +#include + +#include "spin-scale.h" +#include "ui/widget/gimpspinscale.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +SpinScale::SpinScale(const char* label, double value, double lower, double upper, double step_inc, + double climb_rate, int digits, const SPAttributeEnum a, const char* tip_text) + : AttrWidget(a, value) +{ + +#if WITH_GTKMM_3_0 + _adjustment = Gtk::Adjustment::create(value, lower, upper, step_inc); + _spinscale = gimp_spin_scale_new (_adjustment->gobj(), label, digits); +#else + _adjustment = new Gtk::Adjustment(value, lower, upper, step_inc); + _spinscale = gimp_spin_scale_new (_adjustment->gobj(), label, digits); +#endif + + signal_value_changed().connect(signal_attr_changed().make_slot()); + + pack_start(*Gtk::manage(Glib::wrap(_spinscale))); + + if (tip_text){ + gtk_widget_set_tooltip_text( _spinscale, tip_text ); + } + + show_all_children(); +} + +SpinScale::SpinScale(const char* label, +#if WITH_GTKMM_3_0 + Glib::RefPtr adj, +#else + Gtk::Adjustment *adj, +#endif + int digits, const SPAttributeEnum a, const char* tip_text) + : AttrWidget(a, 0.0), + _adjustment(adj) + +{ + + _spinscale = gimp_spin_scale_new (_adjustment->gobj(), label, digits); + + signal_value_changed().connect(signal_attr_changed().make_slot()); + + pack_start(*Gtk::manage(Glib::wrap(_spinscale))); + + if (tip_text){ + gtk_widget_set_tooltip_text( _spinscale, tip_text ); + } + + show_all_children(); +} + +Glib::ustring SpinScale::get_as_attribute() const +{ + const double val = _adjustment->get_value(); + + //if(_spin.get_digits() == 0) + // return Glib::Ascii::dtostr((int)val); + //else + return Glib::Ascii::dtostr(val); +} + +void SpinScale::set_from_attribute(SPObject* o) +{ + const gchar* val = attribute_value(o); + if(val) + _adjustment->set_value(Glib::Ascii::strtod(val)); + else + _adjustment->set_value(get_default()->as_double()); +} + +Glib::SignalProxy0 SpinScale::signal_value_changed() +{ + return _adjustment->signal_value_changed(); +} + +double SpinScale::get_value() const +{ + return _adjustment->get_value(); +} + +void SpinScale::set_value(const double val) +{ + _adjustment->set_value(val); +} + +void SpinScale::set_focuswidget(GtkWidget *widget) +{ + gimp_spin_scale_set_focuswidget(_spinscale, widget); +} + + +void SpinScale::set_appearance(const gchar* appearance) +{ + gimp_spin_scale_set_appearance(_spinscale, appearance); +} + +#if WITH_GTKMM_3_0 +const Glib::RefPtr SpinScale::get_adjustment() const +#else +const Gtk::Adjustment *SpinScale::get_adjustment() const +#endif +{ + return _adjustment; +} +#if WITH_GTKMM_3_0 +Glib::RefPtr SpinScale::get_adjustment() +#else +Gtk::Adjustment *SpinScale::get_adjustment() +#endif +{ + return _adjustment; +} + + +DualSpinScale::DualSpinScale(const char* label1, const char* label2, double value, double lower, double upper, double step_inc, + double climb_rate, int digits, const SPAttributeEnum a, char* tip_text1, char* tip_text2) + : AttrWidget(a), + _s1(label1, value, lower, upper, step_inc, climb_rate, digits, SP_ATTR_INVALID, tip_text1), + _s2(label2, value, lower, upper, step_inc, climb_rate, digits, SP_ATTR_INVALID, tip_text2), + //TRANSLATORS: "Link" means to _link_ two sliders together + _link(C_("Sliders", "Link")) +{ + signal_value_changed().connect(signal_attr_changed().make_slot()); + + _s1.get_adjustment()->signal_value_changed().connect(_signal_value_changed.make_slot()); + _s2.get_adjustment()->signal_value_changed().connect(_signal_value_changed.make_slot()); + _s1.get_adjustment()->signal_value_changed().connect(sigc::mem_fun(*this, &DualSpinScale::update_linked)); + + _link.signal_toggled().connect(sigc::mem_fun(*this, &DualSpinScale::link_toggled)); + + Gtk::VBox* vb = Gtk::manage(new Gtk::VBox); + vb->add(_s1); + vb->add(_s2); + pack_start(*vb); + pack_start(_link, false, false); + _link.set_active(true); + + show_all(); +} + +Glib::ustring DualSpinScale::get_as_attribute() const +{ + if(_link.get_active()) + return _s1.get_as_attribute(); + else + return _s1.get_as_attribute() + " " + _s2.get_as_attribute(); +} + +void DualSpinScale::set_from_attribute(SPObject* o) +{ + const gchar* val = attribute_value(o); + if(val) { + // Split val into parts + gchar** toks = g_strsplit(val, " ", 2); + + if(toks) { + double v1 = 0.0, v2 = 0.0; + if(toks[0]) + v1 = v2 = Glib::Ascii::strtod(toks[0]); + if(toks[1]) + v2 = Glib::Ascii::strtod(toks[1]); + + _link.set_active(toks[1] == 0); + + _s1.get_adjustment()->set_value(v1); + _s2.get_adjustment()->set_value(v2); + + g_strfreev(toks); + } + } +} + +sigc::signal& DualSpinScale::signal_value_changed() +{ + return _signal_value_changed; +} + +const SpinScale& DualSpinScale::get_SpinScale1() const +{ + return _s1; +} + +SpinScale& DualSpinScale::get_SpinScale1() +{ + return _s1; +} + +const SpinScale& DualSpinScale::get_SpinScale2() const +{ + return _s2; +} + +SpinScale& DualSpinScale::get_SpinScale2() +{ + return _s2; +} + +/*void DualSpinScale::remove_scale() +{ + _s1.remove_scale(); + _s2.remove_scale(); +}*/ + +void DualSpinScale::link_toggled() +{ + _s2.set_sensitive(!_link.get_active()); + update_linked(); +} + +void DualSpinScale::update_linked() +{ + if(_link.get_active()) + _s2.set_value(_s1.get_value()); +} + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/spin-scale.h b/src/ui/widget/spin-scale.h new file mode 100644 index 000000000..a8403307f --- /dev/null +++ b/src/ui/widget/spin-scale.h @@ -0,0 +1,117 @@ +/* + * Author: + * + * Copyright (C) 2012 Author + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_SPIN_SCALE_H +#define INKSCAPE_UI_WIDGET_SPIN_SCALE_H + +#include +#include +#include +#include +#include "spinbutton.h" +#include "attr-widget.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +/** + * Wrap the gimpspinscale class + * A combo widget with label, scale slider, spinbutton and adjustment + */ +class SpinScale : public Gtk::HBox, public AttrWidget +{ + +public: + SpinScale(const char* label, double value, double lower, double upper, double step_inc, double climb_rate, + int digits, const SPAttributeEnum a = SP_ATTR_INVALID, const char* tip_text = NULL); + + SpinScale(const char* label, +#if WITH_GTKMM_3_0 + Glib::RefPtr adj, +#else + Gtk::Adjustment *adj, +#endif + int digits, const SPAttributeEnum a = SP_ATTR_INVALID, const char* tip_text = NULL); + + virtual Glib::ustring get_as_attribute() const; + virtual void set_from_attribute(SPObject*); + + // Shortcuts to _adjustment + Glib::SignalProxy0 signal_value_changed(); + double get_value() const; + void set_value(const double); + void set_focuswidget(GtkWidget *widget); + void set_appearance(const gchar* appearance); + +#if WITH_GTKMM_3_0 + const Glib::RefPtr get_adjustment() const; + Glib::RefPtr get_adjustment(); +#else + const Gtk::Adjustment *get_adjustment() const; + Gtk::Adjustment *get_adjustment(); +#endif + +private: +#if WITH_GTKMM_3_0 + Glib::RefPtr _adjustment; +#else + Gtk::Adjustment *_adjustment; +#endif + + GtkWidget *_spinscale; +}; + + +/** + * Contains two SpinScales for controlling number-opt-number attributes. + * + * @see SpinScale + */ +class DualSpinScale : public Gtk::HBox, public AttrWidget +{ +public: + DualSpinScale(const char* label1, const char* label2, double value, double lower, double upper, double step_inc, + double climb_rate, int digits, const SPAttributeEnum, char* tip_text1, char* tip_text2); + + virtual Glib::ustring get_as_attribute() const; + virtual void set_from_attribute(SPObject*); + + sigc::signal& signal_value_changed(); + + const SpinScale& get_SpinScale1() const; + SpinScale& get_SpinScale1(); + + const SpinScale& get_SpinScale2() const; + SpinScale& get_SpinScale2(); + + //void remove_scale(); +private: + void link_toggled(); + void update_linked(); + sigc::signal _signal_value_changed; + SpinScale _s1, _s2; + Gtk::ToggleButton _link; +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_SPIN_SCALE_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : -- cgit v1.2.3 From 7c0506c103c881790a2e347e2a68aecdf8935d5c Mon Sep 17 00:00:00 2001 From: John Smith Date: Sat, 22 Sep 2012 12:27:14 +0900 Subject: Fix for 1014988 : Converts slide widgets to new spin-scale widget (bzr r11691) --- src/ege-adjustment-action.cpp | 10 +--- src/extension/param/float.cpp | 25 ++++---- src/extension/param/int.cpp | 25 ++++---- src/ui/dialog/document-properties.cpp | 18 +++--- src/ui/dialog/fill-and-stroke.cpp | 2 +- src/ui/dialog/filter-effects-dialog.cpp | 88 ++++++++++++++--------------- src/ui/dialog/filter-effects-dialog.h | 1 + src/ui/widget/filter-effect-chooser.cpp | 15 +---- src/ui/widget/filter-effect-chooser.h | 8 +-- src/ui/widget/object-composite-settings.cpp | 58 ++++++------------- src/ui/widget/object-composite-settings.h | 12 +--- src/ui/widget/spin-slider.cpp | 2 +- 12 files changed, 110 insertions(+), 154 deletions(-) (limited to 'src') diff --git a/src/ege-adjustment-action.cpp b/src/ege-adjustment-action.cpp index 7881498b9..cf179478d 100644 --- a/src/ege-adjustment-action.cpp +++ b/src/ege-adjustment-action.cpp @@ -47,6 +47,7 @@ #include "icon-size.h" #include "ege-adjustment-action.h" +#include "ui/widget/gimpspinscale.h" static void ege_adjustment_action_class_init( EgeAdjustmentActionClass* klass ); @@ -835,15 +836,8 @@ static GtkWidget* create_tool_item( GtkAction* action ) if ( act->private_data->appearanceMode == APPEARANCE_FULL ) { /* Slider */ - gchar *leakyForNow = g_value_dup_string( &value ); -#if GTK_CHECK_VERSION(3,0,0) - spinbutton = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, act->private_data->adj); -#else - spinbutton = gtk_hscale_new( act->private_data->adj); -#endif + spinbutton = gimp_spin_scale_new (act->private_data->adj, g_value_get_string( &value ), 0); gtk_widget_set_size_request(spinbutton, 100, -1); - gtk_scale_set_digits( GTK_SCALE(spinbutton), 0 ); - g_signal_connect( G_OBJECT(spinbutton), "format-value", G_CALLBACK(slider_format_falue), leakyForNow ); } else if ( act->private_data->appearanceMode == APPEARANCE_MINIMAL ) { spinbutton = gtk_scale_button_new( GTK_ICON_SIZE_MENU, 0, 100, 2, 0 ); diff --git a/src/extension/param/float.cpp b/src/extension/param/float.cpp index b9ffe68d2..81508f6c0 100644 --- a/src/extension/param/float.cpp +++ b/src/extension/param/float.cpp @@ -14,6 +14,7 @@ #include #include #include "ui/widget/spinbutton.h" +#include "ui/widget/spin-scale.h" #include "xml/node.h" #include "extension/extension.h" @@ -175,9 +176,6 @@ Gtk::Widget * ParamFloat::get_widget(SPDocument * doc, Inkscape::XML::Node * nod } Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4)); - Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_START)); - label->show(); - hbox->pack_start(*label, true, true, _indent); #if WITH_GTKMM_3_0 ParamFloatAdjustment * pfa = new ParamFloatAdjustment(this, doc, node, changeSignal); @@ -187,24 +185,27 @@ Gtk::Widget * ParamFloat::get_widget(SPDocument * doc, Inkscape::XML::Node * nod #endif if (_mode == FULL) { -#if WITH_GTKMM_3_0 - Gtk::HScale * scale = Gtk::manage(new Gtk::HScale(fadjust)); -#else - Gtk::HScale * scale = Gtk::manage(new Gtk::HScale(*fadjust)); -#endif - scale->set_draw_value(false); - scale->set_size_request(200, -1); + + UI::Widget::SpinScale *scale = new UI::Widget::SpinScale(_(_text), fadjust, _precision); + scale->set_size_request(400, -1); scale->show(); hbox->pack_start(*scale, false, false); + } + else if (_mode == MINIMAL) { + + Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_START)); + label->show(); + hbox->pack_start(*label, true, true, _indent); #if WITH_GTKMM_3_0 Inkscape::UI::Widget::SpinButton * spin = Gtk::manage(new Inkscape::UI::Widget::SpinButton(fadjust, 0.1, _precision)); #else Inkscape::UI::Widget::SpinButton * spin = Gtk::manage(new Inkscape::UI::Widget::SpinButton(*fadjust, 0.1, _precision)); #endif - spin->show(); - hbox->pack_start(*spin, false, false); + spin->show(); + hbox->pack_start(*spin, false, false); + } hbox->show(); diff --git a/src/extension/param/int.cpp b/src/extension/param/int.cpp index 7cb930f50..c286018fd 100644 --- a/src/extension/param/int.cpp +++ b/src/extension/param/int.cpp @@ -14,6 +14,7 @@ #include #include #include "ui/widget/spinbutton.h" +#include "ui/widget/spin-scale.h" #include "xml/node.h" #include "extension/extension.h" @@ -156,9 +157,7 @@ ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal } Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4)); - Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_START)); - label->show(); - hbox->pack_start(*label, true, true, _indent); + #if WITH_GTKMM_3_0 ParamIntAdjustment * pia = new ParamIntAdjustment(this, doc, node, changeSignal); @@ -168,24 +167,26 @@ ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal #endif if (_mode == FULL) { -#if WITH_GTKMM_3_0 - Gtk::HScale * scale = Gtk::manage(new Gtk::HScale(fadjust)); -#else - Gtk::HScale * scale = Gtk::manage(new Gtk::HScale(*fadjust)); -#endif - scale->set_draw_value(false); - scale->set_size_request(200, -1); + + UI::Widget::SpinScale *scale = new UI::Widget::SpinScale(_(_text), fadjust, 0); + scale->set_size_request(400, -1); scale->show(); hbox->pack_start(*scale, false, false); } + else if (_mode == MINIMAL) { + Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_START)); + label->show(); + hbox->pack_start(*label, true, true, _indent); + #if WITH_GTKMM_3_0 Inkscape::UI::Widget::SpinButton * spin = Gtk::manage(new Inkscape::UI::Widget::SpinButton(fadjust, 1.0, 0)); #else Inkscape::UI::Widget::SpinButton * spin = Gtk::manage(new Inkscape::UI::Widget::SpinButton(*fadjust, 1.0, 0)); #endif - spin->show(); - hbox->pack_start(*spin, false, false); + spin->show(); + hbox->pack_start(*spin, false, false); + } hbox->show(); diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp index c7be0877d..7bd1b81c0 100644 --- a/src/ui/dialog/document-properties.cpp +++ b/src/ui/dialog/document-properties.cpp @@ -959,16 +959,18 @@ void DocumentProperties::removeEmbeddedScript(){ const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "script" ); while ( current ) { - SPObject* obj = SP_OBJECT(current->data); - if (id == obj->getId()){ + if (current->data && SP_IS_OBJECT(current->data)) { + SPObject* obj = SP_OBJECT(current->data); + if (id == obj->getId()){ - //XML Tree being used directly here while it shouldn't be. - Inkscape::XML::Node *repr = obj->getRepr(); - if (repr){ - sp_repr_unparent(repr); + //XML Tree being used directly here while it shouldn't be. + Inkscape::XML::Node *repr = obj->getRepr(); + if (repr){ + sp_repr_unparent(repr); - // inform the document, so we can undo - DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_EDIT_REMOVE_EMBEDDED_SCRIPT, _("Remove embedded script")); + // inform the document, so we can undo + DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_EDIT_REMOVE_EMBEDDED_SCRIPT, _("Remove embedded script")); + } } } current = g_slist_next(current); diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index 74c19fea7..c7efd3bf2 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -63,7 +63,7 @@ FillAndStroke::FillAndStroke() _layoutPageStrokePaint(); _layoutPageStrokeStyle(); - contents->pack_start(_composite_settings, false, false, 0); + contents->pack_start(_composite_settings, true, true, 0); show_all_children(); diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp index 317cb2773..c3c44f6c3 100644 --- a/src/ui/dialog/filter-effects-dialog.cpp +++ b/src/ui/dialog/filter-effects-dialog.cpp @@ -78,8 +78,8 @@ namespace Dialog { using Inkscape::UI::Widget::AttrWidget; using Inkscape::UI::Widget::ComboBoxEnum; -using Inkscape::UI::Widget::DualSpinSlider; -using Inkscape::UI::Widget::SpinSlider; +using Inkscape::UI::Widget::DualSpinScale; +using Inkscape::UI::Widget::SpinScale; // Returns the number of inputs available for the filter primitive type @@ -484,8 +484,8 @@ public: : AttrWidget(SP_ATTR_VALUES), // TRANSLATORS: this dialog is accessible via menu Filters - Filter editor _matrix(SP_ATTR_VALUES, _("This matrix determines a linear transform on color space. Each line affects one of the color components. Each column determines how much of each color component from the input is passed to the output. The last column does not depend on input colors, so can be used to adjust a constant component value.")), - _saturation(0, 0, 1, 0.1, 0.01, 2, SP_ATTR_VALUES), - _angle(0, 0, 360, 0.1, 0.01, 1, SP_ATTR_VALUES), + _saturation("", 0, 0, 1, 0.1, 0.01, 2, SP_ATTR_VALUES), + _angle("", 0, 0, 360, 0.1, 0.01, 1, SP_ATTR_VALUES), _label(_("None"), Gtk::ALIGN_START), _use_stored(false), _saturation_store(0), @@ -567,8 +567,8 @@ private: } MatrixAttr _matrix; - SpinSlider _saturation; - SpinSlider _angle; + SpinScale _saturation; + SpinScale _angle; Gtk::Label _label; // Store separate values for the different color modes @@ -808,22 +808,22 @@ public: return cmv; } - // SpinSlider - SpinSlider* add_spinslider(double def, const SPAttributeEnum attr, const Glib::ustring& label, + // SpinScale + SpinScale* add_spinscale(double def, const SPAttributeEnum attr, const Glib::ustring& label, const double lo, const double hi, const double step_inc, const double climb, const int digits, char* tip_text = NULL) { - SpinSlider* spinslider = new SpinSlider(def, lo, hi, step_inc, climb, digits, attr, tip_text); + SpinScale* spinslider = new SpinScale("", def, lo, hi, step_inc, climb, digits, attr, tip_text); add_widget(spinslider, label); add_attr_widget(spinslider); return spinslider; } - // DualSpinSlider - DualSpinSlider* add_dualspinslider(const SPAttributeEnum attr, const Glib::ustring& label, + // DualSpinScale + DualSpinScale* add_dualspinscale(const SPAttributeEnum attr, const Glib::ustring& label, const double lo, const double hi, const double step_inc, const double climb, const int digits, char* tip_text1 = NULL, char* tip_text2 = NULL) { - DualSpinSlider* dss = new DualSpinSlider(lo, lo, hi, step_inc, climb, digits, attr, tip_text1, tip_text2); + DualSpinScale* dss = new DualSpinScale("", "", lo, lo, hi, step_inc, climb, digits, attr, tip_text1, tip_text2); add_widget(dss, label); add_attr_widget(dss); return dss; @@ -971,8 +971,8 @@ public: // FIXME: these range values are complete crap _settings.type(LIGHT_DISTANT); - _settings.add_spinslider(0, SP_ATTR_AZIMUTH, _("Azimuth"), 0, 360, 1, 1, 0, _("Direction angle for the light source on the XY plane, in degrees")); - _settings.add_spinslider(0, SP_ATTR_ELEVATION, _("Elevation"), 0, 360, 1, 1, 0, _("Direction angle for the light source on the YZ plane, in degrees")); + _settings.add_spinscale(0, SP_ATTR_AZIMUTH, _("Azimuth"), 0, 360, 1, 1, 0, _("Direction angle for the light source on the XY plane, in degrees")); + _settings.add_spinscale(0, SP_ATTR_ELEVATION, _("Elevation"), 0, 360, 1, 1, 0, _("Direction angle for the light source on the YZ plane, in degrees")); _settings.type(LIGHT_POINT); _settings.add_multispinbutton(/*default x:*/ (double) 0, /*default y:*/ (double) 0, /*default z:*/ (double) 0, SP_ATTR_X, SP_ATTR_Y, SP_ATTR_Z, _("Location:"), -99999, 99999, 1, 100, 0, _("X coordinate"), _("Y coordinate"), _("Z coordinate")); @@ -982,9 +982,9 @@ public: _settings.add_multispinbutton(/*default x:*/ (double) 0, /*default y:*/ (double) 0, /*default z:*/ (double) 0, SP_ATTR_POINTSATX, SP_ATTR_POINTSATY, SP_ATTR_POINTSATZ, _("Points At"), -99999, 99999, 1, 100, 0, _("X coordinate"), _("Y coordinate"), _("Z coordinate")); - _settings.add_spinslider(1, SP_ATTR_SPECULAREXPONENT, _("Specular Exponent"), 1, 100, 1, 1, 0, _("Exponent value controlling the focus for the light source")); + _settings.add_spinscale(1, SP_ATTR_SPECULAREXPONENT, _("Specular Exponent"), 1, 100, 1, 1, 0, _("Exponent value controlling the focus for the light source")); //TODO: here I have used 100 degrees as default value. But spec says that if not specified, no limiting cone is applied. So, there should be a way for the user to set a "no limiting cone" option. - _settings.add_spinslider(100, SP_ATTR_LIMITINGCONEANGLE, _("Cone Angle"), 1, 100, 1, 1, 0, _("This is the angle between the spot light axis (i.e. the axis between the light source and the point to which it is pointing at) and the spot light cone. No light is projected outside this cone.")); + _settings.add_spinscale(100, SP_ATTR_LIMITINGCONEANGLE, _("Cone Angle"), 1, 100, 1, 1, 0, _("This is the angle between the spot light axis (i.e. the axis between the light source and the point to which it is pointing at) and the spot light cone. No light is projected outside this cone.")); } Gtk::VBox& get_box() @@ -2331,7 +2331,7 @@ void FilterEffectsDialog::show_all_vfunc() void FilterEffectsDialog::init_settings_widgets() { - // TODO: Find better range/climb-rate/digits values for the SpinSliders, + // TODO: Find better range/climb-rate/digits values for the SpinScales, // most of the current values are complete guesses! _empty_settings.set_sensitive(false); @@ -2358,18 +2358,18 @@ void FilterEffectsDialog::init_settings_widgets() /* //TRANSLATORS: for info on "Slope" and "Intercept", see http://id.mind.net/~zona/mmts/functionInstitute/linearFunctions/lsif.html _settings->add_combo(COMPONENTTRANSFER_TYPE_IDENTITY, SP_ATTR_TYPE, _("Type"), ComponentTransferTypeConverter); - _ct_slope = _settings->add_spinslider(1, SP_ATTR_SLOPE, _("Slope"), -10, 10, 0.1, 0.01, 2); - _ct_intercept = _settings->add_spinslider(0, SP_ATTR_INTERCEPT, _("Intercept"), -10, 10, 0.1, 0.01, 2); - _ct_amplitude = _settings->add_spinslider(1, SP_ATTR_AMPLITUDE, _("Amplitude"), 0, 10, 0.1, 0.01, 2); - _ct_exponent = _settings->add_spinslider(1, SP_ATTR_EXPONENT, _("Exponent"), 0, 10, 0.1, 0.01, 2); - _ct_offset = _settings->add_spinslider(0, SP_ATTR_OFFSET, _("Offset"), -10, 10, 0.1, 0.01, 2);*/ + _ct_slope = _settings->add_spinscale(1, SP_ATTR_SLOPE, _("Slope"), -10, 10, 0.1, 0.01, 2); + _ct_intercept = _settings->add_spinscale(0, SP_ATTR_INTERCEPT, _("Intercept"), -10, 10, 0.1, 0.01, 2); + _ct_amplitude = _settings->add_spinscale(1, SP_ATTR_AMPLITUDE, _("Amplitude"), 0, 10, 0.1, 0.01, 2); + _ct_exponent = _settings->add_spinscale(1, SP_ATTR_EXPONENT, _("Exponent"), 0, 10, 0.1, 0.01, 2); + _ct_offset = _settings->add_spinscale(0, SP_ATTR_OFFSET, _("Offset"), -10, 10, 0.1, 0.01, 2);*/ _settings->type(NR_FILTER_COMPOSITE); _settings->add_combo(COMPOSITE_OVER, SP_ATTR_OPERATOR, _("Operator:"), CompositeOperatorConverter); - _k1 = _settings->add_spinslider(0, SP_ATTR_K1, _("K1:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); - _k2 = _settings->add_spinslider(0, SP_ATTR_K2, _("K2:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); - _k3 = _settings->add_spinslider(0, SP_ATTR_K3, _("K3:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); - _k4 = _settings->add_spinslider(0, SP_ATTR_K4, _("K4:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); + _k1 = _settings->add_spinscale(0, SP_ATTR_K1, _("K1:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); + _k2 = _settings->add_spinscale(0, SP_ATTR_K2, _("K2:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); + _k3 = _settings->add_spinscale(0, SP_ATTR_K3, _("K3:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); + _k4 = _settings->add_spinscale(0, SP_ATTR_K4, _("K4:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); _settings->type(NR_FILTER_CONVOLVEMATRIX); _convolve_order = _settings->add_dualspinbutton((char*)"3", SP_ATTR_ORDER, _("Size:"), 1, 5, 1, 1, 0, _("width of the convolve matrix"), _("height of the convolve matrix")); @@ -2377,50 +2377,50 @@ void FilterEffectsDialog::init_settings_widgets() //TRANSLATORS: for info on "Kernel", see http://en.wikipedia.org/wiki/Kernel_(matrix) _convolve_matrix = _settings->add_matrix(SP_ATTR_KERNELMATRIX, _("Kernel:"), _("This matrix describes the convolve operation that is applied to the input image in order to calculate the pixel colors at the output. Different arrangements of values in this matrix result in various possible visual effects. An identity matrix would lead to a motion blur effect (parallel to the matrix diagonal) while a matrix filled with a constant non-zero value would lead to a common blur effect.")); _convolve_order->signal_attr_changed().connect(sigc::mem_fun(*this, &FilterEffectsDialog::convolve_order_changed)); - _settings->add_spinslider(0, SP_ATTR_DIVISOR, _("Divisor:"), 0, 1000, 1, 0.1, 2, _("After applying the kernelMatrix to the input image to yield a number, that number is divided by divisor to yield the final destination color value. A divisor that is the sum of all the matrix values tends to have an evening effect on the overall color intensity of the result.")); - _settings->add_spinslider(0, SP_ATTR_BIAS, _("Bias:"), -10, 10, 1, 0.01, 1, _("This value is added to each component. This is useful to define a constant value as the zero response of the filter.")); + _settings->add_spinscale(0, SP_ATTR_DIVISOR, _("Divisor:"), 0, 1000, 1, 0.1, 2, _("After applying the kernelMatrix to the input image to yield a number, that number is divided by divisor to yield the final destination color value. A divisor that is the sum of all the matrix values tends to have an evening effect on the overall color intensity of the result.")); + _settings->add_spinscale(0, SP_ATTR_BIAS, _("Bias:"), -10, 10, 1, 0.01, 1, _("This value is added to each component. This is useful to define a constant value as the zero response of the filter.")); _settings->add_combo(CONVOLVEMATRIX_EDGEMODE_DUPLICATE, SP_ATTR_EDGEMODE, _("Edge Mode:"), ConvolveMatrixEdgeModeConverter, _("Determines how to extend the input image as necessary with color values so that the matrix operations can be applied when the kernel is positioned at or near the edge of the input image.")); _settings->add_checkbutton(false, SP_ATTR_PRESERVEALPHA, _("Preserve Alpha"), "true", "false", _("If set, the alpha channel won't be altered by this filter primitive.")); _settings->type(NR_FILTER_DIFFUSELIGHTING); _settings->add_color(/*default: white*/ 0xffffffff, SP_PROP_LIGHTING_COLOR, _("Diffuse Color:"), _("Defines the color of the light source")); - _settings->add_spinslider(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.01, 0.001, 3, _("This value amplifies the heights of the bump map defined by the input alpha channel")); - _settings->add_spinslider(1, SP_ATTR_DIFFUSECONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model.")); - _settings->add_dualspinslider(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1); + _settings->add_spinscale(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.01, 0.001, 3, _("This value amplifies the heights of the bump map defined by the input alpha channel")); + _settings->add_spinscale(1, SP_ATTR_DIFFUSECONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model.")); + _settings->add_dualspinscale(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1); _settings->add_lightsource(); _settings->type(NR_FILTER_DISPLACEMENTMAP); - _settings->add_spinslider(0, SP_ATTR_SCALE, _("Scale:"), 0, 100, 1, 0.01, 1, _("This defines the intensity of the displacement effect.")); + _settings->add_spinscale(0, SP_ATTR_SCALE, _("Scale:"), 0, 100, 1, 0.01, 1, _("This defines the intensity of the displacement effect.")); _settings->add_combo(DISPLACEMENTMAP_CHANNEL_ALPHA, SP_ATTR_XCHANNELSELECTOR, _("X displacement:"), DisplacementMapChannelConverter, _("Color component that controls the displacement in the X direction")); _settings->add_combo(DISPLACEMENTMAP_CHANNEL_ALPHA, SP_ATTR_YCHANNELSELECTOR, _("Y displacement:"), DisplacementMapChannelConverter, _("Color component that controls the displacement in the Y direction")); _settings->type(NR_FILTER_FLOOD); _settings->add_color(/*default: black*/ 0, SP_PROP_FLOOD_COLOR, _("Flood Color:"), _("The whole filter region will be filled with this color.")); - _settings->add_spinslider(1, SP_PROP_FLOOD_OPACITY, _("Opacity:"), 0, 1, 0.1, 0.01, 2); + _settings->add_spinscale(1, SP_PROP_FLOOD_OPACITY, _("Opacity:"), 0, 1, 0.1, 0.01, 2); _settings->type(NR_FILTER_GAUSSIANBLUR); - _settings->add_dualspinslider(SP_ATTR_STDDEVIATION, _("Standard Deviation:"), 0.01, 100, 1, 0.01, 1, _("The standard deviation for the blur operation.")); + _settings->add_dualspinscale(SP_ATTR_STDDEVIATION, _("Standard Deviation:"), 0.01, 100, 1, 0.01, 1, _("The standard deviation for the blur operation.")); _settings->type(NR_FILTER_MERGE); _settings->add_no_params(); _settings->type(NR_FILTER_MORPHOLOGY); _settings->add_combo(MORPHOLOGY_OPERATOR_ERODE, SP_ATTR_OPERATOR, _("Operator:"), MorphologyOperatorConverter, _("Erode: performs \"thinning\" of input image.\nDilate: performs \"fattenning\" of input image.")); - _settings->add_dualspinslider(SP_ATTR_RADIUS, _("Radius:"), 0, 100, 1, 0.01, 1); + _settings->add_dualspinscale(SP_ATTR_RADIUS, _("Radius:"), 0, 100, 1, 0.01, 1); _settings->type(NR_FILTER_IMAGE); _settings->add_fileorelement(SP_ATTR_XLINK_HREF, _("Source of Image:")); _settings->type(NR_FILTER_OFFSET); - _settings->add_spinslider(0, SP_ATTR_DX, _("Delta X:"), -100, 100, 1, 0.01, 1, _("This is how far the input image gets shifted to the right")); - _settings->add_spinslider(0, SP_ATTR_DY, _("Delta Y:"), -100, 100, 1, 0.01, 1, _("This is how far the input image gets shifted downwards")); + _settings->add_spinscale(0, SP_ATTR_DX, _("Delta X:"), -100, 100, 1, 0.01, 1, _("This is how far the input image gets shifted to the right")); + _settings->add_spinscale(0, SP_ATTR_DY, _("Delta Y:"), -100, 100, 1, 0.01, 1, _("This is how far the input image gets shifted downwards")); _settings->type(NR_FILTER_SPECULARLIGHTING); _settings->add_color(/*default: white*/ 0xffffffff, SP_PROP_LIGHTING_COLOR, _("Specular Color:"), _("Defines the color of the light source")); - _settings->add_spinslider(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.1, 0.01, 2, _("This value amplifies the heights of the bump map defined by the input alpha channel")); - _settings->add_spinslider(1, SP_ATTR_SPECULARCONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model.")); - _settings->add_spinslider(1, SP_ATTR_SPECULAREXPONENT, _("Exponent:"), 1, 50, 1, 0.01, 1, _("Exponent for specular term, larger is more \"shiny\".")); - _settings->add_dualspinslider(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1); + _settings->add_spinscale(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.1, 0.01, 2, _("This value amplifies the heights of the bump map defined by the input alpha channel")); + _settings->add_spinscale(1, SP_ATTR_SPECULARCONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model.")); + _settings->add_spinscale(1, SP_ATTR_SPECULAREXPONENT, _("Exponent:"), 1, 50, 1, 0.01, 1, _("Exponent for specular term, larger is more \"shiny\".")); + _settings->add_dualspinscale(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1); _settings->add_lightsource(); _settings->type(NR_FILTER_TILE); @@ -2429,9 +2429,9 @@ void FilterEffectsDialog::init_settings_widgets() _settings->type(NR_FILTER_TURBULENCE); // _settings->add_checkbutton(false, SP_ATTR_STITCHTILES, _("Stitch Tiles"), "stitch", "noStitch"); _settings->add_combo(TURBULENCE_TURBULENCE, SP_ATTR_TYPE, _("Type:"), TurbulenceTypeConverter, _("Indicates whether the filter primitive should perform a noise or turbulence function.")); - _settings->add_dualspinslider(SP_ATTR_BASEFREQUENCY, _("Base Frequency:"), 0, 1, 0.001, 0.01, 3); - _settings->add_spinslider(1, SP_ATTR_NUMOCTAVES, _("Octaves:"), 1, 10, 1, 1, 0); - _settings->add_spinslider(0, SP_ATTR_SEED, _("Seed:"), 0, 1000, 1, 1, 0, _("The starting number for the pseudo random number generator.")); + _settings->add_dualspinscale(SP_ATTR_BASEFREQUENCY, _("Base Frequency:"), 0, 1, 0.001, 0.01, 3); + _settings->add_spinscale(1, SP_ATTR_NUMOCTAVES, _("Octaves:"), 1, 10, 1, 1, 0); + _settings->add_spinscale(0, SP_ATTR_SEED, _("Seed:"), 0, 1000, 1, 1, 0, _("The starting number for the pseudo random number generator.")); } void FilterEffectsDialog::add_primitive() diff --git a/src/ui/dialog/filter-effects-dialog.h b/src/ui/dialog/filter-effects-dialog.h index 38811354e..acdeecb71 100644 --- a/src/ui/dialog/filter-effects-dialog.h +++ b/src/ui/dialog/filter-effects-dialog.h @@ -20,6 +20,7 @@ #include "sp-filter.h" #include "ui/widget/combo-enums.h" #include "ui/widget/spin-slider.h" +#include "ui/widget/spin-scale.h" #include "xml/helper-observer.h" #include "ui/dialog/desktop-tracker.h" diff --git a/src/ui/widget/filter-effect-chooser.cpp b/src/ui/widget/filter-effect-chooser.cpp index 8d6bcf60f..65706a9dc 100644 --- a/src/ui/widget/filter-effect-chooser.cpp +++ b/src/ui/widget/filter-effect-chooser.cpp @@ -22,12 +22,9 @@ namespace UI { namespace Widget { SimpleFilterModifier::SimpleFilterModifier(int flags) - : _hb_blur(false, 0), - _lb_blend(_("Blend mode:")), - _lb_blur(_("_Blur:")), - _lb_blur_unit(_("%")), + : _lb_blend(_("Blend mode:")), _blend(BlendModeConverter, SP_ATTR_INVALID, false), - _blur(0, 0, 100, 1, 0.01, 1) + _blur(_("Blur (%)"), 0, 0, 100, 1, 0.01, 1) { _flags = flags; @@ -37,11 +34,7 @@ SimpleFilterModifier::SimpleFilterModifier(int flags) _hb_blend.pack_start(_blend); } if (flags & BLUR) { - add(_hb_blur); - _lb_blur.set_alignment(Gtk::ALIGN_END, Gtk::ALIGN_CENTER); - _hb_blur.pack_start(_lb_blur, false, false, 0); - _hb_blur.pack_start(_blur, true, true, 0); - _hb_blur.pack_start(_lb_blur_unit, false, false, 3); + add(_blur); } show_all_children(); @@ -49,8 +42,6 @@ SimpleFilterModifier::SimpleFilterModifier(int flags) _hb_blend.set_spacing(12); _lb_blend.set_use_underline(); _lb_blend.set_mnemonic_widget(_blend); - _lb_blur.set_use_underline(); - _lb_blur.set_mnemonic_widget(_blur.get_scale()); _blend.signal_changed().connect(signal_blend_blur_changed()); _blur.signal_value_changed().connect(signal_blend_blur_changed()); } diff --git a/src/ui/widget/filter-effect-chooser.h b/src/ui/widget/filter-effect-chooser.h index 6afb6c180..ae3ec07c4 100644 --- a/src/ui/widget/filter-effect-chooser.h +++ b/src/ui/widget/filter-effect-chooser.h @@ -18,6 +18,7 @@ #include "combo-enums.h" #include "filter-enums.h" #include "spin-slider.h" +#include "spin-scale.h" namespace Inkscape { namespace UI { @@ -45,17 +46,14 @@ public: double get_blur_value() const; void set_blur_value(const double); void set_blur_sensitive(const bool); - Gtk::Label *get_blur_label() { return &_lb_blur; }; - private: int _flags; Gtk::HBox _hb_blend; - Gtk::HBox _hb_blur; - Gtk::Label _lb_blend, _lb_blur, _lb_blur_unit; + Gtk::Label _lb_blend; ComboBoxEnum _blend; - SpinSlider _blur; + SpinScale _blur; sigc::signal _signal_blend_blur_changed; }; diff --git a/src/ui/widget/object-composite-settings.cpp b/src/ui/widget/object-composite-settings.cpp index 1cb384501..2789676ea 100644 --- a/src/ui/widget/object-composite-settings.cpp +++ b/src/ui/widget/object-composite-settings.cpp @@ -16,6 +16,7 @@ #include +#include "desktop.h" #include "desktop-handles.h" #include "desktop-style.h" #include "document.h" @@ -32,6 +33,7 @@ #include "ui/icon-names.h" #include "display/sp-canvas.h" #include "ui/widget/style-subject.h" +#include "ui/widget/gimpspinscale.h" namespace Inkscape { namespace UI { @@ -62,50 +64,34 @@ ObjectCompositeSettings::ObjectCompositeSettings(unsigned int verb_code, char co _blur_tag(Glib::ustring(history_prefix) + ":blur"), _opacity_tag(Glib::ustring(history_prefix) + ":opacity"), _opacity_vbox(false, 0), - _opacity_label(_("Opacity:")), - _opacity_label_unit(_("%")), -#if WITH_GTKMM_3_0 - _opacity_adjustment(Gtk::Adjustment::create(100.0, 0.0, 100.0, 1.0, 1.0, 0.0)), -#else - _opacity_adjustment(100.0, 0.0, 100.0, 1.0, 1.0, 0.0), -#endif - _opacity_hscale(_opacity_adjustment), - _opacity_spin_button(_opacity_adjustment, 0.01, 1), + _opacity_scale(_("Opacity (%)"), 100.0, 0.0, 100.0, 1.0, 1.0, 1), _fe_cb(flags), _fe_vbox(false, 0), - _fe_alignment(1, 1, 1, 1), _blocked(false) { // Filter Effects pack_start(_fe_vbox, false, false, 2); - _fe_alignment.set_padding(0, 0, 4, 0); - _fe_alignment.add(_fe_cb); - _fe_vbox.pack_start(_fe_alignment, false, false, 0); + _fe_vbox.pack_start(_fe_cb, false, false, 0); _fe_cb.signal_blend_blur_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_blendBlurValueChanged)); // Opacity pack_start(_opacity_vbox, false, false, 2); - _opacity_label.set_alignment(Gtk::ALIGN_END, Gtk::ALIGN_CENTER); - _opacity_hbox.pack_start(_opacity_label, false, false, 3); - //_opacity_vbox.pack_start(_opacity_label_box, false, false, 0); - _opacity_vbox.pack_start(_opacity_hbox, false, false, 0); - _opacity_hbox.pack_start(_opacity_hscale, true, true, 0); - _opacity_hbox.pack_start(_opacity_spin_button, false, false, 0); - _opacity_hbox.pack_start(_opacity_label_unit, false, false, 3); - _opacity_hscale.set_draw_value(false); -#if WITH_GTKMM_3_0 - _opacity_adjustment->signal_value_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_opacityValueChanged)); - _opacity_label.set_mnemonic_widget(_opacity_hscale); -#else - _opacity_adjustment.signal_value_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_opacityValueChanged)); - _opacity_label.set_mnemonic_widget(_opacity_hscale); -#endif + _opacity_vbox.pack_start(_opacity_scale); + + _opacity_scale.set_appearance("compact"); + + _opacity_scale.signal_value_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_opacityValueChanged)); + + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + _opacity_scale.set_focuswidget(GTK_WIDGET(desktop->canvas)); /* SizeGroup keeps the blur and opacity labels aligned in Fill & Stroke dlg */ +/* GtkSizeGroup *labels = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); gtk_size_group_add_widget(labels, (GtkWidget *) _opacity_label.gobj()); gtk_size_group_add_widget(labels, (GtkWidget *) _fe_cb.get_blur_label()->gobj()); +*/ show_all_children(); @@ -223,11 +209,7 @@ ObjectCompositeSettings::_opacityValueChanged() SPCSSAttr *css = sp_repr_css_attr_new (); Inkscape::CSSOStringStream os; -#if WITH_GTKMM_3_0 - os << CLAMP (_opacity_adjustment->get_value() / 100, 0.0, 1.0); -#else - os << CLAMP (_opacity_adjustment.get_value() / 100, 0.0, 1.0); -#endif + os << CLAMP (_opacity_scale.get_adjustment()->get_value() / 100, 0.0, 1.0); sp_repr_css_set_property (css, "opacity", os.str().c_str()); _subject->setCSS(css); @@ -263,18 +245,14 @@ ObjectCompositeSettings::_subjectChanged() { switch (result) { case QUERY_STYLE_NOTHING: - _opacity_hbox.set_sensitive(false); + _opacity_vbox.set_sensitive(false); // gtk_widget_set_sensitive (opa, FALSE); break; case QUERY_STYLE_SINGLE: case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently case QUERY_STYLE_MULTIPLE_SAME: - _opacity_hbox.set_sensitive(true); -#if WITH_GTKMM_3_0 - _opacity_adjustment->set_value(100 * SP_SCALE24_TO_FLOAT(query->opacity.value)); -#else - _opacity_adjustment.set_value(100 * SP_SCALE24_TO_FLOAT(query->opacity.value)); -#endif + _opacity_vbox.set_sensitive(true); + _opacity_scale.get_adjustment()->set_value(100 * SP_SCALE24_TO_FLOAT(query->opacity.value)); break; } diff --git a/src/ui/widget/object-composite-settings.h b/src/ui/widget/object-composite-settings.h index 32da626d6..d3a208525 100644 --- a/src/ui/widget/object-composite-settings.h +++ b/src/ui/widget/object-composite-settings.h @@ -45,22 +45,12 @@ private: Glib::ustring _opacity_tag; Gtk::VBox _opacity_vbox; - Gtk::HBox _opacity_hbox; - Gtk::Label _opacity_label; - Gtk::Label _opacity_label_unit; -#if WITH_GTKMM_3_0 - Glib::RefPtr _opacity_adjustment; -#else - Gtk::Adjustment _opacity_adjustment; -#endif - Gtk::HScale _opacity_hscale; - Inkscape::UI::Widget::SpinButton _opacity_spin_button; + Inkscape::UI::Widget::SpinScale _opacity_scale; StyleSubject *_subject; SimpleFilterModifier _fe_cb; Gtk::VBox _fe_vbox; - Gtk::Alignment _fe_alignment; bool _blocked; gulong _desktop_activated; diff --git a/src/ui/widget/spin-slider.cpp b/src/ui/widget/spin-slider.cpp index 97ae18e20..323b1209c 100644 --- a/src/ui/widget/spin-slider.cpp +++ b/src/ui/widget/spin-slider.cpp @@ -186,7 +186,7 @@ void DualSpinSlider::set_from_attribute(SPObject* o) gchar** toks = g_strsplit(val, " ", 2); if(toks) { - double v1, v2; + double v1 = 0.0, v2 = 0.0; if(toks[0]) v1 = v2 = Glib::Ascii::strtod(toks[0]); if(toks[1]) -- cgit v1.2.3 From 1b62c7c43dead73dd277bcd139d2abfb394d9de3 Mon Sep 17 00:00:00 2001 From: John Smith Date: Sat, 22 Sep 2012 15:00:37 +0900 Subject: Fix for 166691 : Changing layer order does not update layer selector (bzr r11692) --- src/ui/widget/layer-selector.cpp | 26 ++++++++++++++++++++------ src/ui/widget/layer-selector.h | 5 ++++- 2 files changed, 24 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/ui/widget/layer-selector.cpp b/src/ui/widget/layer-selector.cpp index c6622627b..6dd45c402 100644 --- a/src/ui/widget/layer-selector.cpp +++ b/src/ui/widget/layer-selector.cpp @@ -185,7 +185,10 @@ void LayerSelector::setDesktop(SPDesktop *desktop) { if (_desktop) { // _desktop_shutdown_connection.disconnect(); - _layer_changed_connection.disconnect(); + if (_current_layer_changed_connection) + _current_layer_changed_connection.disconnect(); + if (_layers_changed_connection) + _layers_changed_connection.disconnect(); // g_signal_handlers_disconnect_by_func(_desktop, (gpointer)&detach, this); } _desktop = desktop; @@ -195,9 +198,13 @@ void LayerSelector::setDesktop(SPDesktop *desktop) { // sigc::bind (sigc::ptr_fun (detach), this)); // g_signal_connect_after(_desktop, "shutdown", GCallback(detach), this); - _layer_changed_connection = _desktop->connectCurrentLayerChanged( - sigc::mem_fun(*this, &LayerSelector::_selectLayer) - ); + LayerManager *mgr = _desktop->layer_manager; + if ( mgr ) { + _current_layer_changed_connection = mgr->connectCurrentLayerChanged( sigc::mem_fun(*this, &LayerSelector::_selectLayer) ); + //_layerUpdatedConnection = mgr->connectLayerDetailsChanged( sigc::mem_fun(*this, &LayerSelector::_updateLayer) ); + _layers_changed_connection = mgr->connectChanged( sigc::mem_fun(*this, &LayerSelector::_layersChanged) ); + } + _selectLayer(_desktop->currentLayer()); } } @@ -230,6 +237,11 @@ private: } +void LayerSelector::_layersChanged() +{ + _selectLayer(_desktop->currentLayer()); +} + /** Selects the given layer in the dropdown selector. */ void LayerSelector::_selectLayer(SPObject *layer) { @@ -300,11 +312,13 @@ void LayerSelector::_setDesktopLayer() { Gtk::ListStore::iterator selected(_selector.get_active()); SPObject *layer=_selector.get_active()->get_value(_model_columns.object); if ( _desktop && layer ) { - _layer_changed_connection.block(); + _current_layer_changed_connection.block(); + _layers_changed_connection.block(); _desktop->layer_manager->setCurrentLayer(layer); - _layer_changed_connection.unblock(); + _current_layer_changed_connection.unblock(); + _layers_changed_connection.unblock(); _selectLayer(_desktop->currentLayer()); } diff --git a/src/ui/widget/layer-selector.h b/src/ui/widget/layer-selector.h index 6fbdc9857..ff9e4ddfc 100644 --- a/src/ui/widget/layer-selector.h +++ b/src/ui/widget/layer-selector.h @@ -68,7 +68,8 @@ private: Glib::RefPtr _layer_model; // sigc::connection _desktop_shutdown_connection; - sigc::connection _layer_changed_connection; + sigc::connection _layers_changed_connection; + sigc::connection _current_layer_changed_connection; sigc::connection _selection_changed_connection; sigc::connection _visibility_toggled_connection; sigc::connection _lock_toggled_connection; @@ -76,6 +77,8 @@ private: SPObject *_layer; void _selectLayer(SPObject *layer); + void _layersChanged(); + void _setDesktopLayer(); void _buildEntry(unsigned depth, SPObject &object); -- cgit v1.2.3 From 2c8d19264256de07ca62926ca7be9a32e0b76183 Mon Sep 17 00:00:00 2001 From: John Smith Date: Sat, 22 Sep 2012 18:46:47 +0900 Subject: Fix for 166691 : Revert fix (bzr r11693) --- src/ui/widget/layer-selector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ui/widget/layer-selector.cpp b/src/ui/widget/layer-selector.cpp index 6dd45c402..a80a1aba0 100644 --- a/src/ui/widget/layer-selector.cpp +++ b/src/ui/widget/layer-selector.cpp @@ -239,7 +239,7 @@ private: void LayerSelector::_layersChanged() { - _selectLayer(_desktop->currentLayer()); + //_selectLayer(_desktop->currentLayer()); } /** Selects the given layer in the dropdown selector. -- cgit v1.2.3 From a8e76949f48267a704af633032e33d6982c682cc Mon Sep 17 00:00:00 2001 From: John Smith Date: Sat, 22 Sep 2012 18:59:01 +0900 Subject: Fix for 367548 : Invert doesnt work on objects with gradients (bzr r11694) --- src/gradient-chemistry.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/gradient-chemistry.h | 1 + src/gradient-context.cpp | 13 +------------ src/sp-gradient.h | 3 ++- src/ui/widget/selected-style.cpp | 12 ++++++++++++ src/widgets/gradient-toolbar.cpp | 22 +--------------------- 6 files changed, 54 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index 34934f75b..2ddfe5ff7 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -26,7 +26,13 @@ #include "style.h" #include "document-private.h" +#include "document-undo.h" #include "desktop-style.h" +#include "desktop-handles.h" +#include "event-context.h" +#include "selection.h" +#include "verbs.h" +#include #include "sp-gradient-reference.h" #include "sp-gradient-vector.h" @@ -47,6 +53,7 @@ #define noSP_GR_VERBOSE +using Inkscape::DocumentUndo; namespace { @@ -1508,6 +1515,36 @@ SPGradient *sp_gradient_vector_for_object( SPDocument *const doc, SPDesktop *con } +void sp_gradient_invert_selected_gradients(SPDesktop *desktop, Inkscape::PaintTarget fill_or_stroke) +{ + Inkscape::Selection *selection = sp_desktop_selection(desktop); + SPEventContext *ev = sp_desktop_event_context(desktop); + + if (!ev) { + return; + } + + GrDrag *drag = ev->get_drag(); + + // First try selected dragger + if (drag && drag->selected) { + drag->selected_reverse_vector(); + } else { // If no drag or no dragger selected, act on selection (both fill and stroke gradients) + for (GSList const* i = selection->itemList(); i != NULL; i = i->next) { + if (fill_or_stroke == Inkscape::FOR_FILL_AND_STROKE) { + sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_FILL); + sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_STROKE); + } else { + sp_item_gradient_reverse_vector(SP_ITEM(i->data), fill_or_stroke); + } + } + } + + // we did an undoable action + DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_GRADIENT, + _("Invert gradient")); +} + /* Local Variables: mode:c++ diff --git a/src/gradient-chemistry.h b/src/gradient-chemistry.h index 2f3ea4303..ff1f32dc7 100644 --- a/src/gradient-chemistry.h +++ b/src/gradient-chemistry.h @@ -70,6 +70,7 @@ SPStop *sp_vector_add_stop(SPGradient *vector, SPStop* prev_stop, SPStop* next_s void sp_gradient_transform_multiply(SPGradient *gradient, Geom::Affine postmul, bool set); +void sp_gradient_invert_selected_gradients(SPDesktop *desktop, Inkscape::PaintTarget fill_or_stroke); /** * Fetches either the fill or the stroke gradient from the given item. diff --git a/src/gradient-context.cpp b/src/gradient-context.cpp index aa8c8b929..356743eed 100644 --- a/src/gradient-context.cpp +++ b/src/gradient-context.cpp @@ -837,18 +837,7 @@ sp_gradient_context_root_handler(SPEventContext *event_context, GdkEvent *event) case GDK_KEY_r: case GDK_KEY_R: if (MOD__SHIFT_ONLY) { - // First try selected dragger - if (drag && drag->selected) { - drag->selected_reverse_vector(); - } else { // If no drag or no dragger selected, act on selection (both fill and stroke gradients) - for (GSList const* i = selection->itemList(); i != NULL; i = i->next) { - sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_FILL); - sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_STROKE); - } - } - // we did an undoable action - DocumentUndo::done(sp_desktop_document (desktop), SP_VERB_CONTEXT_GRADIENT, - _("Invert gradient")); + sp_gradient_invert_selected_gradients(desktop, Inkscape::FOR_FILL_AND_STROKE); ret = TRUE; } break; diff --git a/src/sp-gradient.h b/src/sp-gradient.h index a21a413f4..36f6f92e6 100644 --- a/src/sp-gradient.h +++ b/src/sp-gradient.h @@ -77,7 +77,8 @@ namespace Inkscape { enum PaintTarget { FOR_FILL, - FOR_STROKE + FOR_STROKE, + FOR_FILL_AND_STROKE }; /** diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp index a37f36eea..b3c4fbdcd 100644 --- a/src/ui/widget/selected-style.cpp +++ b/src/ui/widget/selected-style.cpp @@ -48,6 +48,7 @@ #include "pixmaps/cursor-adj-s.xpm" #include "pixmaps/cursor-adj-l.xpm" #include "sp-cursor.h" +#include "gradient-chemistry.h" static gdouble const _sw_presets[] = { 32 , 16 , 10 , 8 , 6 , 4 , 3 , 2 , 1.5 , 1 , 0.75 , 0.5 , 0.25 , 0.1 }; static gchar const *const _sw_presets_str[] = {"32", "16", "10", "8", "6", "4", "3", "2", "1.5", "1", "0.75", "0.5", "0.25", "0.1"}; @@ -598,6 +599,12 @@ void SelectedStyle::on_fill_invert() { SPCSSAttr *css = sp_repr_css_attr_new (); guint32 color = _thisselected[SS_FILL]; gchar c[64]; + if (_mode[SS_FILL] == SS_LGRADIENT || _mode[SS_FILL] == SS_RGRADIENT) { + g_message("Gradient"); + sp_gradient_invert_selected_gradients(_desktop, Inkscape::FOR_FILL); + return; + } + if (_mode[SS_FILL] != SS_COLOR) return; sp_svg_write_color (c, sizeof(c), SP_RGBA32_U_COMPOSE( @@ -618,6 +625,11 @@ void SelectedStyle::on_stroke_invert() { SPCSSAttr *css = sp_repr_css_attr_new (); guint32 color = _thisselected[SS_STROKE]; gchar c[64]; + if (_mode[SS_FILL] == SS_LGRADIENT || _mode[SS_FILL] == SS_RGRADIENT) { + g_message("Gradient"); + sp_gradient_invert_selected_gradients(_desktop, Inkscape::FOR_STROKE); + return; + } if (_mode[SS_STROKE] != SS_COLOR) return; sp_svg_write_color (c, sizeof(c), SP_RGBA32_U_COMPOSE( diff --git a/src/widgets/gradient-toolbar.cpp b/src/widgets/gradient-toolbar.cpp index ae85ed515..cc6b04413 100644 --- a/src/widgets/gradient-toolbar.cpp +++ b/src/widgets/gradient-toolbar.cpp @@ -633,27 +633,7 @@ static void gr_linked_changed(GtkToggleAction *act, gpointer /*data*/) static void gr_reverse(GtkWidget * /*button*/, gpointer data) { SPDesktop *desktop = static_cast(data); - Inkscape::Selection *selection = sp_desktop_selection(desktop); - SPEventContext *ev = sp_desktop_event_context(desktop); - - if (!ev) { - return; - } - - GrDrag *drag = ev->get_drag(); - - // First try selected dragger - if (drag && drag->selected) { - drag->selected_reverse_vector(); - } else { // If no drag or no dragger selected, act on selection (both fill and stroke gradients) - for (GSList const* i = selection->itemList(); i != NULL; i = i->next) { - sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_FILL); - sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_STROKE); - } - } - // we did an undoable action - DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_GRADIENT, - _("Invert gradient")); + sp_gradient_invert_selected_gradients(desktop, Inkscape::FOR_FILL_AND_STROKE); } /* -- cgit v1.2.3 From 3f61bc675d5f2f0c92d7906b8552b09df3cd411f Mon Sep 17 00:00:00 2001 From: John Smith Date: Sat, 22 Sep 2012 21:14:14 +0900 Subject: Fix for 172222 : Move direct to specified layer (bzr r11695) --- src/interface.cpp | 18 +++++ src/interface.h | 1 + src/menus-skeleton.h | 1 + src/selection-chemistry.cpp | 30 +++++++ src/selection-chemistry.h | 1 + src/ui/dialog/layer-properties.cpp | 147 ++++++++++++++++++++++++++++++++++- src/ui/dialog/layer-properties.h | 44 +++++++++++ src/ui/dialog/livepatheffect-add.cpp | 3 +- src/verbs.cpp | 6 ++ src/verbs.h | 1 + 10 files changed, 249 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/interface.cpp b/src/interface.cpp index acd56f8da..c3dbc47c8 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -79,6 +79,7 @@ // #include "inkscape.h" #include "ui/dialog/dialog-manager.h" // #include "../xml/repr.h" +#include "ui/dialog/layer-properties.h" #include #include @@ -1823,6 +1824,16 @@ void ContextMenu::MakeItemMenu (void) mi->show(); select_same_submenu->append(*mi); + /* Move to layer */ + mi = manage(new Gtk::MenuItem(_("_Move to layer ..."),1)); + if (_desktop->selection->isEmpty()) { + mi->set_sensitive(FALSE); + } else { + mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ItemMoveTo)); + } + mi->show(); + append(*mi); + /* Create link */ mi = manage(new Gtk::MenuItem(_("Create _Link"),1)); mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ItemCreateLink)); @@ -1938,6 +1949,13 @@ void ContextMenu::ItemSelectThis(void) _desktop->selection->set(_item); } +void ContextMenu::ItemMoveTo(void) +{ + Inkscape::UI::Dialogs::LayerPropertiesDialog::showMove(_desktop, _desktop->currentLayer()); +} + + + void ContextMenu::ItemCreateLink(void) { Inkscape::XML::Document *xml_doc = _desktop->doc()->getReprDoc(); diff --git a/src/interface.h b/src/interface.h index aa0281db3..ef520be28 100644 --- a/src/interface.h +++ b/src/interface.h @@ -171,6 +171,7 @@ class ContextMenu : public Gtk::Menu //callbacks for the context menu entries of an SP_TYPE_ITEM object void ItemProperties(void); void ItemSelectThis(void); + void ItemMoveTo(void); void SelectSameFillStroke(void); void SelectSameFillColor(void); void SelectSameStrokeColor(void); diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h index 999fb52fc..09366a33f 100644 --- a/src/menus-skeleton.h +++ b/src/menus-skeleton.h @@ -167,6 +167,7 @@ static char const menus_skeleton[] = " \n" " \n" " \n" +" \n" " \n" " \n" " \n" diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 068928d8f..4cdab4336 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -1314,6 +1314,36 @@ void sp_selection_to_prev_layer(SPDesktop *dt, bool suppressDone) g_slist_free(const_cast(items)); } +void sp_selection_to_layer(SPDesktop *dt, SPObject *moveto, bool suppressDone) +{ + Inkscape::Selection *selection = sp_desktop_selection(dt); + + // check if something is selected + if (selection->isEmpty()) { + dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select object(s) to move.")); + return; + } + + GSList const *items = g_slist_copy(const_cast(selection->itemList())); + + if (moveto) { + GSList *temp_clip = NULL; + sp_selection_copy_impl(items, &temp_clip, dt->doc()->getReprDoc()); // we're in the same doc, so no need to copy defs + sp_selection_delete_impl(items, false, false); + GSList *copied = sp_selection_paste_impl(sp_desktop_document(dt), moveto, &temp_clip); + selection->setReprList((GSList const *) copied); + g_slist_free(copied); + if (temp_clip) g_slist_free(temp_clip); + if (moveto) dt->setCurrentLayer(moveto); + if ( !suppressDone ) { + DocumentUndo::done(sp_desktop_document(dt), SP_VERB_LAYER_MOVE_TO, + _("Move selection to layer")); + } + } + + g_slist_free(const_cast(items)); +} + bool selection_contains_original(SPItem *item, Inkscape::Selection *selection) { diff --git a/src/selection-chemistry.h b/src/selection-chemistry.h index 0ae2a9b06..3c9c1aea9 100644 --- a/src/selection-chemistry.h +++ b/src/selection-chemistry.h @@ -97,6 +97,7 @@ void sp_selection_paste_size_separately(SPDesktop *desktop, bool apply_x, bool a void sp_selection_to_next_layer( SPDesktop *desktop, bool suppressDone = false ); void sp_selection_to_prev_layer( SPDesktop *desktop, bool suppressDone = false ); +void sp_selection_to_layer( SPDesktop *desktop, SPObject *layer, bool suppressDone = false ); void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine const &affine, bool set_i2d = true, bool compensate = true); void sp_selection_remove_transform (SPDesktop *desktop); diff --git a/src/ui/dialog/layer-properties.cpp b/src/ui/dialog/layer-properties.cpp index 465192aee..35a235dbc 100644 --- a/src/ui/dialog/layer-properties.cpp +++ b/src/ui/dialog/layer-properties.cpp @@ -28,7 +28,10 @@ #include "sp-item.h" #include "verbs.h" #include "selection.h" - +#include "selection-chemistry.h" +#include "ui/icon-names.h" +#include "ui/widget/imagetoggler.h" +#include "event-context.h" namespace Inkscape { namespace UI { @@ -51,7 +54,7 @@ LayerPropertiesDialog::LayerPropertiesDialog() 0, 1, 0, 1, Gtk::FILL, Gtk::FILL); _layout_table.attach(_layer_name_entry, 1, 2, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::FILL); - mainVBox->pack_start(_layout_table, false, false, 4); + mainVBox->pack_start(_layout_table, true, true, 4); // Buttons _close_button.set_use_stock(true); @@ -82,6 +85,7 @@ LayerPropertiesDialog::LayerPropertiesDialog() } LayerPropertiesDialog::~LayerPropertiesDialog() { + _setDesktop(NULL); _setLayer(NULL); } @@ -168,6 +172,131 @@ LayerPropertiesDialog::_setup_position_controls() { show_all_children(); } +void +LayerPropertiesDialog::_setup_layers_controls() { + + ModelColumns *zoop = new ModelColumns(); + _model = zoop; + _store = Gtk::TreeStore::create( *zoop ); + _tree.set_model( _store ); + _tree.set_headers_visible(false); + + Inkscape::UI::Widget::ImageToggler *eyeRenderer = manage( new Inkscape::UI::Widget::ImageToggler( + INKSCAPE_ICON("object-visible"), INKSCAPE_ICON("object-hidden")) ); + int visibleColNum = _tree.append_column("vis", *eyeRenderer) - 1; + Gtk::TreeViewColumn* col = _tree.get_column(visibleColNum); + if ( col ) { + col->add_attribute( eyeRenderer->property_active(), _model->_colVisible ); + } + + Inkscape::UI::Widget::ImageToggler * renderer = manage( new Inkscape::UI::Widget::ImageToggler( + INKSCAPE_ICON("object-locked"), INKSCAPE_ICON("object-unlocked")) ); + int lockedColNum = _tree.append_column("lock", *renderer) - 1; + col = _tree.get_column(lockedColNum); + if ( col ) { + col->add_attribute( renderer->property_active(), _model->_colLocked ); + } + + Gtk::CellRendererText *_text_renderer = manage(new Gtk::CellRendererText()); + int nameColNum = _tree.append_column("Name", *_text_renderer) - 1; + Gtk::TreeView::Column *_name_column = _tree.get_column(nameColNum); + _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel); + + _tree.set_expander_column( *_tree.get_column(nameColNum) ); + _tree.signal_key_press_event().connect( sigc::mem_fun(*this, &LayerPropertiesDialog::_handleKeyEvent), false ); + _tree.signal_button_press_event().connect_notify( sigc::mem_fun(*this, &LayerPropertiesDialog::_handleButtonEvent) ); + + _scroller.add( _tree ); + _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + _scroller.set_shadow_type(Gtk::SHADOW_IN); + _scroller.set_size_request(220, 180); + + SPDocument* document = _desktop->doc(); + SPRoot* root = document->getRoot(); + if ( root ) { + SPObject* target = _desktop->currentLayer(); + _store->clear(); + _addLayer( document, (SPObject *)root, 0, target, 0 ); + } + + _layout_table.remove(_layer_name_entry); + _layout_table.remove(_layer_name_label); + + _layout_table.attach(_scroller, + 0, 2, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::FILL | Gtk::EXPAND); + show_all_children(); +} + +void LayerPropertiesDialog::_addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level ) +{ + int _maxNestDepth = 20; + if ( _desktop && _desktop->layer_manager && layer && (level < _maxNestDepth) ) { + unsigned int counter = _desktop->layer_manager->childCount(layer); + for ( unsigned int i = 0; i < counter; i++ ) { + SPObject *child = _desktop->layer_manager->nthChildOf(layer, i); + if ( child ) { +#if DUMP_LAYERS + g_message(" %3d layer:%p {%s} [%s]", level, child, child->id, child->label() ); +#endif // DUMP_LAYERS + + Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend(); + Gtk::TreeModel::Row row = *iter; + row[_model->_colObject] = child; + row[_model->_colLabel] = child->label() ? child->label() : child->getId(); + row[_model->_colVisible] = SP_IS_ITEM(child) ? !SP_ITEM(child)->isHidden() : false; + row[_model->_colLocked] = SP_IS_ITEM(child) ? SP_ITEM(child)->isLocked() : false; + + if ( target && child == target ) { + _tree.expand_to_path( _store->get_path(iter) ); + + Glib::RefPtr select = _tree.get_selection(); + select->select(iter); + + //_checkTreeSelection(); + } + + _addLayer( doc, child, &row, target, level + 1 ); + } + } + } +} + +SPObject* LayerPropertiesDialog::_selectedLayer() +{ + SPObject* obj = 0; + + Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); + if ( iter ) { + Gtk::TreeModel::Row row = *iter; + obj = row[_model->_colObject]; + } + + return obj; +} + +bool LayerPropertiesDialog::_handleKeyEvent(GdkEventKey *event) +{ + + switch (get_group0_keyval(event)) { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: { + _strategy->perform(*this); + _close(); + return true; + } + break; + } + return false; +} + +void LayerPropertiesDialog::_handleButtonEvent(GdkEventButton* event) +{ + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { + _strategy->perform(*this); + _close(); + } +} + /** Formats the label for a given layer row */ void LayerPropertiesDialog::_prepareLabelRenderer( @@ -231,6 +360,20 @@ void LayerPropertiesDialog::Create::perform(LayerPropertiesDialog &dialog) { desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("New layer created.")); } +void LayerPropertiesDialog::Move::setup(LayerPropertiesDialog &dialog) { + dialog.set_title(_("Move to Layer")); + //TODO: find an unused layer number, forming name from _("Layer ") + "%d" + dialog._layer_name_entry.set_text(_("Layer")); + dialog._apply_button.set_label(_("_Move")); + dialog._setup_layers_controls(); +} + +void LayerPropertiesDialog::Move::perform(LayerPropertiesDialog &dialog) { + + SPObject *moveto = dialog._selectedLayer(); + sp_selection_to_layer(dialog._desktop, moveto, false); +} + void LayerPropertiesDialog::_setDesktop(SPDesktop *desktop) { if (desktop) { Inkscape::GC::anchor (desktop); diff --git a/src/ui/dialog/layer-properties.h b/src/ui/dialog/layer-properties.h index c7d7de130..46b31ad35 100644 --- a/src/ui/dialog/layer-properties.h +++ b/src/ui/dialog/layer-properties.h @@ -18,8 +18,12 @@ #include #include #include +#include +#include +#include #include "layer-fns.h" +#include "ui/widget/layer-selector.h" class SPDesktop; @@ -40,6 +44,9 @@ class LayerPropertiesDialog : public Gtk::Dialog { static void showCreate(SPDesktop *desktop, SPObject *layer) { _showDialog(Create::instance(), desktop, layer); } + static void showMove(SPDesktop *desktop, SPObject *layer) { + _showDialog(Move::instance(), desktop, layer); + } protected: struct Strategy { @@ -57,9 +64,15 @@ protected: void setup(LayerPropertiesDialog &dialog); void perform(LayerPropertiesDialog &dialog); }; + struct Move : public Strategy { + static Move &instance() { static Move instance; return instance; } + void setup(LayerPropertiesDialog &dialog); + void perform(LayerPropertiesDialog &dialog); + }; friend class Rename; friend class Create; + friend class Move; Strategy *_strategy; SPDesktop *_desktop; @@ -82,6 +95,31 @@ protected: Gtk::Table _layout_table; bool _position_visible; + class ModelColumns : public Gtk::TreeModel::ColumnRecord + { + public: + + ModelColumns() + { + add(_colObject); + add(_colVisible); + add(_colLocked); + add(_colLabel); + } + virtual ~ModelColumns() {} + + Gtk::TreeModelColumn _colObject; + Gtk::TreeModelColumn _colLabel; + Gtk::TreeModelColumn _colVisible; + Gtk::TreeModelColumn _colLocked; + }; + + Gtk::TreeView _tree; + ModelColumns* _model; + Glib::RefPtr _store; + Gtk::ScrolledWindow _scroller; + + PositionDropdownColumns _dropdown_columns; Gtk::CellRendererText _label_renderer; Glib::RefPtr _dropdown_list; @@ -104,8 +142,14 @@ protected: void _close(); void _setup_position_controls(); + void _setup_layers_controls(); void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row); + void _addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level ); + SPObject* _selectedLayer(); + bool _handleKeyEvent(GdkEventKey *event); + void _handleButtonEvent(GdkEventButton* event); + private: LayerPropertiesDialog(LayerPropertiesDialog const &); // no copy LayerPropertiesDialog &operator=(LayerPropertiesDialog const &); // no assign diff --git a/src/ui/dialog/livepatheffect-add.cpp b/src/ui/dialog/livepatheffect-add.cpp index c22aace37..e899dbcfc 100644 --- a/src/ui/dialog/livepatheffect-add.cpp +++ b/src/ui/dialog/livepatheffect-add.cpp @@ -48,6 +48,7 @@ LivePathEffectAdd::LivePathEffectAdd() : effectlist_treeview.set_model(effectlist_store); effectlist_treeview.set_headers_visible(false); effectlist_treeview.append_column("Name", _columns.name); + //effectlist_treeview.set_activates_default(true); /** * Initialize Effect list @@ -68,7 +69,7 @@ LivePathEffectAdd::LivePathEffectAdd() : * Buttons */ close_button.set_use_stock(true); - close_button.set_can_default(); + //close_button.set_can_default(); add_button.set_use_underline(true); add_button.set_can_default(); diff --git a/src/verbs.cpp b/src/verbs.cpp index d02472383..edfc45f8e 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -1190,6 +1190,10 @@ void LayerVerb::perform(SPAction *action, void *data) sp_selection_to_prev_layer(dt); break; } + case SP_VERB_LAYER_MOVE_TO: { + Inkscape::UI::Dialogs::LayerPropertiesDialog::showMove(dt, dt->currentLayer()); + break; + } case SP_VERB_LAYER_TO_TOP: case SP_VERB_LAYER_TO_BOTTOM: case SP_VERB_LAYER_RAISE: @@ -2465,6 +2469,8 @@ Verb *Verb::_base_verbs[] = { N_("Move selection to the layer above the current"), INKSCAPE_ICON("selection-move-to-layer-above")), new LayerVerb(SP_VERB_LAYER_MOVE_TO_PREV, "LayerMoveToPrev", N_("Move Selection to Layer Bel_ow"), N_("Move selection to the layer below the current"), INKSCAPE_ICON("selection-move-to-layer-below")), + new LayerVerb(SP_VERB_LAYER_MOVE_TO, "LayerMoveTo", N_("Move Selection to Layer..."), + N_("Move selection to layer"), INKSCAPE_ICON("layer-rename")), new LayerVerb(SP_VERB_LAYER_TO_TOP, "LayerToTop", N_("Layer to _Top"), N_("Raise the current layer to the top"), INKSCAPE_ICON("layer-top")), new LayerVerb(SP_VERB_LAYER_TO_BOTTOM, "LayerToBottom", N_("Layer to _Bottom"), diff --git a/src/verbs.h b/src/verbs.h index 2f0ae85c1..aa801803c 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -139,6 +139,7 @@ enum { SP_VERB_LAYER_PREV, SP_VERB_LAYER_MOVE_TO_NEXT, SP_VERB_LAYER_MOVE_TO_PREV, + SP_VERB_LAYER_MOVE_TO, SP_VERB_LAYER_TO_TOP, SP_VERB_LAYER_TO_BOTTOM, SP_VERB_LAYER_RAISE, -- cgit v1.2.3 From a01a3fa9d658218f3afbe5ab9922deb9c3ce38be Mon Sep 17 00:00:00 2001 From: John Smith Date: Sun, 23 Sep 2012 11:19:28 +0900 Subject: Fix for 367548 : Invert doesnt work on objects with gradients (bzr r11696) --- src/gradient-chemistry.cpp | 62 ++++++++++++++++++++++++++++++++++------ src/gradient-chemistry.h | 3 ++ src/gradient-context.cpp | 2 +- src/sp-gradient.h | 3 +- src/ui/widget/selected-style.cpp | 5 ++-- src/widgets/gradient-toolbar.cpp | 2 +- 6 files changed, 62 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index 2ddfe5ff7..ed4e81f0d 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -959,6 +959,44 @@ void sp_item_gradient_reverse_vector(SPItem *item, Inkscape::PaintTarget fill_or g_slist_free (child_objects); } +void sp_item_gradient_invert_vector_color(SPItem *item, Inkscape::PaintTarget fill_or_stroke) +{ +#ifdef SP_GR_VERBOSE + g_message("sp_item_gradient_invert_vector_color(%p, %d)", item, fill_or_stroke); +#endif + SPGradient *gradient = getGradient(item, fill_or_stroke); + if (!gradient || !SP_IS_GRADIENT(gradient)) + return; + + SPGradient *vector = gradient->getVector(); + if (!vector) // orphan! + return; + + vector = sp_gradient_fork_vector_if_necessary (vector); + if ( gradient != vector && gradient->ref->getObject() != vector ) { + sp_gradient_repr_set_link(gradient->getRepr(), vector); + } + + for ( SPObject *child = vector->firstChild(); child; child = child->getNext()) { + if (SP_IS_STOP(child)) { + guint32 color = sp_stop_get_rgba32(SP_STOP(child)); + //g_message("Stop color %d", color); + gchar c[64]; + sp_svg_write_color (c, sizeof(c), + SP_RGBA32_U_COMPOSE( + (255 - SP_RGBA32_R_U(color)), + (255 - SP_RGBA32_G_U(color)), + (255 - SP_RGBA32_B_U(color)), + SP_RGBA32_A_U(color) + ) + ); + SPCSSAttr *css = sp_repr_css_attr_new (); + sp_repr_css_set_property (css, "stop-color", c); + sp_repr_css_change(child->getRepr(), css, "style"); + sp_repr_css_attr_unref (css); + } + } +} /** Set the position of point point_type of the gradient applied to item (either fill_or_stroke) to @@ -1514,8 +1552,20 @@ SPGradient *sp_gradient_vector_for_object( SPDocument *const doc, SPDesktop *con return sp_document_default_gradient_vector( doc, color, singleStop ); } - void sp_gradient_invert_selected_gradients(SPDesktop *desktop, Inkscape::PaintTarget fill_or_stroke) +{ + Inkscape::Selection *selection = sp_desktop_selection(desktop); + + for (GSList const* i = selection->itemList(); i != NULL; i = i->next) { + sp_item_gradient_invert_vector_color(SP_ITEM(i->data), fill_or_stroke); + } + + // we did an undoable action + DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_GRADIENT, + _("Invert gradient colors")); +} + +void sp_gradient_reverse_selected_gradients(SPDesktop *desktop) { Inkscape::Selection *selection = sp_desktop_selection(desktop); SPEventContext *ev = sp_desktop_event_context(desktop); @@ -1531,18 +1581,14 @@ void sp_gradient_invert_selected_gradients(SPDesktop *desktop, Inkscape::PaintTa drag->selected_reverse_vector(); } else { // If no drag or no dragger selected, act on selection (both fill and stroke gradients) for (GSList const* i = selection->itemList(); i != NULL; i = i->next) { - if (fill_or_stroke == Inkscape::FOR_FILL_AND_STROKE) { - sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_FILL); - sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_STROKE); - } else { - sp_item_gradient_reverse_vector(SP_ITEM(i->data), fill_or_stroke); - } + sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_FILL); + sp_item_gradient_reverse_vector(SP_ITEM(i->data), Inkscape::FOR_STROKE); } } // we did an undoable action DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_GRADIENT, - _("Invert gradient")); + _("Reverse gradient")); } /* diff --git a/src/gradient-chemistry.h b/src/gradient-chemistry.h index ff1f32dc7..50422458c 100644 --- a/src/gradient-chemistry.h +++ b/src/gradient-chemistry.h @@ -70,6 +70,8 @@ SPStop *sp_vector_add_stop(SPGradient *vector, SPStop* prev_stop, SPStop* next_s void sp_gradient_transform_multiply(SPGradient *gradient, Geom::Affine postmul, bool set); +void sp_gradient_reverse_selected_gradients(SPDesktop *desktop); + void sp_gradient_invert_selected_gradients(SPDesktop *desktop, Inkscape::PaintTarget fill_or_stroke); /** @@ -98,6 +100,7 @@ void sp_item_gradient_stop_set_style(SPItem *item, GrPointType point_type, guint guint32 sp_item_gradient_stop_query_style(SPItem *item, GrPointType point_type, guint point_i, Inkscape::PaintTarget fill_or_stroke); void sp_item_gradient_edit_stop(SPItem *item, GrPointType point_type, guint point_i, Inkscape::PaintTarget fill_or_stroke); void sp_item_gradient_reverse_vector(SPItem *item, Inkscape::PaintTarget fill_or_stroke); +void sp_item_gradient_invert_vector_color(SPItem *item, Inkscape::PaintTarget fill_or_stroke); #endif // SEEN_SP_GRADIENT_CHEMISTRY_H diff --git a/src/gradient-context.cpp b/src/gradient-context.cpp index 356743eed..5b0e261de 100644 --- a/src/gradient-context.cpp +++ b/src/gradient-context.cpp @@ -837,7 +837,7 @@ sp_gradient_context_root_handler(SPEventContext *event_context, GdkEvent *event) case GDK_KEY_r: case GDK_KEY_R: if (MOD__SHIFT_ONLY) { - sp_gradient_invert_selected_gradients(desktop, Inkscape::FOR_FILL_AND_STROKE); + sp_gradient_reverse_selected_gradients(desktop); ret = TRUE; } break; diff --git a/src/sp-gradient.h b/src/sp-gradient.h index 36f6f92e6..a21a413f4 100644 --- a/src/sp-gradient.h +++ b/src/sp-gradient.h @@ -77,8 +77,7 @@ namespace Inkscape { enum PaintTarget { FOR_FILL, - FOR_STROKE, - FOR_FILL_AND_STROKE + FOR_STROKE }; /** diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp index b3c4fbdcd..a4313f677 100644 --- a/src/ui/widget/selected-style.cpp +++ b/src/ui/widget/selected-style.cpp @@ -600,9 +600,9 @@ void SelectedStyle::on_fill_invert() { guint32 color = _thisselected[SS_FILL]; gchar c[64]; if (_mode[SS_FILL] == SS_LGRADIENT || _mode[SS_FILL] == SS_RGRADIENT) { - g_message("Gradient"); sp_gradient_invert_selected_gradients(_desktop, Inkscape::FOR_FILL); return; + } if (_mode[SS_FILL] != SS_COLOR) return; @@ -625,8 +625,7 @@ void SelectedStyle::on_stroke_invert() { SPCSSAttr *css = sp_repr_css_attr_new (); guint32 color = _thisselected[SS_STROKE]; gchar c[64]; - if (_mode[SS_FILL] == SS_LGRADIENT || _mode[SS_FILL] == SS_RGRADIENT) { - g_message("Gradient"); + if (_mode[SS_STROKE] == SS_LGRADIENT || _mode[SS_STROKE] == SS_RGRADIENT) { sp_gradient_invert_selected_gradients(_desktop, Inkscape::FOR_STROKE); return; } diff --git a/src/widgets/gradient-toolbar.cpp b/src/widgets/gradient-toolbar.cpp index cc6b04413..7542e16b3 100644 --- a/src/widgets/gradient-toolbar.cpp +++ b/src/widgets/gradient-toolbar.cpp @@ -633,7 +633,7 @@ static void gr_linked_changed(GtkToggleAction *act, gpointer /*data*/) static void gr_reverse(GtkWidget * /*button*/, gpointer data) { SPDesktop *desktop = static_cast(data); - sp_gradient_invert_selected_gradients(desktop, Inkscape::FOR_FILL_AND_STROKE); + sp_gradient_reverse_selected_gradients(desktop); } /* -- cgit v1.2.3 From a17956f9fa43854a9b0f3b0a72542cdadfad916a Mon Sep 17 00:00:00 2001 From: John Smith Date: Sun, 23 Sep 2012 11:44:45 +0900 Subject: Fix for 170395 : Add Trace Bitmap to context menu of images (bzr r11697) --- src/interface.cpp | 12 ++++++++++++ src/interface.h | 5 +++++ 2 files changed, 17 insertions(+) (limited to 'src') diff --git a/src/interface.cpp b/src/interface.cpp index c3dbc47c8..0db046559 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -2097,6 +2097,12 @@ void ContextMenu::MakeImageMenu (void) mi->set_sensitive( FALSE ); } + /* Trace Bitmap */ + mi = manage(new Gtk::MenuItem(_("_Trace Bitmap..."),1)); + mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ImageTraceBitmap)); + mi->show(); + insert(*mi,positionOfLastDialog++); + /* Embed image */ if (Inkscape::Verb::getbyid( "org.ekips.filter.embedselectedimages" )) { mi = manage(new Gtk::MenuItem(C_("Context menu", "Embed Image"))); @@ -2208,6 +2214,12 @@ void ContextMenu::ImageEdit(void) } } +void ContextMenu::ImageTraceBitmap(void) +{ + inkscape_dialogs_unhide(); + _desktop->_dlg_mgr->showDialog("Trace"); +} + void ContextMenu::ImageEmbed(void) { if (_desktop->selection->isEmpty()) { diff --git a/src/interface.h b/src/interface.h index ef520be28..891e39957 100644 --- a/src/interface.h +++ b/src/interface.h @@ -224,6 +224,11 @@ class ContextMenu : public Gtk::Menu */ void ImageEmbed(void); + /** + * callback, is executed on clicking the "Trace Bitmap" menu entry + */ + void ImageTraceBitmap(void); + /** * callback, is executed on clicking the "Extract Image" menu entry */ -- cgit v1.2.3 From f29a0a4399cac653df3df4be98ff04cbfc4773cc Mon Sep 17 00:00:00 2001 From: John Smith Date: Sun, 23 Sep 2012 17:33:15 +0900 Subject: Fix for 170395 : Add Trace Bitmap to context menu of images : Focus fix (bzr r11698) --- src/interface.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/interface.cpp b/src/interface.cpp index 0db046559..fdfdce5ae 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -2102,6 +2102,9 @@ void ContextMenu::MakeImageMenu (void) mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ImageTraceBitmap)); mi->show(); insert(*mi,positionOfLastDialog++); + if (_desktop->selection->isEmpty()) { + mi->set_sensitive(FALSE); + } /* Embed image */ if (Inkscape::Verb::getbyid( "org.ekips.filter.embedselectedimages" )) { -- cgit v1.2.3