diff options
| author | Sebastian Wüst <sebi@timewaster.de> | 2013-10-20 15:32:08 +0000 |
|---|---|---|
| committer | Sebastian Wüst <sebi@timewaster.de> | 2013-10-20 15:32:08 +0000 |
| commit | 82908f949129e1fcbf62002799ee7b1b77986eed (patch) | |
| tree | c02098dd7720cdf424f2793ecd3ddac2ea86b969 /src/ui | |
| parent | changed text (diff) | |
| parent | Fix build errors with clang 3.3 and c++11 enabled. (diff) | |
| download | inkscape-82908f949129e1fcbf62002799ee7b1b77986eed.tar.gz inkscape-82908f949129e1fcbf62002799ee7b1b77986eed.zip | |
merge from trunk
(bzr r12417.1.24)
Diffstat (limited to 'src/ui')
71 files changed, 2608 insertions, 1139 deletions
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index f3c3b8473..24324c874 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -54,21 +54,24 @@ set(ui_SRC dialog/livepatheffect-editor.cpp dialog/memory.cpp dialog/messages.cpp + dialog/new-from-template.cpp dialog/object-attributes.cpp dialog/object-properties.cpp dialog/ocaldialogs.cpp dialog/print-colors-preview-dialog.cpp dialog/print.cpp - dialog/scriptdialog.cpp dialog/symbols.cpp dialog/xml-tree.cpp # dialog/session-player.cpp dialog/spellcheck.cpp dialog/svg-fonts-dialog.cpp dialog/swatches.cpp + dialog/template-load-tab.cpp + dialog/template-widget.cpp dialog/text-edit.cpp dialog/tile.cpp dialog/tracedialog.cpp + dialog/pixelartdialog.cpp dialog/transformation.cpp dialog/undo-history.cpp # dialog/whiteboard-connect.cpp @@ -113,6 +116,7 @@ set(ui_SRC widget/text.cpp widget/tolerance-slider.cpp widget/unit-menu.cpp + widget/unit-tracker.cpp view/view.cpp view/view-widget.cpp @@ -166,17 +170,21 @@ set(ui_SRC dialog/livepatheffect-editor.h dialog/memory.h dialog/messages.h + dialog/new-from-template.h dialog/object-attributes.h dialog/object-properties.h dialog/ocaldialogs.h dialog/panel-dialog.h + dialog/pixelartdialog.h dialog/print-colors-preview-dialog.h dialog/print.h - dialog/scriptdialog.h + dialog/spellcheck.h dialog/svg-fonts-dialog.h dialog/swatches.h dialog/symbols.h + dialog/template-load-tab.h + dialog/template-widget.h dialog/text-edit.h dialog/tile.h dialog/tracedialog.h @@ -242,6 +250,7 @@ set(ui_SRC widget/text.h widget/tolerance-slider.h widget/unit-menu.h + widget/unit-tracker.h view/edit-widget-interface.h view/view-widget.h diff --git a/src/ui/cache/svg_preview_cache.cpp b/src/ui/cache/svg_preview_cache.cpp index 74e94b827..a09489f6d 100644 --- a/src/ui/cache/svg_preview_cache.cpp +++ b/src/ui/cache/svg_preview_cache.cpp @@ -33,7 +33,7 @@ #include "ui/cache/svg_preview_cache.h" -GdkPixbuf* render_pixbuf(Inkscape::Drawing &drawing, double scale_factor, const Geom::Rect& dbox, unsigned psize) +GdkPixbuf* render_pixbuf(Inkscape::Drawing &drawing, double scale_factor, Geom::Rect const &dbox, unsigned psize) { Geom::Affine t(Geom::Scale(scale_factor, scale_factor)); drawing.root()->setTransform(Geom::Scale(scale_factor)); @@ -61,13 +61,7 @@ GdkPixbuf* render_pixbuf(Inkscape::Drawing &drawing, double scale_factor, const drawing.render(ct, area, Inkscape::DrawingItem::RENDER_BYPASS_CACHE); cairo_surface_flush(s); - GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(cairo_image_surface_get_data(s), - GDK_COLORSPACE_RGB, - TRUE, - 8, psize, psize, cairo_image_surface_get_stride(s), - ink_cairo_pixbuf_cleanup, s); - convert_pixbuf_argb32_to_normal(pixbuf); - + GdkPixbuf* pixbuf = ink_pixbuf_create_from_cairo_surface(s); return pixbuf; } @@ -81,6 +75,12 @@ SvgPreview::SvgPreview() SvgPreview::~SvgPreview() { + for (std::map<Glib::ustring, GdkPixbuf *>::iterator i = _pixmap_cache.begin(); + i != _pixmap_cache.end(); ++i) + { + g_object_unref(i->second); + i->second = NULL; + } } Glib::ustring SvgPreview::cache_key(gchar const *uri, gchar const *name, unsigned psize) const { @@ -102,6 +102,7 @@ GdkPixbuf* SvgPreview::get_preview_from_cache(const Glib::ustring& key) { } void SvgPreview::set_preview_in_cache(const Glib::ustring& key, GdkPixbuf* px) { + g_object_ref(px); _pixmap_cache[key] = px; } @@ -123,6 +124,8 @@ GdkPixbuf* SvgPreview::get_preview(const gchar* uri, const gchar* id, Inkscape:: void SvgPreview::remove_preview_from_cache(const Glib::ustring& key) { std::map<Glib::ustring, GdkPixbuf *>::iterator found = _pixmap_cache.find(key); if ( found != _pixmap_cache.end() ) { + g_object_unref(found->second); + found->second = NULL; _pixmap_cache.erase(key); } } diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index 72ddd90a9..da6fed86b 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -61,9 +61,8 @@ #include "sp-shape.h" #include "sp-gradient.h" #include "sp-gradient-reference.h" -#include "sp-gradient-fns.h" -#include "sp-linear-gradient-fns.h" -#include "sp-radial-gradient-fns.h" +#include "sp-linear-gradient.h" +#include "sp-radial-gradient.h" #include "sp-clippath.h" #include "sp-mask.h" #include "sp-textpath.h" @@ -79,7 +78,7 @@ #include "text-editing.h" #include "tools-switch.h" #include "path-chemistry.h" -#include "unit-constants.h" +#include "util/units.h" #include "helper/png-write.h" #include "svg/svg-color.h" #include "sp-namedview.h" @@ -94,12 +93,6 @@ #ifdef WIN32 #include <windows.h> -// Clipboard Formats: http://msdn.microsoft.com/en-us/library/ms649013(VS.85).aspx -// On Windows, most graphical applications can handle CF_DIB/CF_BITMAP and/or CF_ENHMETAFILE -// GTK automatically presents an "image/bmp" target as CF_DIB/CF_BITMAP -// Presenting "image/x-emf" as CF_ENHMETAFILE must be done by Inkscape ? -#define CLIPBOARD_WIN32_EMF_TARGET "CF_ENHMETAFILE" -#define CLIPBOARD_WIN32_EMF_MIME "image/x-emf" #endif namespace Inkscape { @@ -179,13 +172,18 @@ ClipboardManagerImpl::ClipboardManagerImpl() _text_style(NULL), _clipboard( Gtk::Clipboard::get() ) { + // Clipboard Formats: http://msdn.microsoft.com/en-us/library/ms649013(VS.85).aspx + // On Windows, most graphical applications can handle CF_DIB/CF_BITMAP and/or CF_ENHMETAFILE + // GTK automatically presents an "image/bmp" target as CF_DIB/CF_BITMAP + // Presenting "image/x-emf" as CF_ENHMETAFILE must be done by Inkscape ? + // push supported clipboard targets, in order of preference _preferred_targets.push_back("image/x-inkscape-svg"); _preferred_targets.push_back("image/svg+xml"); _preferred_targets.push_back("image/svg+xml-compressed"); -#ifdef WIN32 - _preferred_targets.push_back(CLIPBOARD_WIN32_EMF_MIME); -#endif + _preferred_targets.push_back("image/x-emf"); + _preferred_targets.push_back("CF_ENHMETAFILE"); + _preferred_targets.push_back("WCF_ENHMETAFILE"); // seen on Wine _preferred_targets.push_back("application/pdf"); _preferred_targets.push_back("image/x-adobe-illustrator"); } @@ -239,7 +237,8 @@ void ClipboardManagerImpl::copy(SPDesktop *desktop) // Special case for when the color picker ("dropper") is active - copies color under cursor if (tools_isactive(desktop, TOOLS_DROPPER)) { - _setClipboardColor(sp_dropper_context_get_color(desktop->event_context)); + //_setClipboardColor(sp_dropper_context_get_color(desktop->event_context)); + _setClipboardColor(SP_DROPPER_CONTEXT(desktop->event_context)->get_color()); _discardInternalClipboard(); return; } @@ -725,7 +724,7 @@ void ClipboardManagerImpl::_copyUsedDefs(SPItem *item) // For lpe items, copy lpe stack if applicable if (SP_IS_LPE_ITEM(item)) { SPLPEItem *lpeitem = SP_LPE_ITEM (item); - if (sp_lpe_item_has_path_effect(lpeitem)) { + if (lpeitem->hasPathEffect()) { for (PathEffectList::iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); ++it) { LivePathEffectObject *lpeobj = (*it)->lpeobject; @@ -939,7 +938,7 @@ void ClipboardManagerImpl::_applyPathEffect(SPItem *item, gchar const *effectsta { SPLPEItem *lpeitem = SP_LPE_ITEM(item); // for each effect in the stack, check if we need to fork it before adding it to the item - sp_lpe_item_fork_path_effects_if_necessary(lpeitem, 1); + lpeitem->forkPathEffectsIfNecessary(1); std::istringstream iss(effectstack); std::string href; @@ -950,7 +949,7 @@ void ClipboardManagerImpl::_applyPathEffect(SPItem *item, gchar const *effectsta return; } LivePathEffectObject *lpeobj = LIVEPATHEFFECT(obj); - sp_lpe_item_add_path_effect(lpeitem, lpeobj); + lpeitem->addPathEffect(lpeobj); } } } @@ -981,7 +980,7 @@ SPDocument *ClipboardManagerImpl::_retrieveClipboard(Glib::ustring required_targ Glib::ustring target = best_target; #ifdef WIN32 - if (best_target == CLIPBOARD_WIN32_EMF_TARGET) + if (best_target == "CF_ENHMETAFILE" || best_target == "WCF_ENHMETAFILE") { // Try to save clipboard data as en emf file (using win32 api) if (OpenClipboard(NULL)) { HGLOBAL hglb = GetClipboardData(CF_ENHMETAFILE); @@ -989,7 +988,7 @@ SPDocument *ClipboardManagerImpl::_retrieveClipboard(Glib::ustring required_targ HENHMETAFILE hemf = CopyEnhMetaFile((HENHMETAFILE) hglb, filename); if (hemf) { file_saved = true; - target = CLIPBOARD_WIN32_EMF_MIME; + target = "image/x-emf"; DeleteEnhMetaFile(hemf); } } @@ -1020,6 +1019,10 @@ SPDocument *ClipboardManagerImpl::_retrieveClipboard(Glib::ustring required_targ if (target == "image/x-inkscape-svg") { target = "image/svg+xml"; } + // Use the EMF extension to import metafiles + if (target == "CF_ENHMETAFILE" || target == "WCF_ENHMETAFILE") { + target = "image/x-emf"; + } Inkscape::Extension::DB::InputList inlist; Inkscape::Extension::db.get_input_list(inlist); @@ -1078,14 +1081,14 @@ void ClipboardManagerImpl::_onGet(Gtk::SelectionData &sel, guint /*info*/) try { if (out == outlist.end() && target == "image/png") { - gdouble dpi = PX_PER_IN; + gdouble dpi = Inkscape::Util::Quantity::convert(1, "in", "px"); guint32 bgcolor = 0x00000000; Geom::Point origin (_clipboardSPDoc->getRoot()->x.computed, _clipboardSPDoc->getRoot()->y.computed); Geom::Rect area = Geom::Rect(origin, origin + _clipboardSPDoc->getDimensions()); - unsigned long int width = (unsigned long int) (area.width() * dpi / PX_PER_IN + 0.5); - unsigned long int height = (unsigned long int) (area.height() * dpi / PX_PER_IN + 0.5); + unsigned long int width = (unsigned long int) (Inkscape::Util::Quantity::convert(area.width(), "px", "in") * dpi + 0.5); + unsigned long int height = (unsigned long int) (Inkscape::Util::Quantity::convert(area.height(), "in", "px") * dpi + 0.5); // read from namedview Inkscape::XML::Node *nv = sp_repr_lookup_name (_clipboardSPDoc->rroot, "sodipodi:namedview"); @@ -1213,10 +1216,10 @@ Glib::ustring ClipboardManagerImpl::_getBestTarget() // clipboard target debugging snippet /* - g_debug("Begin clipboard targets"); + g_message("Begin clipboard targets"); for ( std::list<Glib::ustring>::iterator x = targets.begin() ; x != targets.end(); ++x ) - g_debug("Clipboard target: %s", (*x).data()); - g_debug("End clipboard targets\n"); + g_message("Clipboard target: %s", (*x).data()); + g_message("End clipboard targets\n"); //*/ for (std::list<Glib::ustring>::iterator i = _preferred_targets.begin() ; @@ -1239,7 +1242,7 @@ Glib::ustring ClipboardManagerImpl::_getBestTarget() CloseClipboard(); if (format == CF_ENHMETAFILE) { - return CLIPBOARD_WIN32_EMF_TARGET; + return "CF_ENHMETAFILE"; } if (format == CF_DIB || format == CF_BITMAP) { return CLIPBOARD_GDK_PIXBUF_TARGET; @@ -1247,7 +1250,7 @@ Glib::ustring ClipboardManagerImpl::_getBestTarget() } if (IsClipboardFormatAvailable(CF_ENHMETAFILE)) { - return CLIPBOARD_WIN32_EMF_TARGET; + return "CF_ENHMETAFILE"; } #endif if (_clipboard->wait_is_image_available()) { @@ -1311,7 +1314,7 @@ void ClipboardManagerImpl::_setClipboardTargets() if (OpenClipboard(NULL)) { if ( _clipboardSPDoc != NULL ) { - const Glib::ustring target = CLIPBOARD_WIN32_EMF_MIME; + const Glib::ustring target = "image/x-emf"; Inkscape::Extension::DB::OutputList outlist; Inkscape::Extension::db.get_output_list(outlist); diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index 580b47522..c37767a08 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -70,6 +70,8 @@ ink_common_sources += \ ui/dialog/memory.h \ ui/dialog/messages.cpp \ ui/dialog/messages.h \ + ui/dialog/new-from-template.cpp \ + ui/dialog/new-from-template.h \ ui/dialog/ocaldialogs.cpp \ ui/dialog/ocaldialogs.h \ ui/dialog/object-attributes.cpp \ @@ -81,8 +83,6 @@ ink_common_sources += \ ui/dialog/print.h \ ui/dialog/print-colors-preview-dialog.cpp \ ui/dialog/print-colors-preview-dialog.h \ - ui/dialog/scriptdialog.cpp \ - ui/dialog/scriptdialog.h \ ui/dialog/spellcheck.cpp \ ui/dialog/spellcheck.h \ ui/dialog/svg-fonts-dialog.cpp \ @@ -91,12 +91,18 @@ ink_common_sources += \ ui/dialog/swatches.h \ ui/dialog/symbols.cpp \ ui/dialog/symbols.h \ + ui/dialog/template-load-tab.cpp \ + ui/dialog/template-load-tab.h \ + ui/dialog/template-widget.cpp \ + ui/dialog/template-widget.h \ ui/dialog/text-edit.cpp \ ui/dialog/text-edit.h \ ui/dialog/tile.cpp \ ui/dialog/tile.h \ ui/dialog/tracedialog.cpp \ ui/dialog/tracedialog.h \ + ui/dialog/pixelartdialog.cpp \ + ui/dialog/pixelartdialog.h \ ui/dialog/transformation.cpp \ ui/dialog/transformation.h \ ui/dialog/undo-history.cpp \ diff --git a/src/ui/dialog/aboutbox.cpp b/src/ui/dialog/aboutbox.cpp index 6f1137e46..121773b6d 100644 --- a/src/ui/dialog/aboutbox.cpp +++ b/src/ui/dialog/aboutbox.cpp @@ -34,6 +34,7 @@ #include "svg-view-widget.h" #include "sp-text.h" #include "text-editing.h" +#include "util/units.h" #include "inkscape-version.h" @@ -175,8 +176,8 @@ Gtk::Widget *build_splash_widget() { GtkWidget *v=sp_svg_view_widget_new(doc); - double width=doc->getWidth(); - double height=doc->getHeight(); + double width=doc->getWidth().value("px"); + double height=doc->getHeight().value("px"); doc->doUnref(); diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp index 8845b60e5..38f10c59c 100644 --- a/src/ui/dialog/align-and-distribute.cpp +++ b/src/ui/dialog/align-and-distribute.cpp @@ -47,6 +47,7 @@ #include "widgets/icon.h" #include "sp-root.h" #include "document-undo.h" +#include "desktop.h" #include <glibmm/i18n.h> @@ -367,19 +368,25 @@ public : private : Geom::Dim2 _orientation; bool _distribute; - virtual void on_button_click() - { - if (!_dialog.getDesktop()) return; - SPEventContext *event_context = sp_desktop_event_context(_dialog.getDesktop()); - if (!INK_IS_NODE_TOOL (event_context)) return; + virtual void on_button_click() { + if (!_dialog.getDesktop()) { + return; + } + + SPEventContext *event_context = _dialog.getDesktop()->getEventContext(); + + if (!INK_IS_NODE_TOOL(event_context)) { + return; + } + InkNodeTool *nt = INK_NODE_TOOL(event_context); - if (_distribute) + if (_distribute) { nt->_multipath->distributeNodes(_orientation); - else + } else { nt->_multipath->alignNodes(_orientation); - + } } }; @@ -825,7 +832,7 @@ private : static void on_tool_changed(Inkscape::Application */*inkscape*/, SPEventContext */*context*/, AlignAndDistribute *daad) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (desktop && sp_desktop_event_context(desktop)) + if (desktop && desktop->getEventContext()) daad->setMode(tools_active(desktop) == TOOLS_NODES); } diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp index 753320ab9..87c399339 100644 --- a/src/ui/dialog/clonetiler.cpp +++ b/src/ui/dialog/clonetiler.cpp @@ -34,8 +34,8 @@ #include "document.h" #include "document-undo.h" #include "filter-chemistry.h" -#include "helper/unit-menu.h" -#include "helper/units.h" +#include "ui/widget/unit-menu.h" +#include "util/units.h" #include "helper/window.h" #include "inkscape.h" #include "interface.h" @@ -58,6 +58,7 @@ #include "sp-root.h" using Inkscape::DocumentUndo; +using Inkscape::Util::unit_table; namespace Inkscape { namespace UI { @@ -1092,35 +1093,36 @@ CloneTiler::CloneTiler (void) : g_object_set_data (G_OBJECT(dlg), "widthheight", (gpointer) hb); // unitmenu - GtkWidget *u = sp_unit_selector_new (SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE); - sp_unit_selector_set_unit (SP_UNIT_SELECTOR(u), sp_desktop_namedview(SP_ACTIVE_DESKTOP)->doc_units); + unit_menu = new Inkscape::UI::Widget::UnitMenu(); + unit_menu->setUnitType(Inkscape::Util::UNIT_TYPE_LINEAR); + unit_menu->setUnit(sp_desktop_namedview(SP_ACTIVE_DESKTOP)->doc_units->abbr); + unitChangedConn = unit_menu->signal_changed().connect(sigc::mem_fun(*this, &CloneTiler::clonetiler_unit_changed)); { // Width spinbutton #if WITH_GTKMM_3_0 - Glib::RefPtr<Gtk::Adjustment> a = Gtk::Adjustment::create(0.0, -1e6, 1e6, 1.0, 10.0, 0); + fill_width = Gtk::Adjustment::create(0.0, -1e6, 1e6, 1.0, 10.0, 0); #else - Gtk::Adjustment *a = new Gtk::Adjustment (0.0, -1e6, 1e6, 1.0, 10.0, 0); + fill_width = new Gtk::Adjustment (0.0, -1e6, 1e6, 1.0, 10.0, 0); #endif - sp_unit_selector_add_adjustment (SP_UNIT_SELECTOR (u), GTK_ADJUSTMENT (a->gobj())); double value = prefs->getDouble(prefs_path + "fillwidth", 50.0); - SPUnit const &unit = *sp_unit_selector_get_unit(SP_UNIT_SELECTOR(u)); - gdouble const units = sp_pixels_get_units (value, unit); - a->set_value (units); + Inkscape::Util::Unit const *unit = unit_menu->getUnit(); + gdouble const units = Inkscape::Util::Quantity::convert(value, "px", unit); + fill_width->set_value (units); #if WITH_GTKMM_3_0 - Inkscape::UI::Widget::SpinButton *e = new Inkscape::UI::Widget::SpinButton(a, 1.0, 2); + Inkscape::UI::Widget::SpinButton *e = new Inkscape::UI::Widget::SpinButton(fill_width, 1.0, 2); #else - Inkscape::UI::Widget::SpinButton *e = new Inkscape::UI::Widget::SpinButton (*a, 1.0, 2); + Inkscape::UI::Widget::SpinButton *e = new Inkscape::UI::Widget::SpinButton (*fill_width, 1.0, 2); #endif e->set_tooltip_text (_("Width of the rectangle to be filled")); e->set_width_chars (7); e->set_digits (4); gtk_box_pack_start (GTK_BOX (hb), GTK_WIDGET(e->gobj()), TRUE, TRUE, 0); // TODO: C++ification - g_signal_connect(G_OBJECT(a->gobj()), "value_changed", - G_CALLBACK(clonetiler_fill_width_changed), u); + g_signal_connect(G_OBJECT(fill_width->gobj()), "value_changed", + G_CALLBACK(clonetiler_fill_width_changed), unit_menu); } { GtkWidget *l = gtk_label_new (""); @@ -1132,32 +1134,31 @@ CloneTiler::CloneTiler (void) : { // Height spinbutton #if WITH_GTKMM_3_0 - Glib::RefPtr<Gtk::Adjustment> a = Gtk::Adjustment::create(0.0, -1e6, 1e6, 1.0, 10.0, 0); + fill_height = Gtk::Adjustment::create(0.0, -1e6, 1e6, 1.0, 10.0, 0); #else - Gtk::Adjustment *a = new Gtk::Adjustment (0.0, -1e6, 1e6, 1.0, 10.0, 0); + fill_height = new Gtk::Adjustment (0.0, -1e6, 1e6, 1.0, 10.0, 0); #endif - sp_unit_selector_add_adjustment (SP_UNIT_SELECTOR (u), GTK_ADJUSTMENT (a->gobj())); double value = prefs->getDouble(prefs_path + "fillheight", 50.0); - SPUnit const &unit = *sp_unit_selector_get_unit(SP_UNIT_SELECTOR(u)); - gdouble const units = sp_pixels_get_units (value, unit); - a->set_value (units); + Inkscape::Util::Unit const *unit = unit_menu->getUnit(); + gdouble const units = Inkscape::Util::Quantity::convert(value, "px", unit); + fill_height->set_value (units); #if WITH_GTKMM_3_0 - Inkscape::UI::Widget::SpinButton *e = new Inkscape::UI::Widget::SpinButton(a, 1.0, 2); + Inkscape::UI::Widget::SpinButton *e = new Inkscape::UI::Widget::SpinButton(fill_height, 1.0, 2); #else - Inkscape::UI::Widget::SpinButton *e = new Inkscape::UI::Widget::SpinButton (*a, 1.0, 2); + Inkscape::UI::Widget::SpinButton *e = new Inkscape::UI::Widget::SpinButton (*fill_height, 1.0, 2); #endif e->set_tooltip_text (_("Height of the rectangle to be filled")); e->set_width_chars (7); e->set_digits (4); gtk_box_pack_start (GTK_BOX (hb), GTK_WIDGET(e->gobj()), TRUE, TRUE, 0); // TODO: C++ification - g_signal_connect(G_OBJECT(a->gobj()), "value_changed", - G_CALLBACK(clonetiler_fill_height_changed), u); + g_signal_connect(G_OBJECT(fill_height->gobj()), "value_changed", + G_CALLBACK(clonetiler_fill_height_changed), unit_menu); } - gtk_box_pack_start (GTK_BOX (hb), u, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hb), (GtkWidget*) unit_menu->gobj(), TRUE, TRUE, 0); clonetiler_table_attach (table, hb, 0.0, 2, 2); } @@ -2944,26 +2945,39 @@ void CloneTiler::clonetiler_switch_to_fill(GtkToggleButton * /*tb*/, GtkWidget * -void CloneTiler::clonetiler_fill_width_changed(GtkAdjustment *adj, GtkWidget *u) +void CloneTiler::clonetiler_fill_width_changed(GtkAdjustment *adj, Inkscape::UI::Widget::UnitMenu *u) { gdouble const raw_dist = gtk_adjustment_get_value (adj); - SPUnit const &unit = *sp_unit_selector_get_unit(SP_UNIT_SELECTOR(u)); - gdouble const pixels = sp_units_get_pixels (raw_dist, unit); + Inkscape::Util::Unit const *unit = u->getUnit(); + gdouble const pixels = Inkscape::Util::Quantity::convert(raw_dist, unit, "px"); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setDouble(prefs_path + "fillwidth", pixels); } -void CloneTiler::clonetiler_fill_height_changed(GtkAdjustment *adj, GtkWidget *u) +void CloneTiler::clonetiler_fill_height_changed(GtkAdjustment *adj, Inkscape::UI::Widget::UnitMenu *u) { gdouble const raw_dist = gtk_adjustment_get_value (adj); - SPUnit const &unit = *sp_unit_selector_get_unit(SP_UNIT_SELECTOR(u)); - gdouble const pixels = sp_units_get_pixels (raw_dist, unit); + Inkscape::Util::Unit const *unit = u->getUnit(); + gdouble const pixels = Inkscape::Util::Quantity::convert(raw_dist, unit, "px"); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setDouble(prefs_path + "fillheight", pixels); } +void CloneTiler::clonetiler_unit_changed() +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + gdouble width_pixels = prefs->getDouble(prefs_path + "fillwidth"); + gdouble height_pixels = prefs->getDouble(prefs_path + "fillheight"); + + Inkscape::Util::Unit const *unit = unit_menu->getUnit(); + + gdouble width_value = Inkscape::Util::Quantity::convert(width_pixels, "px", unit); + gdouble height_value = Inkscape::Util::Quantity::convert(height_pixels, "px", unit); + gtk_adjustment_set_value(fill_width->gobj(), width_value); + gtk_adjustment_set_value(fill_height->gobj(), height_value); +} void CloneTiler::clonetiler_do_pick_toggled(GtkToggleButton *tb, GtkWidget *dlg) { @@ -2977,7 +2991,6 @@ void CloneTiler::clonetiler_do_pick_toggled(GtkToggleButton *tb, GtkWidget *dlg) } } - } } } diff --git a/src/ui/dialog/clonetiler.h b/src/ui/dialog/clonetiler.h index 7ec30cfaa..e2a0240ee 100644 --- a/src/ui/dialog/clonetiler.h +++ b/src/ui/dialog/clonetiler.h @@ -19,6 +19,11 @@ namespace Inkscape { namespace UI { + +namespace Widget { + class UnitMenu; +} + namespace Dialog { class CloneTiler : public Widget::Panel { @@ -45,8 +50,9 @@ protected: static void clonetiler_do_pick_toggled(GtkToggleButton *tb, GtkWidget *dlg); static void clonetiler_pick_to(GtkToggleButton *tb, gpointer data); static void clonetiler_xy_changed(GtkAdjustment *adj, gpointer data); - static void clonetiler_fill_width_changed(GtkAdjustment *adj, GtkWidget *u); - static void clonetiler_fill_height_changed(GtkAdjustment *adj, GtkWidget *u); + static void clonetiler_fill_width_changed(GtkAdjustment *adj, Inkscape::UI::Widget::UnitMenu *u); + static void clonetiler_fill_height_changed(GtkAdjustment *adj, Inkscape::UI::Widget::UnitMenu *u); + void clonetiler_unit_changed(); static void clonetiler_switch_to_create(GtkToggleButton */*tb*/, GtkWidget *dlg); static void clonetiler_switch_to_fill(GtkToggleButton */*tb*/, GtkWidget *dlg); static void clonetiler_keep_bbox_toggled(GtkToggleButton *tb, gpointer /*data*/); @@ -112,12 +118,22 @@ private: DesktopTracker deskTrack; Inkscape::UI::Widget::ColorPicker *color_picker; GtkSizeGroup* table_row_labels; + Inkscape::UI::Widget::UnitMenu *unit_menu; + +#if WITH_GTKMM_3_0 + Glib::RefPtr<Gtk::Adjustment> fill_width; + Glib::RefPtr<Gtk::Adjustment> fill_height; +#else + Gtk::Adjustment *fill_width; + Gtk::Adjustment *fill_height; +#endif sigc::connection desktopChangeConn; sigc::connection selectChangedConn; sigc::connection subselChangedConn; sigc::connection selectModifiedConn; sigc::connection color_changed_connection; + sigc::connection unitChangedConn; /** * Can be invoked for setting the desktop. Currently not used. diff --git a/src/ui/dialog/color-item.cpp b/src/ui/dialog/color-item.cpp index 2292b66fc..7940c28ae 100644 --- a/src/ui/dialog/color-item.cpp +++ b/src/ui/dialog/color-item.cpp @@ -235,11 +235,7 @@ static void colorItemDragBegin( GtkWidget */*widget*/, GdkDragContext* dc, gpoin cairo_pattern_destroy(gradient); cairo_surface_flush(s); - pixbuf = gdk_pixbuf_new_from_data(cairo_image_surface_get_data(s), - GDK_COLORSPACE_RGB, TRUE, 8, - width, height, cairo_image_surface_get_stride(s), - ink_cairo_pixbuf_cleanup, s); - convert_pixbuf_argb32_to_normal(pixbuf); + pixbuf = ink_pixbuf_create_from_cairo_surface(s); } else { Glib::RefPtr<Gdk::Pixbuf> thumb = Gdk::Pixbuf::create( Gdk::COLORSPACE_RGB, false, 8, width, height ); guint32 fillWith = (0xff000000 & (item->def.getR() << 24)) @@ -561,11 +557,7 @@ void ColorItem::_regenPreview(EekPreview * preview) cairo_destroy(ct); cairo_surface_flush(s); - GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( cairo_image_surface_get_data(s), - GDK_COLORSPACE_RGB, TRUE, 8, - w, h, cairo_image_surface_get_stride(s), - ink_cairo_pixbuf_cleanup, s); - convert_pixbuf_argb32_to_normal(pixbuf); + GdkPixbuf* pixbuf = ink_pixbuf_create_from_cairo_surface(s); eek_preview_set_pixbuf( preview, pixbuf ); } diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 993f48d8f..6d32e3aa8 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -32,10 +32,10 @@ #include "ui/dialog/livepatheffect-editor.h" #include "ui/dialog/memory.h" #include "ui/dialog/messages.h" -#include "ui/dialog/scriptdialog.h" #include "ui/dialog/symbols.h" #include "ui/dialog/tile.h" #include "ui/dialog/tracedialog.h" +#include "ui/dialog/pixelartdialog.h" #include "ui/dialog/transformation.h" #include "ui/dialog/undo-history.h" #include "ui/dialog/panel-dialog.h" @@ -114,12 +114,12 @@ DialogManager::DialogManager() { registerFactory("ObjectAttributes", &create<ObjectAttributes, FloatingBehavior>); registerFactory("ObjectProperties", &create<ObjectProperties, FloatingBehavior>); // registerFactory("PrintColorsPreviewDialog", &create<PrintColorsPreviewDialog, FloatingBehavior>); - registerFactory("Script", &create<ScriptDialog, FloatingBehavior>); registerFactory("SvgFontsDialog", &create<SvgFontsDialog, FloatingBehavior>); registerFactory("Swatches", &create<SwatchesPanel, FloatingBehavior>); registerFactory("Symbols", &create<SymbolsDialog, FloatingBehavior>); registerFactory("TileDialog", &create<TileDialog, FloatingBehavior>); registerFactory("Trace", &create<TraceDialog, FloatingBehavior>); + registerFactory("PixelArt", &create<PixelArtDialog, FloatingBehavior>); registerFactory("Transformation", &create<Transformation, FloatingBehavior>); registerFactory("UndoHistory", &create<UndoHistory, FloatingBehavior>); registerFactory("InputDevices", &create<InputDialog, FloatingBehavior>); @@ -148,12 +148,12 @@ DialogManager::DialogManager() { registerFactory("ObjectAttributes", &create<ObjectAttributes, DockBehavior>); registerFactory("ObjectProperties", &create<ObjectProperties, DockBehavior>); // registerFactory("PrintColorsPreviewDialog", &create<PrintColorsPreviewDialog, DockBehavior>); - registerFactory("Script", &create<ScriptDialog, DockBehavior>); registerFactory("SvgFontsDialog", &create<SvgFontsDialog, DockBehavior>); registerFactory("Swatches", &create<SwatchesPanel, DockBehavior>); registerFactory("Symbols", &create<SymbolsDialog, DockBehavior>); registerFactory("TileDialog", &create<TileDialog, DockBehavior>); registerFactory("Trace", &create<TraceDialog, DockBehavior>); + registerFactory("PixelArt", &create<PixelArtDialog, DockBehavior>); registerFactory("Transformation", &create<Transformation, DockBehavior>); registerFactory("UndoHistory", &create<UndoHistory, DockBehavior>); registerFactory("InputDevices", &create<InputDialog, DockBehavior>); @@ -243,14 +243,14 @@ Dialog *DialogManager::getDialog(GQuark name) { /** * Shows the named dialog, creating it if necessary. */ -void DialogManager::showDialog(gchar const *name) { - showDialog(g_quark_from_string(name)); +void DialogManager::showDialog(gchar const *name, bool grabfocus) { + showDialog(g_quark_from_string(name), grabfocus); } /** * Shows the named dialog, creating it if necessary. */ -void DialogManager::showDialog(GQuark name) { +void DialogManager::showDialog(GQuark name, bool grabfocus) { bool wantTiming = Inkscape::Preferences::get()->getBool("/dialogs/debug/trackAppear", false); GTimer *timer = (wantTiming) ? g_timer_new() : 0; // if needed, must be created/started before getDialog() Dialog *dialog = getDialog(name); @@ -261,7 +261,8 @@ void DialogManager::showDialog(GQuark name) { tracker->setAutodelete(true); timer = 0; } - dialog->present(); + if (grabfocus) + dialog->present(); } if ( timer ) { diff --git a/src/ui/dialog/dialog-manager.h b/src/ui/dialog/dialog-manager.h index 33b166aa1..15573f760 100644 --- a/src/ui/dialog/dialog-manager.h +++ b/src/ui/dialog/dialog-manager.h @@ -44,8 +44,8 @@ public: void registerFactory(GQuark name, DialogFactory factory); Dialog *getDialog(gchar const* dlgName); Dialog *getDialog(GQuark dlgName); - void showDialog(gchar const *name); - void showDialog(GQuark name); + void showDialog(gchar const *name, bool grabfocus=true); + void showDialog(GQuark name, bool grabfocus=true); protected: DialogManager(DialogManager const &d); // no copy diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp index d335fb303..a6019c55c 100644 --- a/src/ui/dialog/document-properties.cpp +++ b/src/ui/dialog/document-properties.cpp @@ -28,14 +28,15 @@ #include "document.h" #include "desktop-handles.h" #include "desktop.h" -#include "helper/units.h" #include "inkscape.h" #include "io/sys.h" #include "preferences.h" +#include "shape-editor.h" #include "sp-namedview.h" -#include "sp-object-repr.h" #include "sp-root.h" #include "sp-script.h" +#include "svg/stringstream.h" +#include "tools-switch.h" #include "ui/widget/color-picker.h" #include "ui/widget/scalar-unit.h" #include "ui/dialog/filedialog.h" @@ -55,6 +56,8 @@ #include <gtkmm/stock.h> #include <gtkmm/table.h> +#include <2geom/transforms.h> + using std::pair; namespace Inkscape { @@ -170,6 +173,9 @@ DocumentProperties::DocumentProperties() signalDocumentReplaced().connect(sigc::mem_fun(*this, &DocumentProperties::_handleDocumentReplaced)); signalActivateDesktop().connect(sigc::mem_fun(*this, &DocumentProperties::_handleActivateDesktop)); signalDeactiveDesktop().connect(sigc::mem_fun(*this, &DocumentProperties::_handleDeactivateDesktop)); + + _rum_deflt._changed_connection.block(); + _rum_deflt.getUnitMenu()->signal_changed().connect(sigc::mem_fun(*this, &DocumentProperties::onDocUnitChange)); } void DocumentProperties::init() @@ -1432,11 +1438,25 @@ void DocumentProperties::update() _rcb_shad.setActive (nv->showpageshadow); if (nv->doc_units) - _rum_deflt.setUnit (nv->doc_units); - - double const doc_w_px = sp_desktop_document(dt)->getWidth(); - double const doc_h_px = sp_desktop_document(dt)->getHeight(); - _page_sizer.setDim (doc_w_px, doc_h_px); + _rum_deflt.setUnit (nv->doc_units->abbr); + + double doc_w = sp_desktop_document(dt)->getRoot()->width.value; + Glib::ustring doc_w_unit = unit_table.getUnit(sp_desktop_document(dt)->getRoot()->width.unit)->abbr; + if (doc_w_unit == "") { + doc_w_unit = "px"; + } else if (doc_w_unit == "%" && sp_desktop_document(dt)->getRoot()->viewBox_set) { + doc_w_unit = "px"; + doc_w = sp_desktop_document(dt)->getRoot()->viewBox.width(); + } + double doc_h = sp_desktop_document(dt)->getRoot()->height.value; + Glib::ustring doc_h_unit = unit_table.getUnit(sp_desktop_document(dt)->getRoot()->height.unit)->abbr; + if (doc_h_unit == "") { + doc_h_unit = "px"; + } else if (doc_h_unit == "%" && sp_desktop_document(dt)->getRoot()->viewBox_set) { + doc_h_unit = "px"; + doc_h = sp_desktop_document(dt)->getRoot()->viewBox.height(); + } + _page_sizer.setDim(Inkscape::Util::Quantity(doc_w, doc_w_unit), Inkscape::Util::Quantity(doc_h, doc_h_unit)); _page_sizer.updateFitMarginsUI(nv->getRepr()); //-----------------------------------------------------------guide page @@ -1619,6 +1639,47 @@ void DocumentProperties::onRemoveGrid() } } +/** Callback for document unit change. */ +void DocumentProperties::onDocUnitChange() +{ + SPDocument *doc = SP_ACTIVE_DOCUMENT; + Inkscape::XML::Node *repr = sp_desktop_namedview(getDesktop())->getRepr(); + Inkscape::Util::Unit const *old_doc_unit = unit_table.getUnit("px"); + if(repr->attribute("inkscape:document-units")) { + old_doc_unit = unit_table.getUnit(repr->attribute("inkscape:document-units")); + } + Inkscape::Util::Unit const *doc_unit = _rum_deflt.getUnit(); + + // Don't execute when change is being undone + if (!DocumentUndo::getUndoSensitive(doc)) { + return; + } + + // Set document unit + Inkscape::SVGOStringStream os; + os << doc_unit->abbr; + repr->setAttribute("inkscape:document-units", os.str().c_str()); + + // Set viewBox + Inkscape::Util::Quantity width = doc->getWidth(); + Inkscape::Util::Quantity height = doc->getHeight(); + doc->setViewBox(Geom::Rect::from_xywh(0, 0, width.value(doc_unit), height.value(doc_unit))); + + // TODO: Fix bug in nodes tool instead of switching away from it + if (tools_active(getDesktop()) == TOOLS_NODES) { + tools_switch(getDesktop(), TOOLS_SELECT); + } + + // Scale and translate objects + gdouble scale = Inkscape::Util::Quantity::convert(1, old_doc_unit, doc_unit); + ShapeEditor::blockSetItem(true); + doc->getRoot()->scaleChildItemsRec(Geom::Scale(scale), Geom::Point(0, doc->getHeight().value("px"))); + ShapeEditor::blockSetItem(false); + + doc->setModifiedSinceSave(); + + DocumentUndo::done(doc, SP_VERB_NONE, _("Changed document unit")); +} } // namespace Dialog } // namespace UI diff --git a/src/ui/dialog/document-properties.h b/src/ui/dialog/document-properties.h index 56fed30c4..e3ca91731 100644 --- a/src/ui/dialog/document-properties.h +++ b/src/ui/dialog/document-properties.h @@ -216,6 +216,9 @@ private: // callback methods for buttons on grids page. void onNewGrid(); void onRemoveGrid(); + + // callback for document unit change + void onDocUnitChange(); }; } // namespace Dialog diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index a851503fe..f1f7cf6c1 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -48,9 +48,8 @@ #include <glibmm/i18n.h> #include <glibmm/miscutils.h> -#include "helper/unit-menu.h" -#include "helper/units.h" -#include "unit-constants.h" +#include "ui/widget/unit-menu.h" +#include "util/units.h" #include "helper/window.h" #include "inkscape-private.h" #include "document.h" @@ -98,7 +97,7 @@ #define SP_EXPORT_MIN_SIZE 1.0 -#define DPI_BASE PX_PER_IN +#define DPI_BASE Inkscape::Util::Quantity::convert(1, "in", "px") #define EXPORT_COORD_PRECISION 3 @@ -108,6 +107,8 @@ #include "verbs.h" #include "export.h" +using Inkscape::Util::unit_table; + namespace { class MessageCleaner @@ -198,10 +199,13 @@ Export::Export (void) : /* Units box */ /* gets added to the vbox later, but the unit selector is needed earlier than that */ - unit_selector = Glib::wrap(sp_unit_selector_new (SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE)); + unit_selector = new Inkscape::UI::Widget::UnitMenu(); + unit_selector->setUnitType(Inkscape::Util::UNIT_TYPE_LINEAR); + SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (desktop) - sp_unit_selector_set_unit (SP_UNIT_SELECTOR(unit_selector->gobj()), sp_desktop_namedview(desktop)->doc_units); + unit_selector->setUnit(sp_desktop_namedview(desktop)->doc_units->abbr); + unitChangedConn = unit_selector->signal_changed().connect(sigc::mem_fun(*this, &Export::onUnitChanged)); unitbox.pack_end(*unit_selector, false, false, 0); unitbox.pack_end(units_label, false, false, 3); @@ -226,28 +230,28 @@ Export::Export (void) : t->set_col_spacings (4); #endif - x0_adj = createSpinbutton ( "x0", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, unit_selector->gobj(), + x0_adj = createSpinbutton ( "x0", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, ((Gtk::Widget*) unit_selector)->gobj(), t, 0, 0, _("_x0:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaX0Change); - x1_adj = createSpinbutton ( "x1", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, unit_selector->gobj(), + x1_adj = createSpinbutton ( "x1", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, ((Gtk::Widget*) unit_selector)->gobj(), t, 0, 1, _("x_1:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaX1Change); width_adj = createSpinbutton ( "width", 0.0, 0.0, PNG_UINT_31_MAX, 0.1, 1.0, - unit_selector->gobj(), t, 0, 2, _("Wid_th:"), "", EXPORT_COORD_PRECISION, 1, + ((Gtk::Widget*) unit_selector)->gobj(), t, 0, 2, _("Wid_th:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaWidthChange); - y0_adj = createSpinbutton ( "y0", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, unit_selector->gobj(), + y0_adj = createSpinbutton ( "y0", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, ((Gtk::Widget*) unit_selector)->gobj(), t, 2, 0, _("_y0:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaY0Change); - y1_adj = createSpinbutton ( "y1", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, unit_selector->gobj(), + y1_adj = createSpinbutton ( "y1", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, ((Gtk::Widget*) unit_selector)->gobj(), t, 2, 1, _("y_1:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaY1Change); height_adj = createSpinbutton ( "height", 0.0, 0.0, PNG_UINT_31_MAX, 0.1, 1.0, - unit_selector->gobj(), t, 2, 2, _("Hei_ght:"), "", EXPORT_COORD_PRECISION, 1, + ((Gtk::Widget*) unit_selector)->gobj(), t, 2, 2, _("Hei_ght:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaHeightChange); area_box.pack_start(togglebox, false, false, 3); @@ -496,9 +500,6 @@ Gtk::Adjustment * Export::createSpinbutton( gchar const * /*key*/, float val, fl #else Gtk::Adjustment *adj = new Gtk::Adjustment ( val, min, max, step, page, 0 ); #endif - if (us) { - sp_unit_selector_add_adjustment ( SP_UNIT_SELECTOR (us), GTK_ADJUSTMENT (adj->gobj()) ); - } int pos = 0; Gtk::Label *l = NULL; @@ -761,7 +762,7 @@ void Export::onAreaToggled () } case SELECTION_PAGE: bbox = Geom::Rect(Geom::Point(0.0, 0.0), - Geom::Point(doc->getWidth(), doc->getHeight())); + Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); // std::cout << "Using selection: PAGE" << std::endl; key = SELECTION_PAGE; @@ -979,6 +980,12 @@ Glib::ustring Export::absolutize_path_from_document_location (SPDocument *doc, c return path; } +// Called when unit is changed +void Export::onUnitChanged() +{ + onAreaToggled(); +} + void Export::onHideExceptSelected () { prefs->setBool("/dialogs/export/hideexceptselected/value", hide_export.get_active()); @@ -1042,8 +1049,8 @@ void Export::onExport () Geom::OptRect area = item->desktopVisualBounds(); if (area) { - gint width = (gint) (area->width() * dpi / PX_PER_IN + 0.5); - gint height = (gint) (area->height() * dpi / PX_PER_IN + 0.5); + gint width = (gint) (area->width() * dpi / DPI_BASE + 0.5); + gint height = (gint) (area->height() * dpi / DPI_BASE + 0.5); if (width > 1 && height > 1) { // Do export @@ -1468,8 +1475,8 @@ void Export::detectSize() { doc = sp_desktop_document (SP_ACTIVE_DESKTOP); Geom::Point x(0.0, 0.0); - Geom::Point y(doc->getWidth(), - doc->getHeight()); + Geom::Point y(doc->getWidth().value("px"), + doc->getHeight().value("px")); Geom::Rect bbox(x, y); if (bbox_equal(bbox,current_bbox)) { @@ -1507,10 +1514,6 @@ void Export::areaXChange (Gtk::Adjustment *adj) return; } - if (sp_unit_selector_update_test(SP_UNIT_SELECTOR(unit_selector->gobj()))) { - return; - } - update = true; x0 = getValuePx(x0_adj); @@ -1554,10 +1557,6 @@ void Export::areaYChange (Gtk::Adjustment *adj) return; } - if (sp_unit_selector_update_test (SP_UNIT_SELECTOR(unit_selector->gobj()))) { - return; - } - update = true; y0 = getValuePx(y0_adj); @@ -1597,10 +1596,6 @@ void Export::onAreaWidthChange() return; } - if (sp_unit_selector_update_test(reinterpret_cast<SPUnitSelector *>(unit_selector->gobj()))) { - return; - } - update = true; float x0 = getValuePx(x0_adj); @@ -1630,10 +1625,6 @@ void Export::onAreaHeightChange() return; } - if (sp_unit_selector_update_test(reinterpret_cast<SPUnitSelector *>(unit_selector->gobj()))) { - return; - } - update = true; float y0 = getValuePx(y0_adj); @@ -1709,10 +1700,6 @@ void Export::onBitmapWidthChange () return; } - if (sp_unit_selector_update_test(SP_UNIT_SELECTOR(unit_selector->gobj()))) { - return; - } - update = true; x0 = getValuePx(x0_adj); @@ -1743,10 +1730,6 @@ void Export::onBitmapHeightChange () return; } - if (sp_unit_selector_update_test(SP_UNIT_SELECTOR(unit_selector->gobj()))) { - return; - } - update = true; y0 = getValuePx(y0_adj); @@ -1803,10 +1786,6 @@ void Export::onExportXdpiChange() return; } - if (sp_unit_selector_update_test(SP_UNIT_SELECTOR(unit_selector->gobj()))) { - return; - } - update = true; x0 = getValuePx(x0_adj); @@ -1905,9 +1884,9 @@ void Export::setValuePx(Glib::RefPtr<Gtk::Adjustment>& adj, double val) void Export::setValuePx( Gtk::Adjustment *adj, double val) #endif { - const SPUnit *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(unit_selector->gobj()) ); + Unit const *unit = unit_selector->getUnit(); - setValue(adj, sp_pixels_get_units (val, *unit)); + setValue(adj, Inkscape::Util::Quantity::convert(val, "px", unit)); return; } @@ -1955,9 +1934,9 @@ float Export::getValuePx( Gtk::Adjustment *adj ) #endif { float value = getValue( adj); - const SPUnit *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(unit_selector->gobj())); + Unit const *unit = unit_selector->getUnit(); - return sp_units_get_pixels (value, *unit); + return Inkscape::Util::Quantity::convert(value, unit, "px"); } // end of sp_export_value_get_px() /** diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index b10c98fd2..f324f5dc5 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -172,6 +172,11 @@ private: #endif /** + * Unit changed callback + */ + void onUnitChanged(); + + /** * Hide except selected callback */ void onHideExceptSelected (); @@ -330,7 +335,7 @@ private: /* Unit selector widgets */ Gtk::HBox unitbox; - Gtk::Widget* unit_selector; + Inkscape::UI::Widget::UnitMenu *unit_selector; Gtk::Label units_label; /* Filename widgets */ @@ -365,6 +370,7 @@ private: sigc::connection selectChangedConn; sigc::connection subselChangedConn; sigc::connection selectModifiedConn; + sigc::connection unitChangedConn; }; diff --git a/src/ui/dialog/filedialogimpl-win32.h b/src/ui/dialog/filedialogimpl-win32.h index 2e6bb4bb8..29bcb9a45 100644 --- a/src/ui/dialog/filedialogimpl-win32.h +++ b/src/ui/dialog/filedialogimpl-win32.h @@ -140,7 +140,7 @@ public: /// Shows the file dialog, and blocks until a file /// has been selected. - /// @return Returns true if the the user selected a + /// @return Returns true if the user selected a /// file, or false if the user pressed cancel. bool show(); @@ -341,7 +341,7 @@ public: /// Shows the file dialog, and blocks until a file /// has been selected. - /// @return Returns true if the the user selected a + /// @return Returns true if the user selected a /// file, or false if the user pressed cancel. bool show(); diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp index 4401d5658..4ce2eafd1 100644 --- a/src/ui/dialog/filter-effects-dialog.cpp +++ b/src/ui/dialog/filter-effects-dialog.cpp @@ -1310,7 +1310,8 @@ void FilterEffectsDialog::FilterModifier::on_name_edited(const Glib::ustring& pa void FilterEffectsDialog::FilterModifier::on_filter_reorder(const Gtk::TreeModel::Path& path) { for(Gtk::TreeModel::iterator i = _model->children().begin(); i != _model->children().end(); ++i) { SPObject* object = (*i)[_columns.filter]; - object->getRepr()->setPosition(0); + if(object && object->getRepr()) + object->getRepr()->setPosition(0); } } diff --git a/src/ui/dialog/find.cpp b/src/ui/dialog/find.cpp index def7b5bdb..37f2761df 100644 --- a/src/ui/dialog/find.cpp +++ b/src/ui/dialog/find.cpp @@ -664,7 +664,7 @@ bool Find::item_type_match (SPItem *item) if ( SP_IS_RECT(item)) { return ( all ||check_rects.get_active()); - } else if (SP_IS_GENERICELLIPSE(item) || SP_IS_ELLIPSE(item) || SP_IS_ARC(item) || SP_IS_CIRCLE(item)) { + } else if (SP_IS_GENERICELLIPSE(item)) { return ( all || check_ellipses.get_active()); } else if (SP_IS_STAR(item) || SP_IS_POLYGON(item)) { diff --git a/src/ui/dialog/guides.cpp b/src/ui/dialog/guides.cpp index 51bbc7d9a..5dfafa78d 100644 --- a/src/ui/dialog/guides.cpp +++ b/src/ui/dialog/guides.cpp @@ -59,7 +59,7 @@ Glib::ustring GuidelinePropertiesDialog::_angle_unit_status = DEG; // initialize GuidelinePropertiesDialog::~GuidelinePropertiesDialog() { // save current status _relative_toggle_status = _relative_toggle.get_active(); - _angle_unit_status = _spin_angle.getUnit().abbr; + _angle_unit_status = _spin_angle.getUnit()->abbr; } void GuidelinePropertiesDialog::showDialog(SPGuide *guide, SPDesktop *desktop) { @@ -230,7 +230,7 @@ void GuidelinePropertiesDialog::_setup() { _unit_menu.setUnitType(UNIT_TYPE_LINEAR); _unit_menu.setUnit("px"); if (_desktop->namedview->doc_units) { - _unit_menu.setUnit( sp_unit_get_abbreviation(_desktop->namedview->doc_units) ); + _unit_menu.setUnit( _desktop->namedview->doc_units->abbr ); } _spin_angle.setUnit(_angle_unit_status); diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index bc648002d..e9cf2e753 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -28,7 +28,7 @@ #include "preferences.h" #include "verbs.h" #include "selcue.h" -#include "unit-constants.h" +#include "util/units.h" #include <iostream> #include "enums.h" #include "desktop-handles.h" @@ -879,8 +879,12 @@ void InkscapePreferences::initPageIO() _page_svgoutput.add_group_header( _("Path data")); - _svgoutput_allowrelativecoordinates.init( _("Allow relative coordinates"), "/options/svgoutput/allowrelativecoordinates", true); - _page_svgoutput.add_line( true, "", _svgoutput_allowrelativecoordinates, "", _("If set, relative coordinates may be used in path data"), false); + int const numPathstringFormat = 3; + Glib::ustring pathstringFormatLabels[numPathstringFormat] = {_("Absolute"), _("Relative"), _("Optimized")}; + int pathstringFormatValues[numPathstringFormat] = {0, 1, 2}; + + _svgoutput_pathformat.init("/options/svgoutput/pathstring_format", pathstringFormatLabels, pathstringFormatValues, numPathstringFormat, 2); + _page_svgoutput.add_line( true, _("Path string format:"), _svgoutput_pathformat, "", _("Path data should be written: only with absolute coordinates, only with relative coordinates, or optimized for string length (mixed absolute and relative coordinates)"), false); _svgoutput_forcerepeatcommands.init( _("Force repeat commands"), "/options/svgoutput/forcerepeatcommands", false); _page_svgoutput.add_line( true, "", _svgoutput_forcerepeatcommands, "", _("Force repeating of the same path command (for example, 'L 1,2 L 3,4' instead of 'L 1,2 3,4')"), false); @@ -1428,10 +1432,10 @@ void InkscapePreferences::initPageBitmaps() _("Automatically reload linked images when file is changed on disk")); _misc_bitmap_editor.init("/options/bitmapeditor/value", true); _page_bitmaps.add_line( false, _("_Bitmap editor:"), _misc_bitmap_editor, "", "", true); - _importexport_export_res.init("/dialogs/export/defaultxdpi/value", 0.0, 6000.0, 1.0, 1.0, PX_PER_IN, true, false); + _importexport_export_res.init("/dialogs/export/defaultxdpi/value", 0.0, 6000.0, 1.0, 1.0, Inkscape::Util::Quantity::convert(1, "in", "px"), true, false); _page_bitmaps.add_line( false, _("Default export _resolution:"), _importexport_export_res, _("dpi"), _("Default bitmap resolution (in dots per inch) in the Export dialog"), false); - _bitmap_copy_res.init("/options/createbitmap/resolution", 1.0, 6000.0, 1.0, 1.0, PX_PER_IN, true, false); + _bitmap_copy_res.init("/options/createbitmap/resolution", 1.0, 6000.0, 1.0, 1.0, Inkscape::Util::Quantity::convert(1, "in", "px"), true, false); _page_bitmaps.add_line( false, _("Resolution for Create Bitmap _Copy:"), _bitmap_copy_res, _("dpi"), _("Resolution used by the Create Bitmap Copy command"), false); { @@ -1443,7 +1447,7 @@ void InkscapePreferences::initPageBitmaps() _bitmap_import_quality.init("/dialogs/import/quality", 1, 100, 1, 1, 100, true, false); _page_bitmaps.add_line( false, _("Bitmap import quality:"), _bitmap_import_quality, "%", "Bitmap import quality (jpeg only). 100 is best quality", false); } - _importexport_import_res.init("/dialogs/import/defaultxdpi/value", 0.0, 6000.0, 1.0, 1.0, PX_PER_IN, true, false); + _importexport_import_res.init("/dialogs/import/defaultxdpi/value", 0.0, 6000.0, 1.0, 1.0, Inkscape::Util::Quantity::convert(1, "in", "px"), 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); diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h index 37c05df05..56222fb22 100644 --- a/src/ui/dialog/inkscape-preferences.h +++ b/src/ui/dialog/inkscape-preferences.h @@ -426,7 +426,7 @@ protected: UI::Widget::PrefSpinButton _svgoutput_minimumexponent; UI::Widget::PrefCheckButton _svgoutput_inlineattrs; UI::Widget::PrefSpinButton _svgoutput_indent; - UI::Widget::PrefCheckButton _svgoutput_allowrelativecoordinates; + UI::Widget::PrefCombo _svgoutput_pathformat; UI::Widget::PrefCheckButton _svgoutput_forcerepeatcommands; // Attribute Checking controls for SVG Output page: diff --git a/src/ui/dialog/layer-properties.cpp b/src/ui/dialog/layer-properties.cpp index 3feed2afe..b9e5d4883 100644 --- a/src/ui/dialog/layer-properties.cpp +++ b/src/ui/dialog/layer-properties.cpp @@ -3,7 +3,7 @@ * Dialog for renaming layers. */ /* Author: - * Bryce W. Harrington <bryce@bryceharrington.com> + * Bryce W. Harrington <bryce@bryceharrington.org> * Andrius R. <knutux@gmail.com> * Abhishek Sharma * diff --git a/src/ui/dialog/layer-properties.h b/src/ui/dialog/layer-properties.h index d38b8edf5..d114c6ba5 100644 --- a/src/ui/dialog/layer-properties.h +++ b/src/ui/dialog/layer-properties.h @@ -2,7 +2,7 @@ * @brief Dialog for renaming layers */ /* Author: - * Bryce W. Harrington <bryce@bryceharrington.com> + * Bryce W. Harrington <bryce@bryceharrington.org> * * Copyright (C) 2004 Bryce Harrington * diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp index c41046123..c01903f94 100644 --- a/src/ui/dialog/layers.cpp +++ b/src/ui/dialog/layers.cpp @@ -838,7 +838,8 @@ LayersPanel::LayersPanel() : _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel); _tree.set_expander_column( *_tree.get_column(nameColNum) ); - + _tree.set_search_column(nameColNum + 1); + _compositeSettings.setSubject(&_subject); _selectedConnection = _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &LayersPanel::_pushTreeSelectionToCurrent) ); diff --git a/src/ui/dialog/livepatheffect-editor.cpp b/src/ui/dialog/livepatheffect-editor.cpp index e6bb9b43d..30b16cee0 100644 --- a/src/ui/dialog/livepatheffect-editor.cpp +++ b/src/ui/dialog/livepatheffect-editor.cpp @@ -279,8 +279,8 @@ LivePathEffectEditor::onSelectionChanged(Inkscape::Selection *sel) current_lpeitem = lpeitem; set_sensitize_all(true); - if ( sp_lpe_item_has_path_effect(lpeitem) ) { - Inkscape::LivePathEffect::Effect *lpe = sp_lpe_item_get_current_lpe(lpeitem); + if ( lpeitem->hasPathEffect() ) { + Inkscape::LivePathEffect::Effect *lpe = lpeitem->getCurrentLPE(); if (lpe) { showParams(*lpe); lpe_list_locked = true; @@ -296,7 +296,7 @@ LivePathEffectEditor::onSelectionChanged(Inkscape::Selection *sel) } } else if ( SP_IS_USE(item) ) { // test whether linked object is supported by the CLONE_ORIGINAL LPE - SPItem *orig = sp_use_get_original( SP_USE(item) ); + SPItem *orig = SP_USE(item)->get_original(); if ( SP_IS_SHAPE(orig) || SP_IS_TEXT(orig) ) { @@ -332,7 +332,7 @@ LivePathEffectEditor::effect_list_reload(SPLPEItem *lpeitem) { effectlist_store->clear(); - PathEffectList effectlist = sp_lpe_item_get_effect_list(lpeitem); + PathEffectList effectlist = lpeitem->getEffectList(); PathEffectList::iterator it; for( it = effectlist.begin() ; it!=effectlist.end(); ++it) { @@ -416,7 +416,7 @@ LivePathEffectEditor::onAdd() // If item is a SPRect, convert it to path first: if ( SP_IS_RECT(item) ) { - sp_selected_path_to_curves(current_desktop, false); + sp_selected_path_to_curves(sel, current_desktop, false); item = sel->singleItem(); // get new item } @@ -433,7 +433,7 @@ LivePathEffectEditor::onAdd() // convert to path, apply CLONE_ORIGINAL LPE, link it to the cloned path // test whether linked object is supported by the CLONE_ORIGINAL LPE - SPItem *orig = sp_use_get_original( SP_USE(item) ); + SPItem *orig = SP_USE(item)->get_original(); if ( SP_IS_SHAPE(orig) || SP_IS_TEXT(orig) ) { @@ -448,9 +448,9 @@ LivePathEffectEditor::onAdd() // run sp_selection_clone_original_path_lpe sp_selection_clone_original_path_lpe(current_desktop); - item = sel->singleItem(); - item->getRepr()->setAttribute("id", id); - item->getRepr()->setAttribute("transform", transform); + SPItem *new_item = sel->singleItem(); + new_item->getRepr()->setAttribute("id", id); + new_item->getRepr()->setAttribute("transform", transform); g_free(id); g_free(transform); @@ -475,7 +475,7 @@ LivePathEffectEditor::onRemove() if ( sel && !sel->isEmpty() ) { SPItem *item = sel->singleItem(); if ( item && SP_IS_LPE_ITEM(item) ) { - sp_lpe_item_remove_current_path_effect(SP_LPE_ITEM(item), false); + SP_LPE_ITEM(item)->removeCurrentPathEffect(false); DocumentUndo::done( sp_desktop_document(current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Remove path effect") ); @@ -491,13 +491,13 @@ void LivePathEffectEditor::onUp() Inkscape::Selection *sel = _getSelection(); if ( sel && !sel->isEmpty() ) { SPItem *item = sel->singleItem(); - if ( item && SP_IS_LPE_ITEM(item) ) { - sp_lpe_item_up_current_path_effect(SP_LPE_ITEM(item)); + if ( SPLPEItem *lpeitem = SP_LPE_ITEM(item) ) { + lpeitem->upCurrentPathEffect(); DocumentUndo::done( sp_desktop_document(current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Move path effect up") ); - effect_list_reload(SP_LPE_ITEM(item)); + effect_list_reload(lpeitem); } } } @@ -507,13 +507,13 @@ void LivePathEffectEditor::onDown() Inkscape::Selection *sel = _getSelection(); if ( sel && !sel->isEmpty() ) { SPItem *item = sel->singleItem(); - if ( item && SP_IS_LPE_ITEM(item) ) { - sp_lpe_item_down_current_path_effect(SP_LPE_ITEM(item)); + if ( SPLPEItem *lpeitem = SP_LPE_ITEM(item) ) { + lpeitem->downCurrentPathEffect(); DocumentUndo::done( sp_desktop_document(current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Move path effect down") ); - effect_list_reload(SP_LPE_ITEM(item)); + effect_list_reload(lpeitem); } } } @@ -530,7 +530,7 @@ void LivePathEffectEditor::on_effect_selection_changed() if (lperef && current_lpeitem) { if (lperef->lpeobject->get_lpe()) { lpe_list_locked = true; // prevent reload of the list which would lose selection - sp_lpe_item_set_current_path_effect(current_lpeitem, lperef); + current_lpeitem->setCurrentPathEffect(lperef); showParams(*lperef->lpeobject->get_lpe()); } } diff --git a/src/ui/dialog/new-from-template.cpp b/src/ui/dialog/new-from-template.cpp new file mode 100644 index 000000000..2595e2cf5 --- /dev/null +++ b/src/ui/dialog/new-from-template.cpp @@ -0,0 +1,59 @@ +/** @file + * @brief New From Template main dialog - implementation + */ +/* Authors: + * Jan Darowski <jan.darowski@gmail.com>, supervised by Krzysztof Kosiński + * + * Copyright (C) 2013 Authors + * Released under GNU GPL, read the file 'COPYING' for more information + */ + + +#include "new-from-template.h" +#include "file.h" + +#include <gtkmm/alignment.h> +#include <glibmm/i18n.h> + + +namespace Inkscape { +namespace UI { + + +NewFromTemplate::NewFromTemplate() + : _create_template_button(_("Create from template")) +{ + set_title(_("New From Template")); + resize(400, 400); + + get_vbox()->pack_start(_main_widget); + + Gtk::Alignment *align; + align = manage(new Gtk::Alignment(Gtk::ALIGN_END, Gtk::ALIGN_CENTER, 0.0, 0.0)); + get_vbox()->pack_end(*align, Gtk::PACK_SHRINK); + align->set_padding(0, 0, 0, 15); + align->add(_create_template_button); + + _create_template_button.signal_pressed().connect( + sigc::mem_fun(*this, &NewFromTemplate::_createFromTemplate)); + + show_all(); +} + + +void NewFromTemplate::_createFromTemplate() +{ + _main_widget.createTemplate(); + + response(0); +} + + +void NewFromTemplate::load_new_from_template() +{ + NewFromTemplate dl; + dl.run(); +} + +} +} diff --git a/src/ui/dialog/new-from-template.h b/src/ui/dialog/new-from-template.h new file mode 100644 index 000000000..8ebcb2863 --- /dev/null +++ b/src/ui/dialog/new-from-template.h @@ -0,0 +1,39 @@ +/** @file + * @brief New From Template main dialog + */ +/* Authors: + * Jan Darowski <jan.darowski@gmail.com>, supervised by Krzysztof Kosiński + * + * Copyright (C) 2013 Authors + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef INKSCAPE_SEEN_UI_DIALOG_NEW_FROM_TEMPLATE_H +#define INKSCAPE_SEEN_UI_DIALOG_NEW_FROM_TEMPLATE_H + +#include <gtkmm/dialog.h> +#include <gtkmm/button.h> + +#include "template-load-tab.h" + + +namespace Inkscape { +namespace UI { + + +class NewFromTemplate : public Gtk::Dialog +{ +public: + static void load_new_from_template(); + +private: + NewFromTemplate(); + Gtk::Button _create_template_button; + TemplateLoadTab _main_widget; + + void _createFromTemplate(); +}; + +} +} +#endif diff --git a/src/ui/dialog/object-attributes.cpp b/src/ui/dialog/object-attributes.cpp index 027c9ae56..9a7b91c57 100644 --- a/src/ui/dialog/object-attributes.cpp +++ b/src/ui/dialog/object-attributes.cpp @@ -124,16 +124,20 @@ void ObjectAttributes::widget_setup (void) } blocked = true; + + // CPPIFY SPObject *obj = SP_OBJECT(item); //to get the selected item - GObjectClass *klass = G_OBJECT_GET_CLASS(obj); //to deduce the object's type - GType type = G_TYPE_FROM_CLASS(klass); +// GObjectClass *klass = G_OBJECT_GET_CLASS(obj); //to deduce the object's type +// GType type = G_TYPE_FROM_CLASS(klass); const SPAttrDesc *desc; - if (type == SP_TYPE_ANCHOR) +// if (type == SP_TYPE_ANCHOR) + if (SP_IS_ANCHOR(item)) { desc = anchor_desc; } - else if (type == SP_TYPE_IMAGE) +// else if (type == SP_TYPE_IMAGE) + else if (SP_IS_IMAGE(item)) { Inkscape::XML::Node *ir = obj->getRepr(); const gchar *href = ir->attribute("xlink:href"); diff --git a/src/ui/dialog/ocaldialogs.cpp b/src/ui/dialog/ocaldialogs.cpp index f87288494..ca0edfadd 100644 --- a/src/ui/dialog/ocaldialogs.cpp +++ b/src/ui/dialog/ocaldialogs.cpp @@ -1017,7 +1017,7 @@ void SearchResultList::populate_from_xml(xmlNode * a_node) } else if (!strcmp(reinterpret_cast<const char*>(cur_node->name), "enclosure")) { - xmlChar *xml_url = xmlGetProp(cur_node, reinterpret_cast<xmlChar*>(g_strdup("url"))); + xmlChar *xml_url = xmlGetProp(cur_node, reinterpret_cast<xmlChar const*>("url")); char* url = reinterpret_cast<char*>(xml_url); char* filename = g_path_get_basename(url); @@ -1027,7 +1027,7 @@ void SearchResultList::populate_from_xml(xmlNode * a_node) } else if (!strcmp(reinterpret_cast<const char*>(cur_node->name), "thumbnail")) { - xmlChar *xml_thumbnail_url = xmlGetProp(cur_node, reinterpret_cast<xmlChar*>(g_strdup("url"))); + xmlChar *xml_thumbnail_url = xmlGetProp(cur_node, reinterpret_cast<xmlChar const*>("url")); char* thumbnail_url = reinterpret_cast<char*>(xml_thumbnail_url); char* thumbnail_filename = g_path_get_basename(thumbnail_url); diff --git a/src/ui/dialog/pixelartdialog.cpp b/src/ui/dialog/pixelartdialog.cpp new file mode 100644 index 000000000..ff527434e --- /dev/null +++ b/src/ui/dialog/pixelartdialog.cpp @@ -0,0 +1,512 @@ +/** + * @file + * Pixel art tracing settings dialog - implementation. + */ +/* Authors: + * Bob Jamison <rjamison@titan.com> + * Stéphane Gimenez <dev@gim.name> + * Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com> + * Other dudes from The Inkscape Organization + * + * Copyright (C) 2004-2013 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "pixelartdialog.h" +#include <gtkmm/radiobutton.h> +#include <gtkmm/stock.h> +#include <gtkmm/messagedialog.h> + +#include <gtk/gtk.h> //for GTK_RESPONSE* types +#include <glibmm/i18n.h> + +#include "ui/widget/spinbutton.h" +#include "ui/widget/frame.h" + +#include "desktop.h" +#include "desktop-tracker.h" +#include "message-stack.h" +#include "selection.h" +#include "preferences.h" + +#include "sp-image.h" +#include "display/cairo-utils.h" +#include "libdepixelize/kopftracer2011.h" +#include <algorithm> +#include "document.h" +#include "xml/repr.h" +#include "xml/document.h" +#include "svg/svg.h" +#include "svg/svg-color.h" +#include "color.h" +#include "svg/css-ostringstream.h" +#include "document-undo.h" + +#ifdef HAVE_OPENMP +#include <omp.h> +#endif // HAVE_OPENMP + +namespace Inkscape { +namespace UI { +namespace Dialog { + +template<class T> +T move(T &obj) +{ +#ifdef LIBDEPIXELIZE_ENABLE_CPP11 + return std::move(obj); +#else + T ret; + std::swap(obj, ret); + return ret; +#endif // LIBDEPIXELIZE_ENABLE_CPP11 +} + +/** + * A dialog for adjusting pixel art -> vector tracing parameters + */ +class PixelArtDialogImpl : public PixelArtDialog +{ +public: + PixelArtDialogImpl(); + + ~PixelArtDialogImpl(); + +private: + void setDesktop(SPDesktop *desktop); + void setTargetDesktop(SPDesktop *desktop); + + //############ Events + + void responseCallback(int response_id); + + //############ UI Logic + + Tracer::Kopf2011::Options options(); + + void vectorize(); + void processLibdepixelize(SPImage *img); + void setDefaults(); + void updatePreview(); + + bool ignorePreview; + bool pendingPreview; + + //############ UI + + Gtk::HBox buttonsHBox; + + Gtk::Button *mainOkButton; + Gtk::Button *mainCancelButton; + Gtk::Button *mainResetButton; + + Gtk::VBox heuristicsVBox; + UI::Widget::Frame heuristicsFrame; + + Gtk::HBox curvesMultiplierHBox; + Gtk::Label curvesMultiplierLabel; + Inkscape::UI::Widget::SpinButton curvesMultiplierSpinner; + + Gtk::HBox islandsWeightHBox; + Gtk::Label islandsWeightLabel; + Inkscape::UI::Widget::SpinButton islandsWeightSpinner; + + Gtk::HBox sparsePixelsMultiplierHBox; + Gtk::Label sparsePixelsMultiplierLabel; + Inkscape::UI::Widget::SpinButton sparsePixelsMultiplierSpinner; + + Gtk::HBox sparsePixelsRadiusHBox; + Gtk::Label sparsePixelsRadiusLabel; + Inkscape::UI::Widget::SpinButton sparsePixelsRadiusSpinner; + + Gtk::VBox outputVBox; + UI::Widget::Frame outputFrame; + Gtk::RadioButtonGroup outputGroup; + + Gtk::RadioButton voronoiRadioButton; + Gtk::RadioButton noOptimizeRadioButton; +#if LIBDEPIXELIZE_INKSCAPE_ENABLE_SMOOTH + Gtk::RadioButton optimizeRadioButton; +#endif // LIBDEPIXELIZE_INKSCAPE_ENABLE_SMOOTH + + SPDesktop *desktop; + DesktopTracker deskTrack; + sigc::connection desktopChangeConn; +}; + +void PixelArtDialogImpl::setDesktop(SPDesktop *desktop) +{ + Panel::setDesktop(desktop); + deskTrack.setBase(desktop); +} + +void PixelArtDialogImpl::setTargetDesktop(SPDesktop *desktop) +{ + this->desktop = desktop; +} + +PixelArtDialogImpl::PixelArtDialogImpl() : + PixelArtDialog(), + ignorePreview(false), + pendingPreview(false) +{ + + Gtk::Box *contents = _getContents(); + + // Heuristics + { + curvesMultiplierLabel.set_label(_("_Curves (multiplier)")); + curvesMultiplierLabel.set_use_underline(true); + curvesMultiplierLabel.set_mnemonic_widget(curvesMultiplierSpinner); + curvesMultiplierLabel.set_tooltip_text(_("Favors connections that are part of a long curve")); + curvesMultiplierSpinner.set_increments(0.125, 0); + curvesMultiplierSpinner.set_digits(3); + curvesMultiplierSpinner.set_range(-10, 10); + curvesMultiplierSpinner.get_adjustment()->signal_value_changed() + .connect(sigc::mem_fun(*this, &PixelArtDialogImpl::updatePreview)); + + curvesMultiplierHBox.pack_start(curvesMultiplierLabel, false, false); + curvesMultiplierHBox.pack_end(curvesMultiplierSpinner, false, false); + heuristicsVBox.pack_start(curvesMultiplierHBox, false, false); + + islandsWeightLabel.set_label(_("_Islands (weight)")); + islandsWeightLabel.set_use_underline(true); + islandsWeightLabel.set_mnemonic_widget(islandsWeightSpinner); + islandsWeightLabel.set_tooltip_text(_("Avoid single disconnected pixels")); + + islandsWeightSpinner.set_tooltip_text(_("A constant vote value")); + islandsWeightSpinner.set_increments(1, 0); + islandsWeightSpinner.set_range(-20, 20); + islandsWeightSpinner.get_adjustment()->signal_value_changed() + .connect(sigc::mem_fun(*this, &PixelArtDialogImpl::updatePreview)); + + islandsWeightHBox.pack_start(islandsWeightLabel, false, false); + islandsWeightHBox.pack_end(islandsWeightSpinner, false, false); + heuristicsVBox.pack_start(islandsWeightHBox, false, false); + + sparsePixelsRadiusLabel.set_label(_("Sparse pixels (window _radius)")); + sparsePixelsRadiusLabel.set_use_underline(true); + sparsePixelsRadiusLabel.set_mnemonic_widget(sparsePixelsRadiusSpinner); + + sparsePixelsRadiusSpinner.set_increments(1, 0); + sparsePixelsRadiusSpinner.set_range(2, 8); + sparsePixelsRadiusSpinner.get_adjustment()->signal_value_changed() + .connect(sigc::mem_fun(*this, &PixelArtDialogImpl::updatePreview)); + + sparsePixelsRadiusSpinner.set_tooltip_text(_("The radius of the window analyzed")); + sparsePixelsMultiplierLabel.set_label(_("Sparse pixels (_multiplier)")); + sparsePixelsMultiplierLabel.set_use_underline(true); + sparsePixelsMultiplierLabel.set_mnemonic_widget(sparsePixelsMultiplierSpinner); + + sparsePixelsMultiplierSpinner.set_increments(0.125, 0); + sparsePixelsMultiplierSpinner.set_digits(3); + sparsePixelsMultiplierSpinner.set_range(-10, 10); + sparsePixelsMultiplierSpinner.get_adjustment()->signal_value_changed() + .connect(sigc::mem_fun(*this, &PixelArtDialogImpl::updatePreview)); + + { + char const *str = _("Favors connections that are part of foreground color"); + sparsePixelsRadiusLabel.set_tooltip_text(str); + sparsePixelsMultiplierLabel.set_tooltip_text(str); + } + + { + char const *str = _("The heuristic computed vote will be multiplied by this value"); + curvesMultiplierSpinner.set_tooltip_text(str); + sparsePixelsMultiplierSpinner.set_tooltip_text(str); + } + + sparsePixelsRadiusHBox.pack_start(sparsePixelsRadiusLabel, false, false); + sparsePixelsRadiusHBox.pack_end(sparsePixelsRadiusSpinner, false, false); + heuristicsVBox.pack_start(sparsePixelsRadiusHBox, false, false); + + sparsePixelsMultiplierHBox.pack_start(sparsePixelsMultiplierLabel, false, false); + sparsePixelsMultiplierHBox.pack_end(sparsePixelsMultiplierSpinner, false, false); + heuristicsVBox.pack_start(sparsePixelsMultiplierHBox, false, false); + + heuristicsFrame.set_label(_("Heuristics")); + heuristicsFrame.add(heuristicsVBox); + contents->pack_start(heuristicsFrame, false, false); + } + + // Output + { + voronoiRadioButton.set_label(_("_Voronoi diagram")); + voronoiRadioButton.set_tooltip_text(_("Output composed of straight lines")); + voronoiRadioButton.set_use_underline(true); + outputGroup = voronoiRadioButton.get_group(); + + outputVBox.pack_start(voronoiRadioButton, false, false); + + noOptimizeRadioButton.set_label(_("Convert to _B-spline curves")); + noOptimizeRadioButton.set_tooltip_text(_("Preserve staircasing artifacts")); + noOptimizeRadioButton.set_use_underline(true); + noOptimizeRadioButton.set_group(outputGroup); + + outputVBox.pack_start(noOptimizeRadioButton, false, false); + +#if LIBDEPIXELIZE_INKSCAPE_ENABLE_SMOOTH + optimizeRadioButton.set_label(_("_Smooth curves")); + optimizeRadioButton.set_tooltip_text(_("The Kopf-Lischinski algorithm")); + optimizeRadioButton.set_use_underline(true); + optimizeRadioButton.set_group(outputGroup); + + outputVBox.pack_start(optimizeRadioButton, false, false); +#endif // LIBDEPIXELIZE_INKSCAPE_ENABLE_SMOOTH + + outputFrame.set_label(_("Output")); + outputFrame.add(outputVBox); + contents->pack_start(outputFrame, true, false); + } + + // Buttons + { + mainResetButton = addResponseButton(_("Reset"), GTK_RESPONSE_HELP, true); + mainResetButton ->set_tooltip_text(_("Reset all settings to defaults")); + + //## The OK button + mainCancelButton = addResponseButton(Gtk::Stock::STOP, GTK_RESPONSE_CANCEL); + if (mainCancelButton) { + mainCancelButton->set_tooltip_text(_("Abort a trace in progress")); + mainCancelButton->set_sensitive(false); + } + mainOkButton = addResponseButton(Gtk::Stock::OK, GTK_RESPONSE_OK); + mainOkButton->set_tooltip_text(_("Execute the trace")); + + contents->pack_start(buttonsHBox); + } + + setDefaults(); + + show_all_children(); + + desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &PixelArtDialogImpl::setTargetDesktop) ); + deskTrack.connect(GTK_WIDGET(gobj())); + + signalResponse().connect(sigc::mem_fun(*this, &PixelArtDialogImpl::responseCallback)); +} + +void PixelArtDialogImpl::responseCallback(int response_id) +{ + if (response_id == GTK_RESPONSE_OK) { + vectorize(); + } else if (response_id == GTK_RESPONSE_CANCEL) { + // TODO + } else if (response_id == GTK_RESPONSE_HELP) { + setDefaults(); + } else { + hide(); + return; + } +} + +Tracer::Kopf2011::Options PixelArtDialogImpl::options() +{ + Tracer::Kopf2011::Options options; + + options.curvesMultiplier = curvesMultiplierSpinner.get_value(); + options.islandsWeight = islandsWeightSpinner.get_value_as_int(); + options.sparsePixelsMultiplier = sparsePixelsMultiplierSpinner.get_value(); + options.sparsePixelsRadius = sparsePixelsRadiusSpinner.get_value_as_int(); +#if LIBDEPIXELIZE_INKSCAPE_ENABLE_SMOOTH + options.optimize = optimizeRadioButton.get_active(); +#else // LIBDEPIXELIZE_INKSCAPE_ENABLE_SMOOTH + options.optimize = false; +#endif // LIBDEPIXELIZE_INKSCAPE_ENABLE_SMOOTH + + options.nthreads = Inkscape::Preferences::get() + ->getIntLimited("/options/threading/numthreads", +#ifdef HAVE_OPENMP + omp_get_num_procs(), +#else + 1, +#endif // HAVE_OPENMP + 1, 256); + + return options; +} + +void PixelArtDialogImpl::vectorize() +{ + Inkscape::MessageStack *msgStack = desktop->messageStack(); + + if ( !desktop->selection ) { + char *msg = _("Select an <b>image</b> to trace"); + msgStack->flash(Inkscape::ERROR_MESSAGE, msg); + return; + } + + bool found = false; + + for ( GSList const *list = desktop->selection->itemList() ; list + ; list = list->next ) { + if ( !SP_IS_IMAGE(list->data) ) + continue; + + found = true; + + processLibdepixelize(SP_IMAGE(list->data)); + } + + if ( !found ) { + char *msg = _("Select an <b>image</b> to trace"); + msgStack->flash(Inkscape::ERROR_MESSAGE, msg); + return; + } + + DocumentUndo::done(desktop->doc(), SP_VERB_SELECTION_PIXEL_ART, + _("Trace pixel art")); + + // Flush pending updates + desktop->doc()->ensureUpToDate(); +} + +void PixelArtDialogImpl::processLibdepixelize(SPImage *img) +{ + Tracer::Splines out; + + Glib::RefPtr<Gdk::Pixbuf> pixbuf + = Glib::wrap(img->pixbuf->getPixbufRaw(), true); + + if ( pixbuf->get_width() > 256 || pixbuf->get_height() > 256 ) { + char *msg = _("Image looks too big. Process may take a while and is" + " wise to save your document before continue." + "\n\nContinue the procedure (without saving)?"); + Gtk::MessageDialog dialog(msg, false, Gtk::MESSAGE_WARNING, + Gtk::BUTTONS_OK_CANCEL, true); + + if ( dialog.run() != Gtk::RESPONSE_OK ) + return; + } + + if ( voronoiRadioButton.get_active() ) { + out = Tracer::Kopf2011::to_voronoi(pixbuf, options()); + } else { + out = Tracer::Kopf2011::to_splines(pixbuf, options()); + } + + Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); + Inkscape::XML::Node *group = xml_doc->createElement("svg:g"); + + for ( Tracer::Splines::iterator it = out.begin(), end = out.end() + ; it != end ; ++it ) { + Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); + + { + SPCSSAttr *css = sp_repr_css_attr_new(); + + { + gchar b[64]; + sp_svg_write_color(b, sizeof(b), + SP_RGBA32_U_COMPOSE(unsigned(it->rgba[0]), + unsigned(it->rgba[1]), + unsigned(it->rgba[2]), + unsigned(it->rgba[3]))); + + sp_repr_css_set_property(css, "fill", b); + } + + { + Inkscape::CSSOStringStream osalpha; + osalpha << float(it->rgba[3]) / 255.; + sp_repr_css_set_property(css, "fill-opacity", + osalpha.str().c_str()); + } + + sp_repr_css_set(repr, css, "style"); + sp_repr_css_attr_unref(css); + } + + gchar *str = sp_svg_write_path(move(it->pathVector)); + repr->setAttribute("d", str); + g_free(str); + + group->appendChild(repr); + + Inkscape::GC::release(repr); + } + + { + group->setAttribute("transform", + (std::string("translate(") + + sp_svg_length_write_with_units(img->x) + + ' ' + sp_svg_length_write_with_units(img->y) + + ')').c_str()); + } + + desktop->currentLayer()->appendChildRepr(group); + + Inkscape::GC::release(group); +} + +void PixelArtDialogImpl::setDefaults() +{ + ignorePreview = true; + + curvesMultiplierSpinner.set_value(Tracer::Kopf2011::Options + ::CURVES_MULTIPLIER); + + islandsWeightSpinner.set_value(Tracer::Kopf2011::Options::ISLANDS_WEIGHT); + + sparsePixelsRadiusSpinner.set_value(Tracer::Kopf2011::Options + ::SPARSE_PIXELS_RADIUS); + + sparsePixelsMultiplierSpinner.set_value(Tracer::Kopf2011::Options + ::SPARSE_PIXELS_MULTIPLIER); + +#if LIBDEPIXELIZE_INKSCAPE_ENABLE_SMOOTH + optimizeRadioButton.set_active(); +#else // LIBDEPIXELIZE_INKSCAPE_ENABLE_SMOOTH + noOptimizeRadioButton.set_active(); +#endif // LIBDEPIXELIZE_INKSCAPE_ENABLE_SMOOTH + + ignorePreview = false; + + if ( pendingPreview ) + updatePreview(); +} + +void PixelArtDialogImpl::updatePreview() +{ + if ( ignorePreview ) { + pendingPreview = true; + return; + } + + // TODO: update preview + pendingPreview = false; +} + +/** + * Factory method. Use this to create a new PixelArtDialog + */ +PixelArtDialog &PixelArtDialog::getInstance() +{ + PixelArtDialog *dialog = new PixelArtDialogImpl(); + return *dialog; +} + +PixelArtDialogImpl::~PixelArtDialogImpl() +{ + desktopChangeConn.disconnect(); +} + + +} //namespace Dialog +} //namespace UI +} //namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/scriptdialog.h b/src/ui/dialog/pixelartdialog.h index d1962bf6f..165cb8699 100644 --- a/src/ui/dialog/scriptdialog.h +++ b/src/ui/dialog/pixelartdialog.h @@ -1,20 +1,17 @@ /** @file - * @brief Script dialog - * - * This dialog is for launching scripts whose main purpose is - * the scripting of Inkscape itself. + * @brief Bitmap tracing settings dialog */ /* Authors: * Bob Jamison + * Vinícius dos Santos Oliveira <vini.ipsmaker@gmail.com> * Other dudes from The Inkscape Organization * * Copyright (C) 2004, 2005 Authors - * * Released under GNU GPL, read the file 'COPYING' for more information */ -#ifndef __SCRIPTDIALOG_H__ -#define __SCRIPTDIALOG_H__ +#ifndef __PIXELARTDIALOG_H__ +#define __PIXELARTDIALOG_H__ #include "ui/widget/panel.h" #include "verbs.h" @@ -25,32 +22,29 @@ namespace Dialog { /** - * A script editor, loader, and executor + * A dialog that displays log messages */ -class ScriptDialog : public UI::Widget::Panel +class PixelArtDialog : public UI::Widget::Panel { - public: - ScriptDialog() : - UI::Widget::Panel("", "/dialogs/script", SP_VERB_DIALOG_SCRIPT) +public: + + PixelArtDialog() : + UI::Widget::Panel("", "/dialogs/pixelart", SP_VERB_SELECTION_PIXEL_ART) {} - /** - * Helper function which returns a new instance of the dialog. - * getInstance is needed by the dialog manager (Inkscape::UI::Dialog::DialogManager). - */ - static ScriptDialog &getInstance(); - virtual ~ScriptDialog() {}; + static PixelArtDialog &getInstance(); -}; // class ScriptDialog + virtual ~PixelArtDialog() {}; +}; } //namespace Dialog } //namespace UI } //namespace Inkscape -#endif /* __DEBUGDIALOG_H__ */ +#endif /* __PIXELARTDIALOGDIALOG_H__ */ /* Local Variables: diff --git a/src/ui/dialog/print.cpp b/src/ui/dialog/print.cpp index 2ab8cf121..03ac9dc64 100644 --- a/src/ui/dialog/print.cpp +++ b/src/ui/dialog/print.cpp @@ -26,7 +26,7 @@ #include "ui/widget/rendering-options.h" #include "document.h" -#include "unit-constants.h" +#include "util/units.h" #include "helper/png-write.h" #include "svg/svg-color.h" #include "io/sys.h" @@ -49,8 +49,8 @@ static void draw_page( if (junk->_tab->as_bitmap()) { // Render as exported PNG - gdouble width = (junk->_doc)->getWidth(); - gdouble height = (junk->_doc)->getHeight(); + gdouble width = (junk->_doc)->getWidth().value("px"); + gdouble height = (junk->_doc)->getHeight().value("px"); gdouble dpi = junk->_tab->bitmap_dpi(); std::string tmp_png; std::string tmp_base = "inkscape-print-png-XXXXXX"; @@ -72,8 +72,8 @@ static void draw_page( sp_export_png_file(junk->_doc, tmp_png.c_str(), 0.0, 0.0, width, height, - (unsigned long)(width * dpi / PX_PER_IN), - (unsigned long)(height * dpi / PX_PER_IN), + (unsigned long)(Inkscape::Util::Quantity::convert(width, "px", "in") * dpi), + (unsigned long)(Inkscape::Util::Quantity::convert(height, "px", "in") * dpi), dpi, dpi, bgcolor, NULL, NULL, true, NULL); // This doesn't seem to work: @@ -90,7 +90,7 @@ static void draw_page( cairo_t *cr = gtk_print_context_get_cairo_context (context); cairo_matrix_t m; cairo_get_matrix(cr, &m); - cairo_scale(cr, PT_PER_IN / dpi, PT_PER_IN / dpi); + cairo_scale(cr, Inkscape::Util::Quantity::convert(1, "in", "pt") / dpi, Inkscape::Util::Quantity::convert(1, "in", "pt") / dpi); // FIXME: why is the origin offset?? cairo_set_source_surface(cr, png->cobj(), -16.0, -16.0); cairo_paint(cr); @@ -101,7 +101,7 @@ static void draw_page( unlink (tmp_png.c_str()); } else { - g_warning(_("Could not open temporary PNG for bitmap printing")); + g_warning("%s", _("Could not open temporary PNG for bitmap printing")); } } else { @@ -144,11 +144,11 @@ static void draw_page( ret = ctx->finish(); } else { - g_warning(_("Could not set up Document")); + g_warning("%s", _("Could not set up Document")); } } else { - g_warning(_("Failed to set CairoRenderContext")); + g_warning("%s", _("Failed to set CairoRenderContext")); } // Clean up @@ -195,8 +195,8 @@ Print::Print(SPDocument *doc, SPItem *base) : // set up paper size to match the document size gtk_print_operation_set_unit (_printop, GTK_UNIT_POINTS); GtkPageSetup *page_setup = gtk_page_setup_new(); - gdouble doc_width = _doc->getWidth() * PT_PER_PX; - gdouble doc_height = _doc->getHeight() * PT_PER_PX; + gdouble doc_width = _doc->getWidth().value("pt"); + gdouble doc_height = _doc->getHeight().value("pt"); GtkPaperSize *paper_size; if (doc_width > doc_height) { gtk_page_setup_set_orientation (page_setup, GTK_PAGE_ORIENTATION_LANDSCAPE); diff --git a/src/ui/dialog/scriptdialog.cpp b/src/ui/dialog/scriptdialog.cpp deleted file mode 100644 index 87794a3ce..000000000 --- a/src/ui/dialog/scriptdialog.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/** - * @file - * Dialog for executing and monitoring script execution. - */ -/* Author: - * Bob Jamison - * - * Copyright (C) 2004-2008 Authors - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include "scriptdialog.h" -#include <glibmm/i18n.h> -#include <gtkmm/menubar.h> -#include <gtkmm/frame.h> -#include <gtkmm/scrolledwindow.h> -#include <gtkmm/textview.h> - -#include <extension/script/InkscapeScript.h> - - - -namespace Inkscape -{ -namespace UI -{ -namespace Dialog -{ - - - -//######################################################################### -//## I M P L E M E N T A T I O N -//######################################################################### - -/** - * A script editor/executor - */ -class ScriptDialogImpl : public ScriptDialog -{ - - public: - ScriptDialogImpl(); - ~ScriptDialogImpl() - {} - - - /** - * Remove all text from the dialog. - */ - void clear(); - - /** - * Execute a script in the dialog. - * - * @param lang language in which the script is programmed - */ - void execute(Inkscape::Extension::Script::InkscapeScript::ScriptLanguage lang); - - /** - * Execute a Javascript script - */ - void executeJavascript(); - - /** - * Execute a Python script - */ - void executePython(); - - /** - * Execute a Ruby script - */ - void executeRuby(); - - - - private: - Gtk::MenuBar menuBar; - Gtk::Menu fileMenu; - - //## Script text - Gtk::Frame scriptTextFrame; - Gtk::ScrolledWindow scriptTextScroll; - Gtk::TextView scriptText; - - //## Output text - Gtk::Frame outputTextFrame; - Gtk::ScrolledWindow outputTextScroll; - Gtk::TextView outputText; - - //## Error text - Gtk::Frame errorTextFrame; - Gtk::ScrolledWindow errorTextScroll; - Gtk::TextView errorText; - - - -}; - -static const char *defaultCodeStr = - "/**\n" - " * This is some example Javascript.\n" - " * Try 'Execute Javascript'\n" - " */\n" - "importPackage(javax.swing);\n" - "function sayHello() {\n" - " JOptionPane.showMessageDialog(null, 'Hello, world!',\n" - " 'Welcome to Inkscape', JOptionPane.WARNING_MESSAGE);\n" - "}\n" - "\n" - "sayHello();\n" - "\n"; - - - - -//######################################################################### -//## E V E N T S -//######################################################################### - -static void textViewClear(Gtk::TextView &view) -{ - Glib::RefPtr<Gtk::TextBuffer> buffer = view.get_buffer(); - buffer->erase(buffer->begin(), buffer->end()); -} - -void ScriptDialogImpl::clear() -{ - textViewClear(scriptText); - textViewClear(outputText); - textViewClear(errorText); -} - -void ScriptDialogImpl::execute(Inkscape::Extension::Script::InkscapeScript::ScriptLanguage lang) -{ - Glib::ustring script = scriptText.get_buffer()->get_text(true); - Glib::ustring output; - Glib::ustring error; - Inkscape::Extension::Script::InkscapeScript engine; - bool ok = engine.interpretScript(script, output, error, lang); - outputText.get_buffer()->set_text(output); - errorText.get_buffer()->set_text(error); - if (!ok) - { - //do we want something here? - } -} - -void ScriptDialogImpl::executeJavascript() -{ - execute(Inkscape::Extension::Script::InkscapeScript::JAVASCRIPT); -} - -void ScriptDialogImpl::executePython() -{ - execute(Inkscape::Extension::Script::InkscapeScript::PYTHON); -} - -void ScriptDialogImpl::executeRuby() -{ - execute(Inkscape::Extension::Script::InkscapeScript::RUBY); -} - - -//######################################################################### -//## C O N S T R U C T O R / D E S T R U C T O R -//######################################################################### -ScriptDialogImpl::ScriptDialogImpl() : - ScriptDialog() -{ - Gtk::Box *contents = _getContents(); - - //## Add a menu for clear() - Gtk::MenuItem* item = Gtk::manage(new Gtk::MenuItem(_("File"), true)); - item->set_submenu(fileMenu); - menuBar.append(*item); - - item = Gtk::manage(new Gtk::MenuItem(_("_Clear"), true)); - item->signal_activate().connect(sigc::mem_fun(*this, &ScriptDialogImpl::clear)); - fileMenu.append(*item); - - item = Gtk::manage(new Gtk::MenuItem(_("_Execute Javascript"), true)); - item->signal_activate().connect(sigc::mem_fun(*this, &ScriptDialogImpl::executeJavascript)); - fileMenu.append(*item); - - item = Gtk::manage(new Gtk::MenuItem(_("_Execute Python"), true)); - item->signal_activate().connect(sigc::mem_fun(*this, &ScriptDialogImpl::executePython)); - fileMenu.append(*item); - - item = Gtk::manage(new Gtk::MenuItem(_("_Execute Ruby"), true)); - item->signal_activate().connect(sigc::mem_fun(*this, &ScriptDialogImpl::executeRuby)); - fileMenu.append(*item); - - contents->pack_start(menuBar, Gtk::PACK_SHRINK); - - //### Set up the script field - scriptText.set_editable(true); - scriptText.get_buffer()->set_text(defaultCodeStr); - scriptTextScroll.add(scriptText); - scriptTextScroll.set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS); - scriptTextFrame.set_label(_("Script")); - scriptTextFrame.set_shadow_type(Gtk::SHADOW_NONE); - scriptTextFrame.add(scriptTextScroll); - contents->pack_start(scriptTextFrame); - - //### Set up the output field - outputText.set_editable(true); - outputText.get_buffer()->set_text(""); - outputTextScroll.add(outputText); - outputTextScroll.set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS); - outputTextFrame.set_label(_("Output")); - outputTextFrame.set_shadow_type(Gtk::SHADOW_NONE); - outputTextFrame.add(outputTextScroll); - contents->pack_start(outputTextFrame); - - //### Set up the error field - errorText.set_editable(true); - errorText.get_buffer()->set_text(""); - errorTextScroll.add(errorText); - errorTextScroll.set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS); - errorTextFrame.set_label(_("Errors")); - errorTextFrame.set_shadow_type(Gtk::SHADOW_NONE); - errorTextFrame.add(errorTextScroll); - contents->pack_start(errorTextFrame); - - // sick of this thing shrinking too much - set_size_request(350, 400); - show_all_children(); - -} - -ScriptDialog &ScriptDialog::getInstance() -{ - ScriptDialog *dialog = new ScriptDialogImpl(); - return *dialog; -} - -} //namespace Dialogs -} //namespace UI -} //namespace Inkscape - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/spellcheck.cpp b/src/ui/dialog/spellcheck.cpp index 9cc18c02c..45106755c 100644 --- a/src/ui/dialog/spellcheck.cpp +++ b/src/ui/dialog/spellcheck.cpp @@ -459,7 +459,7 @@ SpellCheck::finished () if (_stops) label = g_strdup_printf(_("<b>Finished</b>, <b>%d</b> words added to dictionary"), _adds); else - label = g_strdup_printf(_("<b>Finished</b>, nothing suspicious found")); + label = g_strdup_printf("%s", _("<b>Finished</b>, nothing suspicious found")); banner_label.set_markup(label); g_free(label); } diff --git a/src/ui/dialog/svg-fonts-dialog.cpp b/src/ui/dialog/svg-fonts-dialog.cpp index ab5f4c0e9..56ecfdecc 100644 --- a/src/ui/dialog/svg-fonts-dialog.cpp +++ b/src/ui/dialog/svg-fonts-dialog.cpp @@ -541,7 +541,9 @@ void SvgFontsDialog::set_glyph_description_from_selected_path(){ Geom::PathVector pathv = sp_svg_read_pathv(node->attribute("d")); //XML Tree being directly used here while it shouldn't be. - glyph->getRepr()->setAttribute("d", (char*) sp_svg_write_path (flip_coordinate_system(pathv))); + gchar *str = sp_svg_write_path (flip_coordinate_system(pathv)); + glyph->getRepr()->setAttribute("d", str); + g_free(str); DocumentUndo::done(doc, SP_VERB_DIALOG_SVG_FONTS, _("Set glyph curves")); update_glyphs(); @@ -578,7 +580,9 @@ void SvgFontsDialog::missing_glyph_description_from_selected_path(){ if (SP_IS_MISSING_GLYPH(obj)){ //XML Tree being directly used here while it shouldn't be. - obj->getRepr()->setAttribute("d", (char*) sp_svg_write_path (flip_coordinate_system(pathv))); + gchar *str = sp_svg_write_path (flip_coordinate_system(pathv)); + obj->getRepr()->setAttribute("d", str); + g_free(str); DocumentUndo::done(doc, SP_VERB_DIALOG_SVG_FONTS, _("Set glyph curves")); } } diff --git a/src/ui/dialog/svg-fonts-dialog.h b/src/ui/dialog/svg-fonts-dialog.h index 01f70654a..e5c4631e4 100644 --- a/src/ui/dialog/svg-fonts-dialog.h +++ b/src/ui/dialog/svg-fonts-dialog.h @@ -34,8 +34,8 @@ class HScale; #endif } -struct SPGlyph; -struct SPGlyphKerning; +class SPGlyph; +class SPGlyphKerning; class SvgFont; class SvgFontDrawingArea : Gtk::DrawingArea{ @@ -52,7 +52,7 @@ private: bool on_expose_event (GdkEventExpose *event); }; -struct SPFont; +class SPFont; namespace Inkscape { namespace UI { diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 094a6fa6a..d4d80c9b1 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -42,7 +42,6 @@ #include "path-prefix.h" #include "preferences.h" #include "sp-item.h" -#include "sp-gradient-fns.h" #include "sp-gradient.h" #include "sp-gradient-vector.h" #include "style.h" diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp index 26bc52947..6427eb9cc 100644 --- a/src/ui/dialog/symbols.cpp +++ b/src/ui/dialog/symbols.cpp @@ -420,12 +420,12 @@ void SymbolsDialog::iconChanged() { // First look for default style stored in <symbol> gchar const* style = symbol->getAttribute("inkscape:symbol-style"); if( !style ) { - // If no default style in <symbol>, look in documents. - if( symbolDocument == currentDocument ) { - style = style_from_use( symbol_id.c_str(), currentDocument ); - } else { - style = symbolDocument->getReprRoot()->attribute("style"); - } + // If no default style in <symbol>, look in documents. + if( symbolDocument == currentDocument ) { + style = style_from_use( symbol_id.c_str(), currentDocument ); + } else { + style = symbolDocument->getReprRoot()->attribute("style"); + } } ClipboardManager *cm = ClipboardManager::get(); @@ -489,8 +489,8 @@ SPDocument* read_vss( gchar* fullname, gchar* filename ) { while( std::getline( iss, line ) ) { // std::cout << line << std::endl; if( line.find( "svg:svg" ) == std::string::npos ) { - tmpSVGOutput += line; - tmpSVGOutput += "\n"; + tmpSVGOutput += line; + tmpSVGOutput += "\n"; } } @@ -499,23 +499,23 @@ SPDocument* read_vss( gchar* fullname, gchar* filename ) { tmpSVGOutput += " </defs>\n"; tmpSVGOutput += "</svg>\n"; - + return SPDocument::createNewDocFromMem( tmpSVGOutput.c_str(), strlen( tmpSVGOutput.c_str()), 0 ); } #endif - + /* Hunts preference directories for symbol files */ void SymbolsDialog::get_symbols() { std::list<Glib::ustring> directories; if( Inkscape::IO::file_test( INKSCAPE_SYMBOLSDIR, G_FILE_TEST_EXISTS ) && - Inkscape::IO::file_test( INKSCAPE_SYMBOLSDIR, G_FILE_TEST_IS_DIR ) ) { + Inkscape::IO::file_test( INKSCAPE_SYMBOLSDIR, G_FILE_TEST_IS_DIR ) ) { directories.push_back( INKSCAPE_SYMBOLSDIR ); } if( Inkscape::IO::file_test( profile_path("symbols"), G_FILE_TEST_EXISTS ) && - Inkscape::IO::file_test( profile_path("symbols"), G_FILE_TEST_IS_DIR ) ) { + Inkscape::IO::file_test( profile_path("symbols"), G_FILE_TEST_IS_DIR ) ) { directories.push_back( profile_path("symbols") ); } @@ -526,46 +526,46 @@ void SymbolsDialog::get_symbols() { GDir *dir = g_dir_open( (*it).c_str(), 0, &err ); if( dir ) { - gchar *filename = 0; - while( (filename = (gchar *)g_dir_read_name( dir ) ) != NULL) { + gchar *filename = 0; + while( (filename = (gchar *)g_dir_read_name( dir ) ) != NULL) { - gchar *fullname = g_build_filename((*it).c_str(), filename, NULL); + gchar *fullname = g_build_filename((*it).c_str(), filename, NULL); - if ( !Inkscape::IO::file_test( fullname, G_FILE_TEST_IS_DIR ) ) { + if ( !Inkscape::IO::file_test( fullname, G_FILE_TEST_IS_DIR ) ) { - Glib::ustring fn( filename ); - Glib::ustring tag = fn.substr( fn.find_last_of(".") + 1 ); + Glib::ustring fn( filename ); + Glib::ustring tag = fn.substr( fn.find_last_of(".") + 1 ); - SPDocument* symbol_doc = NULL; + SPDocument* symbol_doc = NULL; #ifdef WITH_LIBVISIO - if( tag.compare( "vss" ) == 0 ) { - - symbol_doc = read_vss( fullname, filename ); - if( symbol_doc ) { - symbolSets[Glib::ustring(filename)]= symbol_doc; - symbolSet->append(filename); - } - } + if( tag.compare( "vss" ) == 0 ) { + + symbol_doc = read_vss( fullname, filename ); + if( symbol_doc ) { + symbolSets[Glib::ustring(filename)]= symbol_doc; + symbolSet->append(filename); + } + } #endif - // Try to read all remaining files as SVG - if( !symbol_doc ) { + // Try to read all remaining files as SVG + if( !symbol_doc ) { - symbol_doc = SPDocument::createNewDoc( fullname, FALSE ); - if( symbol_doc ) { + symbol_doc = SPDocument::createNewDoc( fullname, FALSE ); + if( symbol_doc ) { gchar *title = symbol_doc->getRoot()->title(); if( title == NULL ) { title = _("Unnamed Symbols"); } - symbolSets[Glib::ustring(title)] = symbol_doc; - symbolSet->append(title); - } - } - - } - g_free( fullname ); - } - g_dir_close( dir ); + symbolSets[Glib::ustring(title)] = symbol_doc; + symbolSet->append(title); + } + } + + } + g_free( fullname ); + } + g_dir_close( dir ); } } } @@ -627,16 +627,16 @@ gchar const* SymbolsDialog::style_from_use( gchar const* id, SPDocument* documen for( ; l != NULL; l = l->next ) { SPObject* use = SP_OBJECT(l->data); if( SP_IS_USE( use ) ) { - gchar const *href = use->getRepr()->attribute("xlink:href"); - if( href ) { - Glib::ustring href2(href); - Glib::ustring id2(id); - id2 = "#" + id2; - if( !href2.compare(id2) ) { - style = use->getRepr()->attribute("style"); - break; - } - } + gchar const *href = use->getRepr()->attribute("xlink:href"); + if( href ) { + Glib::ustring href2(href); + Glib::ustring id2(id); + id2 = "#" + id2; + if( !href2.compare(id2) ) { + style = use->getRepr()->attribute("style"); + break; + } + } } } return style; @@ -749,9 +749,13 @@ SymbolsDialog::create_symbol_image(gchar const *symbol_id, SPObject *symbol) /* Update to renderable state */ Glib::ustring key = svg_preview_cache.cache_key(previewDocument->getURI(), symbol_id, psize); //std::cout << " Key: " << key << std::endl; - // FIX ME - //Glib::RefPtr<Gdk::Pixbuf> pixbuf = Glib::wrap(svg_preview_cache.get_preview_from_cache(key)); - Glib::RefPtr<Gdk::Pixbuf> pixbuf = Glib::RefPtr<Gdk::Pixbuf>(0); + + Glib::RefPtr<Gdk::Pixbuf> pixbuf(NULL); + GdkPixbuf *pixbuf_gobj = svg_preview_cache.get_preview_from_cache(key); + if (pixbuf_gobj) { + g_object_ref(pixbuf_gobj); // the reference in svg_preview_cache will get destroyed when it's freed + pixbuf = Glib::wrap(pixbuf_gobj); + } // Find object's bbox in document. // Note symbols can have own viewport... ignore for now. @@ -776,8 +780,8 @@ SymbolsDialog::create_symbol_image(gchar const *symbol_id, SPObject *symbol) } if( fitSymbol->get_active() ) { - /* Fit */ - scale = psize/std::max(width,height); + /* Fit */ + scale = psize/std::max(width,height); } pixbuf = Glib::wrap(render_pixbuf(renderDrawing, scale, *dbox, psize)); @@ -814,8 +818,8 @@ void SymbolsDialog::setTargetDesktop(SPDesktop *desktop) if (this->currentDesktop != desktop) { this->currentDesktop = desktop; if( !symbolSets[symbolSet->get_active_text()] ) { - // Symbol set is from Current document, update - rebuild(); + // Symbol set is from Current document, update + rebuild(); } } } diff --git a/src/ui/dialog/template-load-tab.cpp b/src/ui/dialog/template-load-tab.cpp new file mode 100644 index 000000000..8e33cf503 --- /dev/null +++ b/src/ui/dialog/template-load-tab.cpp @@ -0,0 +1,318 @@ +/** @file + * @brief New From Template abstract tab implementation + */ +/* Authors: + * Jan Darowski <jan.darowski@gmail.com>, supervised by Krzysztof Kosiński + * + * Copyright (C) 2013 Authors + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "template-widget.h" + +#include "template-load-tab.h" + +#include <gtkmm/messagedialog.h> +#include <gtkmm/scrolledwindow.h> +#include <glibmm/i18n.h> +#include <glibmm/fileutils.h> +#include <glibmm/miscutils.h> +#include <glibmm/stringutils.h> +#include <iostream> +#include <list> + +#include "extension/db.h" +#include "extension/effect.h" +#include "inkscape.h" +#include "interface.h" +#include "file.h" +#include "path-prefix.h" +#include "preferences.h" +#include "xml/repr.h" +#include "xml/document.h" +#include "xml/node.h" + + +namespace Inkscape { +namespace UI { + + +TemplateLoadTab::TemplateLoadTab() + : _current_keyword("") + , _keywords_combo(true) + , _current_search_type(ALL) +{ + set_border_width(10); + + _info_widget = manage(new TemplateWidget()); + + Gtk::Label *title; + title = manage(new Gtk::Label(_("Search:"))); + _search_box.pack_start(*title, Gtk::PACK_SHRINK); + _search_box.pack_start(_keywords_combo, Gtk::PACK_SHRINK, 5); + + _tlist_box.pack_start(_search_box, Gtk::PACK_SHRINK, 10); + + pack_start(_tlist_box, Gtk::PACK_SHRINK); + pack_start(*_info_widget, Gtk::PACK_EXPAND_WIDGET, 5); + + Gtk::ScrolledWindow *scrolled; + scrolled = manage(new Gtk::ScrolledWindow()); + scrolled->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); + scrolled->add(_tlist_view); + _tlist_box.pack_start(*scrolled, Gtk::PACK_EXPAND_WIDGET, 5); + + _keywords_combo.signal_changed().connect( + sigc::mem_fun(*this, &TemplateLoadTab::_keywordSelected)); + this->show_all(); + + _loading_path = ""; + _loadTemplates(); + _initLists(); +} + + +TemplateLoadTab::~TemplateLoadTab() +{ +} + + +void TemplateLoadTab::createTemplate() +{ + _info_widget->create(); +} + + +void TemplateLoadTab::_displayTemplateInfo() +{ + Glib::RefPtr<Gtk::TreeSelection> templateSelectionRef = _tlist_view.get_selection(); + if (templateSelectionRef->get_selected()) { + _current_template = (*templateSelectionRef->get_selected())[_columns.textValue]; + + _info_widget->display(_tdata[_current_template]); + } + +} + + +void TemplateLoadTab::_initKeywordsList() +{ + _keywords_combo.append(_("All")); + + for (std::set<Glib::ustring>::iterator it = _keywords.begin() ; it != _keywords.end() ; ++it){ + _keywords_combo.append(*it); + } +} + + +void TemplateLoadTab::_initLists() +{ + _tlist_store = Gtk::ListStore::create(_columns); + _tlist_view.set_model(_tlist_store); + _tlist_view.append_column("", _columns.textValue); + _tlist_view.set_headers_visible(false); + + _initKeywordsList(); + _refreshTemplatesList(); + + Glib::RefPtr<Gtk::TreeSelection> templateSelectionRef = + _tlist_view.get_selection(); + templateSelectionRef->signal_changed().connect( + sigc::mem_fun(*this, &TemplateLoadTab::_displayTemplateInfo)); +} + + +void TemplateLoadTab::_keywordSelected() +{ + _current_keyword = _keywords_combo.get_active_text(); + if (_current_keyword == ""){ + _current_keyword = _keywords_combo.get_entry_text(); + _current_search_type = USER_SPECIFIED; + } + else + _current_search_type = LIST_KEYWORD; + + if (_current_keyword == "" || _current_keyword == _("All")) + _current_search_type = ALL; + + _refreshTemplatesList(); +} + + +void TemplateLoadTab::_refreshTemplatesList() +{ + _tlist_store->clear(); + + switch (_current_search_type){ + case ALL :{ + + for (std::map<Glib::ustring, TemplateData>::iterator it = _tdata.begin() ; it != _tdata.end() ; ++it) { + Gtk::TreeModel::iterator iter = _tlist_store->append(); + Gtk::TreeModel::Row row = *iter; + row[_columns.textValue] = it->first; + } + break; + } + + case LIST_KEYWORD: { + for (std::map<Glib::ustring, TemplateData>::iterator it = _tdata.begin() ; it != _tdata.end() ; ++it) { + if (it->second.keywords.count(_current_keyword.lowercase()) != 0){ + Gtk::TreeModel::iterator iter = _tlist_store->append(); + Gtk::TreeModel::Row row = *iter; + row[_columns.textValue] = it->first; + } + } + break; + } + + case USER_SPECIFIED : { + for (std::map<Glib::ustring, TemplateData>::iterator it = _tdata.begin() ; it != _tdata.end() ; ++it) { + if (it->second.keywords.count(_current_keyword.lowercase()) != 0 || + it->second.display_name.lowercase().find(_current_keyword.lowercase()) != Glib::ustring::npos || + it->second.author.lowercase().find(_current_keyword.lowercase()) != Glib::ustring::npos || + it->second.short_description.lowercase().find(_current_keyword.lowercase()) != Glib::ustring::npos || + it->second.long_description.lowercase().find(_current_keyword.lowercase()) != Glib::ustring::npos ) + { + Gtk::TreeModel::iterator iter = _tlist_store->append(); + Gtk::TreeModel::Row row = *iter; + row[_columns.textValue] = it->first; + } + } + break; + } + } +} + + +void TemplateLoadTab::_loadTemplates() +{ + // user's local dir + _getTemplatesFromDir(profile_path("templates") + _loading_path); + + // system templates dir + _getTemplatesFromDir(INKSCAPE_TEMPLATESDIR + _loading_path); + + // procedural templates + _getProceduralTemplates(); +} + + +TemplateLoadTab::TemplateData TemplateLoadTab::_processTemplateFile(const std::string &path) +{ + TemplateData result; + result.path = path; + result.is_procedural = false; + result.preview_name = ""; + + // convert path into valid template name + result.display_name = Glib::path_get_basename(path); + gsize n = 0; + while ((n = result.display_name.find_first_of("_", 0)) < Glib::ustring::npos){ + result.display_name.replace(n, 1, 1, ' '); + } + n = result.display_name.rfind(".svg"); + result.display_name.replace(n, 4, 1, ' '); + + Inkscape::XML::Document *rdoc; + rdoc = sp_repr_read_file(path.data(), SP_SVG_NS_URI); + Inkscape::XML::Node *myRoot; + + if (rdoc){ + myRoot = rdoc->root(); + if (strcmp(myRoot->name(), "svg:svg") != 0){ // Wrong file format + return result; + } + + myRoot = sp_repr_lookup_name(myRoot, "inkscape:_templateinfo"); + + if (myRoot == NULL) // No template info + return result; + _getDataFromNode(myRoot, result); + } + + return result; +} + + +void TemplateLoadTab::_getTemplatesFromDir(const std::string &path) +{ + if ( !Glib::file_test(path, Glib::FILE_TEST_EXISTS) || + !Glib::file_test(path, Glib::FILE_TEST_IS_DIR)) + return; + + Glib::Dir dir(path); + + std::string file = Glib::build_filename(path, dir.read_name()); + while (file != path){ + if (Glib::str_has_suffix(file, ".svg") && !Glib::str_has_prefix(Glib::path_get_basename(file), "default.")){ + TemplateData tmp = _processTemplateFile(file); + if (tmp.display_name != "") + _tdata[tmp.display_name] = tmp; + } + file = Glib::build_filename(path, dir.read_name()); + } +} + + +void TemplateLoadTab::_getProceduralTemplates() +{ + std::list<Inkscape::Extension::Effect *> effects; + Inkscape::Extension::db.get_effect_list(effects); + + std::list<Inkscape::Extension::Effect *>::iterator it = effects.begin(); + while (it != effects.end()){ + Inkscape::XML::Node *myRoot; + myRoot = (*it)->get_repr(); + myRoot = sp_repr_lookup_name(myRoot, "inkscape:_templateinfo"); + + if (myRoot){ + TemplateData result; + result.display_name = (*it)->get_name(); + result.is_procedural = true; + result.path = ""; + result.tpl_effect = *it; + + _getDataFromNode(myRoot, result); + _tdata[result.display_name] = result; + } + ++it; + } +} + + +void TemplateLoadTab::_getDataFromNode(Inkscape::XML::Node *dataNode, TemplateData &data) +{ + Inkscape::XML::Node *currentData; + if ((currentData = sp_repr_lookup_name(dataNode, "inkscape:_name")) != NULL) + data.display_name = dgettext("Document template name", currentData->firstChild()->content()); + if ((currentData = sp_repr_lookup_name(dataNode, "inkscape:author")) != NULL) + data.author = currentData->firstChild()->content(); + if ((currentData = sp_repr_lookup_name(dataNode, "inkscape:_shortdesc")) != NULL) + data.short_description = dgettext("Document template short description", currentData->firstChild()->content()); + if ((currentData = sp_repr_lookup_name(dataNode, "inkscape:_long") )!= NULL) + data.long_description = dgettext("Document template long description", currentData->firstChild()->content()); + if ((currentData = sp_repr_lookup_name(dataNode, "inkscape:preview")) != NULL) + data.preview_name = currentData->firstChild()->content(); + if ((currentData = sp_repr_lookup_name(dataNode, "inkscape:date")) != NULL) + data.creation_date = currentData->firstChild()->content(); + + if ((currentData = sp_repr_lookup_name(dataNode, "inkscape:_keywords")) != NULL){ + Glib::ustring tplKeywords = currentData->firstChild()->content(); + while (!tplKeywords.empty()){ + std::size_t pos = tplKeywords.find_first_of(" "); + if (pos == Glib::ustring::npos) + pos = tplKeywords.size(); + + Glib::ustring keyword = dgettext("Document template keyword", tplKeywords.substr(0, pos).data()); + data.keywords.insert(keyword.lowercase()); + _keywords.insert(keyword.lowercase()); + + if (pos == tplKeywords.size()) + break; + tplKeywords.erase(0, pos+1); + } + } +} + +} +} diff --git a/src/ui/dialog/template-load-tab.h b/src/ui/dialog/template-load-tab.h new file mode 100644 index 000000000..744a2a9fb --- /dev/null +++ b/src/ui/dialog/template-load-tab.h @@ -0,0 +1,109 @@ +/** @file + * @brief New From Template abstract tab class + */ +/* Authors: + * Jan Darowski <jan.darowski@gmail.com>, supervised by Krzysztof Kosiński + * + * Copyright (C) 2013 Authors + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef INKSCAPE_SEEN_UI_DIALOG_TEMPLATE_LOAD_TAB_H +#define INKSCAPE_SEEN_UI_DIALOG_TEMPLATE_LOAD_TAB_H + +#include <gtkmm/box.h> +#include <gtkmm/comboboxtext.h> +#include <gtkmm/frame.h> +#include <gtkmm/liststore.h> +#include <gtkmm/treeview.h> +#include <map> +#include <set> +#include <string> + +#include "xml/node.h" +#include "extension/effect.h" + + +namespace Inkscape { +namespace UI { + +class TemplateWidget; + +class TemplateLoadTab : public Gtk::HBox +{ + +public: + struct TemplateData + { + bool is_procedural; + std::string path; + Glib::ustring display_name; + Glib::ustring author; + Glib::ustring short_description; + Glib::ustring long_description; + Glib::ustring preview_name; + Glib::ustring creation_date; + std::set<Glib::ustring> keywords; + Inkscape::Extension::Effect *tpl_effect; + }; + + TemplateLoadTab(); + virtual ~TemplateLoadTab(); + virtual void createTemplate(); + +protected: + class StringModelColumns : public Gtk::TreeModelColumnRecord + { + public: + StringModelColumns() + { + add(textValue); + } + + Gtk::TreeModelColumn<Glib::ustring> textValue; + }; + + Glib::ustring _current_keyword; + Glib::ustring _current_template; + std::string _loading_path; + std::map<Glib::ustring, TemplateData> _tdata; + std::set<Glib::ustring> _keywords; + + + virtual void _displayTemplateInfo(); + virtual void _initKeywordsList(); + virtual void _refreshTemplatesList(); + void _loadTemplates(); + void _initLists(); + + Gtk::VBox _tlist_box; + Gtk::HBox _search_box; + TemplateWidget *_info_widget; + + Gtk::ComboBoxText _keywords_combo; + + Gtk::TreeView _tlist_view; + Glib::RefPtr<Gtk::ListStore> _tlist_store; + StringModelColumns _columns; + +private: + enum SearchType + { + LIST_KEYWORD, + USER_SPECIFIED, + ALL + }; + + SearchType _current_search_type; + + void _getDataFromNode(Inkscape::XML::Node *, TemplateData &); + void _getProceduralTemplates(); + void _getTemplatesFromDir(const std::string &); + void _keywordSelected(); + TemplateData _processTemplateFile(const std::string &); +}; + +} +} + +#endif diff --git a/src/ui/dialog/template-widget.cpp b/src/ui/dialog/template-widget.cpp new file mode 100644 index 000000000..898903f2b --- /dev/null +++ b/src/ui/dialog/template-widget.cpp @@ -0,0 +1,138 @@ +/** @file + * @brief New From Template - templates widget - implementation + */ +/* Authors: + * Jan Darowski <jan.darowski@gmail.com>, supervised by Krzysztof Kosiński + * + * Copyright (C) 2013 Authors + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "template-widget.h" + +#include <gtkmm/alignment.h> +#include <gtkmm/button.h> +#include <gtkmm/label.h> +#include <gtkmm/messagedialog.h> + +#include <glibmm/i18n.h> +#include <glibmm/miscutils.h> + +#include "template-load-tab.h" +#include "desktop.h" +#include "desktop-handles.h" +#include "document.h" +#include "document-undo.h" +#include "file.h" +#include "extension/implementation/implementation.h" +#include "inkscape.h" + + +namespace Inkscape { +namespace UI { + + +TemplateWidget::TemplateWidget() + : _more_info_button(_("More info")) + , _short_description_label(_(" ")) + , _template_name_label(_("no template selected")) + , _effect_prefs(NULL) +{ + pack_start(_template_name_label, Gtk::PACK_SHRINK, 10); + pack_start(_preview_box, Gtk::PACK_SHRINK, 0); + + _preview_box.pack_start(_preview_image, Gtk::PACK_EXPAND_PADDING, 15); + _preview_box.pack_start(_preview_render, Gtk::PACK_EXPAND_PADDING, 10); + + _short_description_label.set_line_wrap(true); + + Gtk::Alignment *align; + align = manage(new Gtk::Alignment(Gtk::ALIGN_END, Gtk::ALIGN_CENTER, 0.0, 0.0)); + pack_end(*align, Gtk::PACK_SHRINK); + align->add(_more_info_button); + + pack_end(_short_description_label, Gtk::PACK_SHRINK, 5); + + _more_info_button.signal_pressed().connect( + sigc::mem_fun(*this, &TemplateWidget::_displayTemplateDetails)); +} + + +void TemplateWidget::create() +{ + if (_current_template.display_name == "") + return; + + if (_current_template.is_procedural){ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + SPDesktop *desc = sp_file_new_default(); + _current_template.tpl_effect->effect(desc); + DocumentUndo::clearUndo(sp_desktop_document(desc)); + sp_desktop_document(desc)->setModifiedSinceSave(false); + + if (desktop) + desktop->clearWaitingCursor(); + } + else { + sp_file_new(_current_template.path); + } +} + + +void TemplateWidget::display(TemplateLoadTab::TemplateData data) +{ + _current_template = data; + + _template_name_label.set_text(_current_template.display_name); + _short_description_label.set_text(_current_template.short_description); + + _preview_render.hide(); + _preview_image.hide(); + + std::string imagePath = Glib::build_filename(Glib::path_get_dirname(_current_template.path), _current_template.preview_name); + if (data.preview_name != ""){ + _preview_image.set(imagePath); + _preview_image.show(); + } + else if (!data.is_procedural){ + Glib::ustring gPath = data.path.c_str(); + _preview_render.showImage(gPath); + _preview_render.show(); + } + + if (_effect_prefs != NULL){ + remove (*_effect_prefs); + _effect_prefs = NULL; + } + if (data.is_procedural){ + _effect_prefs = data.tpl_effect->get_imp()->prefs_effect(data.tpl_effect, SP_ACTIVE_DESKTOP, NULL, NULL); + pack_start(*_effect_prefs); + } +} + + +void TemplateWidget::_displayTemplateDetails() +{ + Glib::ustring message = _current_template.display_name + "\n\n"; + + if (_current_template.path != "") + message += _("Path: ") + _current_template.path + "\n\n"; + + if (_current_template.long_description != "") + message += _("Description: ") + _current_template.long_description + "\n\n"; + if (~_current_template.keywords.empty()){ + message += _("Keywords: "); + for (std::set<Glib::ustring>::iterator it = _current_template.keywords.begin(); it != _current_template.keywords.end(); ++it) + message += *it + " "; + message += "\n\n"; + } + + if (_current_template.author != "") + message += _("By: ") + _current_template.author + " " + _current_template.creation_date + "\n\n"; + + Gtk::MessageDialog dl(message, false, Gtk::MESSAGE_OTHER); + dl.run(); +} + +} +} diff --git a/src/ui/dialog/template-widget.h b/src/ui/dialog/template-widget.h new file mode 100644 index 000000000..bb35d26a0 --- /dev/null +++ b/src/ui/dialog/template-widget.h @@ -0,0 +1,49 @@ +/** @file + * @brief New From Template - template widget + */ +/* Authors: + * Jan Darowski <jan.darowski@gmail.com>, supervised by Krzysztof Kosiński + * + * Copyright (C) 2013 Authors + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef INKSCAPE_SEEN_UI_DIALOG_TEMPLATE_WIDGET_H +#define INKSCAPE_SEEN_UI_DIALOG_TEMPLATE_WIDGET_H + +#include "filedialogimpl-gtkmm.h" + +#include <gtkmm/box.h> + +#include "template-load-tab.h" + + +namespace Inkscape { +namespace UI { + + +class TemplateWidget : public Gtk::VBox +{ +public: + TemplateWidget (); + void create(); + void display(TemplateLoadTab::TemplateData); + +private: + TemplateLoadTab::TemplateData _current_template; + + Gtk::Button _more_info_button; + Gtk::HBox _preview_box; + Gtk::Image _preview_image; + Dialog::SVGPreview _preview_render; + Gtk::Label _short_description_label; + Gtk::Label _template_name_label; + Gtk::Widget *_effect_prefs; + + void _displayTemplateDetails(); +}; + +} +} + +#endif diff --git a/src/ui/dialog/text-edit.cpp b/src/ui/dialog/text-edit.cpp index a662495a0..9124681a0 100644 --- a/src/ui/dialog/text-edit.cpp +++ b/src/ui/dialog/text-edit.cpp @@ -58,7 +58,7 @@ extern "C" { #include "widgets/font-selector.h" #include <glibmm/i18n.h> #include <glibmm/markup.h> -#include "unit-constants.h" +#include "util/units.h" #include "sp-textpath.h" namespace Inkscape { @@ -401,7 +401,7 @@ void TextEdit::setPreviewText (Glib::ustring font_spec, Glib::ustring phrase) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int unit = prefs->getInt("/options/font/unitType", SP_CSS_UNIT_PT); - double pt_size = sp_style_css_size_units_to_px(sp_font_selector_get_size(fsel), unit) * PT_PER_PX; + double pt_size = Inkscape::Util::Quantity::convert(sp_style_css_size_units_to_px(sp_font_selector_get_size(fsel), unit), "px", "pt"); // Pango font size is in 1024ths of a point // C++11: Glib::ustring size = std::to_string( pt_size * PANGO_SCALE ); diff --git a/src/ui/tool/control-point.h b/src/ui/tool/control-point.h index 27a0f8074..30efe8a27 100644 --- a/src/ui/tool/control-point.h +++ b/src/ui/tool/control-point.h @@ -23,7 +23,7 @@ #include "enums.h" class SPDesktop; -struct SPEventContext; +class SPEventContext; namespace Inkscape { namespace UI { diff --git a/src/ui/tool/node-tool.cpp b/src/ui/tool/node-tool.cpp index e743e0efc..76e33e506 100644 --- a/src/ui/tool/node-tool.cpp +++ b/src/ui/tool/node-tool.cpp @@ -104,64 +104,49 @@ using Inkscape::ControlManager; -namespace { - SPCanvasGroup *create_control_group(SPDesktop *d); -void ink_node_tool_dispose(GObject *object); - -void ink_node_tool_setup(SPEventContext *ec); -gint ink_node_tool_root_handler(SPEventContext *event_context, GdkEvent *event); -gint ink_node_tool_item_handler(SPEventContext *event_context, SPItem *item, GdkEvent *event); -void ink_node_tool_set(SPEventContext *ec, Inkscape::Preferences::Entry *value); - -void ink_node_tool_update_tip(InkNodeTool *nt, GdkEvent *event); -void ink_node_tool_selection_changed(InkNodeTool *nt, Inkscape::Selection *sel); -void ink_node_tool_select_area(InkNodeTool *nt, Geom::Rect const &, GdkEventButton *); -void ink_node_tool_select_point(InkNodeTool *nt, Geom::Point const &, GdkEventButton *); -void ink_node_tool_mouseover_changed(InkNodeTool *nt, Inkscape::UI::ControlPoint *p); - -void handleControlUiStyleChange(InkNodeTool *nt); - -} // anonymous namespace -G_DEFINE_TYPE(InkNodeTool, ink_node_tool, SP_TYPE_EVENT_CONTEXT); +#include "tool-factory.h" -static void -ink_node_tool_class_init(InkNodeToolClass *klass) -{ - GObjectClass *object_class = (GObjectClass *) klass; - SPEventContextClass *event_context_class = (SPEventContextClass *) klass; - - object_class->dispose = ink_node_tool_dispose; +namespace { + SPEventContext* createNodesContext() { + return new InkNodeTool(); + } - event_context_class->setup = ink_node_tool_setup; - event_context_class->set = ink_node_tool_set; - event_context_class->root_handler = ink_node_tool_root_handler; - event_context_class->item_handler = ink_node_tool_item_handler; + bool nodesContextRegistered = ToolFactory::instance().registerObject("/tools/nodes", createNodesContext); } -static void -ink_node_tool_init(InkNodeTool *nt) -{ - SPEventContext *event_context = SP_EVENT_CONTEXT(nt); - - event_context->cursor_shape = cursor_node_xpm; - event_context->hot_x = 1; - event_context->hot_y = 1; - - new (&nt->_selection_changed_connection) sigc::connection(); - new (&nt->_selection_modified_connection) sigc::connection(); - new (&nt->_mouseover_changed_connection) sigc::connection(); - new (&nt->_sizeUpdatedConn) sigc::connection(); - //new (&nt->_mgroup) Inkscape::UI::ManipulatorGroup(nt->desktop); - new (&nt->_selected_nodes) CSelPtr(); - new (&nt->_multipath) MultiPathPtr(); - new (&nt->_selector) SelectorPtr(); - new (&nt->_path_data) PathSharedDataPtr(); - new (&nt->_shape_editors) ShapeEditors(); +const std::string& InkNodeTool::getPrefsPath() { + return InkNodeTool::prefsPath; } -namespace { +const std::string InkNodeTool::prefsPath = "/tools/nodes"; + +InkNodeTool::InkNodeTool() : SPEventContext() { + this->show_handles = false; + this->single_node_transform_handles = false; + this->show_transform_handles = false; + this->cursor_drag = false; + this->live_objects = false; + this->edit_clipping_paths = false; + this->live_outline = false; + this->flashed_item = 0; + this->_transform_handle_group = 0; + this->show_path_direction = false; + this->_last_over = 0; + this->edit_masks = false; + this->show_outline = false; + this->flash_tempitem = 0; + + this->cursor_shape = cursor_node_xpm; + this->hot_x = 1; + this->hot_y = 1; + + this->_selected_nodes = 0; + this->_multipath = 0; + this->_selector = 0; + this->_path_data = 0; +} SPCanvasGroup *create_control_group(SPDesktop *d) { @@ -174,189 +159,160 @@ void destroy_group(SPCanvasGroup *g) sp_canvas_item_destroy(SP_CANVAS_ITEM(g)); } -void ink_node_tool_dispose(GObject *object) -{ - InkNodeTool *nt = INK_NODE_TOOL(object); - - nt->enableGrDrag(false); +InkNodeTool::~InkNodeTool() { + this->enableGrDrag(false); - if (nt->flash_tempitem) { - nt->desktop->remove_temporary_canvasitem(nt->flash_tempitem); + if (this->flash_tempitem) { + this->desktop->remove_temporary_canvasitem(this->flash_tempitem); } - nt->_selection_changed_connection.disconnect(); - nt->_selection_modified_connection.disconnect(); - nt->_mouseover_changed_connection.disconnect(); - nt->_sizeUpdatedConn.disconnect(); - nt->_multipath.~MultiPathPtr(); - nt->_selected_nodes.~CSelPtr(); - nt->_selector.~SelectorPtr(); - nt->_shape_editors.~ShapeEditors(); - - Inkscape::UI::PathSharedData &data = *nt->_path_data; + this->_selection_changed_connection.disconnect(); + //this->_selection_modified_connection.disconnect(); + this->_mouseover_changed_connection.disconnect(); + this->_sizeUpdatedConn.disconnect(); + + delete this->_multipath; + delete this->_selected_nodes; + delete this->_selector; + + Inkscape::UI::PathSharedData &data = *this->_path_data; destroy_group(data.node_data.node_group); destroy_group(data.node_data.handle_group); destroy_group(data.node_data.handle_line_group); destroy_group(data.outline_group); destroy_group(data.dragpoint_group); - destroy_group(nt->_transform_handle_group); - - nt->_path_data.~PathSharedDataPtr(); - nt->_selection_changed_connection.~connection(); - nt->_selection_modified_connection.~connection(); - nt->_mouseover_changed_connection.~connection(); - nt->_sizeUpdatedConn.~connection(); - - if (nt->_node_message_context) { - delete nt->_node_message_context; - } - - G_OBJECT_CLASS(ink_node_tool_parent_class)->dispose(object); + destroy_group(this->_transform_handle_group); } -void ink_node_tool_setup(SPEventContext *ec) -{ - InkNodeTool *nt = INK_NODE_TOOL(ec); +void InkNodeTool::setup() { + SPEventContext::setup(); - if (SP_EVENT_CONTEXT_CLASS(ink_node_tool_parent_class)->setup) - SP_EVENT_CONTEXT_CLASS(ink_node_tool_parent_class)->setup(ec); + this->_path_data = new Inkscape::UI::PathSharedData(); - nt->_node_message_context = new Inkscape::MessageContext((ec->desktop)->messageStack()); - - nt->_path_data.reset(new Inkscape::UI::PathSharedData()); - Inkscape::UI::PathSharedData &data = *nt->_path_data; - data.node_data.desktop = nt->desktop; + Inkscape::UI::PathSharedData &data = *this->_path_data; + data.node_data.desktop = this->desktop; // selector has to be created here, so that its hidden control point is on the bottom - nt->_selector.reset(new Inkscape::UI::Selector(nt->desktop)); + this->_selector = new Inkscape::UI::Selector(this->desktop); // Prepare canvas groups for controls. This guarantees correct z-order, so that // for example a dragpoint won't obscure a node - data.outline_group = create_control_group(nt->desktop); - data.node_data.handle_line_group = create_control_group(nt->desktop); - data.dragpoint_group = create_control_group(nt->desktop); - nt->_transform_handle_group = create_control_group(nt->desktop); - data.node_data.node_group = create_control_group(nt->desktop); - data.node_data.handle_group = create_control_group(nt->desktop); - - Inkscape::Selection *selection = sp_desktop_selection (ec->desktop); - nt->_selection_changed_connection.disconnect(); - nt->_selection_changed_connection = - selection->connectChanged( - sigc::bind<0>( - sigc::ptr_fun(&ink_node_tool_selection_changed), - nt)); - /*nt->_selection_modified_connection.disconnect(); - nt->_selection_modified_connection = - selection->connectModified( - sigc::hide(sigc::bind<0>( - sigc::ptr_fun(&ink_node_tool_selection_modified), - nt)));*/ - nt->_mouseover_changed_connection.disconnect(); - nt->_mouseover_changed_connection = - Inkscape::UI::ControlPoint::signal_mouseover_change.connect( - sigc::bind<0>( - sigc::ptr_fun(&ink_node_tool_mouseover_changed), - nt)); - - nt->_sizeUpdatedConn = ControlManager::getManager().connectCtrlSizeChanged(sigc::bind(sigc::ptr_fun(&handleControlUiStyleChange), nt)); + data.outline_group = create_control_group(this->desktop); + data.node_data.handle_line_group = create_control_group(this->desktop); + data.dragpoint_group = create_control_group(this->desktop); + this->_transform_handle_group = create_control_group(this->desktop); + data.node_data.node_group = create_control_group(this->desktop); + data.node_data.handle_group = create_control_group(this->desktop); + + Inkscape::Selection *selection = sp_desktop_selection (this->desktop); + + this->_selection_changed_connection.disconnect(); + this->_selection_changed_connection = + selection->connectChanged(sigc::mem_fun(this, &InkNodeTool::selection_changed)); + + this->_mouseover_changed_connection.disconnect(); + this->_mouseover_changed_connection = + Inkscape::UI::ControlPoint::signal_mouseover_change.connect(sigc::mem_fun(this, &InkNodeTool::mouseover_changed)); + + this->_sizeUpdatedConn = ControlManager::getManager().connectCtrlSizeChanged( + sigc::mem_fun(this, &InkNodeTool::handleControlUiStyleChange) + ); - nt->_selected_nodes.reset( - new Inkscape::UI::ControlPointSelection(nt->desktop, nt->_transform_handle_group)); - data.node_data.selection = nt->_selected_nodes.get(); - nt->_multipath.reset(new Inkscape::UI::MultiPathManipulator(data, - nt->_selection_changed_connection)); - - nt->_selector->signal_point.connect( - sigc::bind<0>( - sigc::ptr_fun(&ink_node_tool_select_point), - nt)); - nt->_selector->signal_area.connect( - sigc::bind<0>( - sigc::ptr_fun(&ink_node_tool_select_area), - nt)); - - nt->_multipath->signal_coords_changed.connect( + this->_selected_nodes = new Inkscape::UI::ControlPointSelection(this->desktop, this->_transform_handle_group); + + data.node_data.selection = this->_selected_nodes; + + this->_multipath = new Inkscape::UI::MultiPathManipulator(data, this->_selection_changed_connection); + + this->_selector->signal_point.connect(sigc::mem_fun(this, &InkNodeTool::select_point)); + this->_selector->signal_area.connect(sigc::mem_fun(this, &InkNodeTool::select_area)); + + this->_multipath->signal_coords_changed.connect( sigc::bind( - sigc::mem_fun(*nt->desktop, &SPDesktop::emitToolSubselectionChanged), - (void*) 0)); - nt->_selected_nodes->signal_point_changed.connect( - sigc::hide( sigc::hide( - sigc::bind( - sigc::bind( - sigc::ptr_fun(ink_node_tool_update_tip), - (GdkEvent*)0), - nt)))); - - nt->cursor_drag = false; - nt->show_transform_handles = true; - nt->single_node_transform_handles = false; - nt->flash_tempitem = NULL; - nt->flashed_item = NULL; - nt->_last_over = NULL; + sigc::mem_fun(*this->desktop, &SPDesktop::emitToolSubselectionChanged), + (void*)NULL + ) + ); + + this->_selected_nodes->signal_point_changed.connect( + // Hide both signal parameters and bind the function parameter to 0 + // sigc::signal<void, SelectableControlPoint *, bool> + // <=> + // void update_tip(GdkEvent *event) + sigc::hide(sigc::hide(sigc::bind( + sigc::mem_fun(this, &InkNodeTool::update_tip), + (GdkEvent*)NULL + ))) + ); + + this->cursor_drag = false; + this->show_transform_handles = true; + this->single_node_transform_handles = false; + this->flash_tempitem = NULL; + this->flashed_item = NULL; + this->_last_over = NULL; // read prefs before adding items to selection to prevent momentarily showing the outline - sp_event_context_read(nt, "show_handles"); - sp_event_context_read(nt, "show_outline"); - sp_event_context_read(nt, "live_outline"); - sp_event_context_read(nt, "live_objects"); - sp_event_context_read(nt, "show_path_direction"); - sp_event_context_read(nt, "show_transform_handles"); - sp_event_context_read(nt, "single_node_transform_handles"); - sp_event_context_read(nt, "edit_clipping_paths"); - sp_event_context_read(nt, "edit_masks"); - - ink_node_tool_selection_changed(nt, selection); - ink_node_tool_update_tip(nt, NULL); + sp_event_context_read(this, "show_handles"); + sp_event_context_read(this, "show_outline"); + sp_event_context_read(this, "live_outline"); + sp_event_context_read(this, "live_objects"); + sp_event_context_read(this, "show_path_direction"); + sp_event_context_read(this, "show_transform_handles"); + sp_event_context_read(this, "single_node_transform_handles"); + sp_event_context_read(this, "edit_clipping_paths"); + sp_event_context_read(this, "edit_masks"); + + this->selection_changed(selection); + this->update_tip(NULL); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if (prefs->getBool("/tools/nodes/selcue")) { - ec->enableSelectionCue(); + this->enableSelectionCue(); } + if (prefs->getBool("/tools/nodes/gradientdrag")) { - ec->enableGrDrag(); + this->enableGrDrag(); } - nt->desktop->emitToolSubselectionChanged(NULL); // sets the coord entry fields to inactive + this->desktop->emitToolSubselectionChanged(NULL); // sets the coord entry fields to inactive } -void ink_node_tool_set(SPEventContext *ec, Inkscape::Preferences::Entry *value) -{ - InkNodeTool *nt = INK_NODE_TOOL(ec); - Glib::ustring entry_name = value->getEntryName(); +void InkNodeTool::set(const Inkscape::Preferences::Entry& value) { + Glib::ustring entry_name = value.getEntryName(); if (entry_name == "show_handles") { - nt->show_handles = value->getBool(true); - nt->_multipath->showHandles(nt->show_handles); + this->show_handles = value.getBool(true); + this->_multipath->showHandles(this->show_handles); } else if (entry_name == "show_outline") { - nt->show_outline = value->getBool(); - nt->_multipath->showOutline(nt->show_outline); + this->show_outline = value.getBool(); + this->_multipath->showOutline(this->show_outline); } else if (entry_name == "live_outline") { - nt->live_outline = value->getBool(); - nt->_multipath->setLiveOutline(nt->live_outline); + this->live_outline = value.getBool(); + this->_multipath->setLiveOutline(this->live_outline); } else if (entry_name == "live_objects") { - nt->live_objects = value->getBool(); - nt->_multipath->setLiveObjects(nt->live_objects); + this->live_objects = value.getBool(); + this->_multipath->setLiveObjects(this->live_objects); } else if (entry_name == "show_path_direction") { - nt->show_path_direction = value->getBool(); - nt->_multipath->showPathDirection(nt->show_path_direction); + this->show_path_direction = value.getBool(); + this->_multipath->showPathDirection(this->show_path_direction); } else if (entry_name == "show_transform_handles") { - nt->show_transform_handles = value->getBool(true); - nt->_selected_nodes->showTransformHandles( - nt->show_transform_handles, nt->single_node_transform_handles); + this->show_transform_handles = value.getBool(true); + this->_selected_nodes->showTransformHandles( + this->show_transform_handles, this->single_node_transform_handles); } else if (entry_name == "single_node_transform_handles") { - nt->single_node_transform_handles = value->getBool(); - nt->_selected_nodes->showTransformHandles( - nt->show_transform_handles, nt->single_node_transform_handles); + this->single_node_transform_handles = value.getBool(); + this->_selected_nodes->showTransformHandles( + this->show_transform_handles, this->single_node_transform_handles); } else if (entry_name == "edit_clipping_paths") { - nt->edit_clipping_paths = value->getBool(); - ink_node_tool_selection_changed(nt, nt->desktop->selection); + this->edit_clipping_paths = value.getBool(); + this->selection_changed(this->desktop->selection); } else if (entry_name == "edit_masks") { - nt->edit_masks = value->getBool(); - ink_node_tool_selection_changed(nt, nt->desktop->selection); + this->edit_masks = value.getBool(); + this->selection_changed(this->desktop->selection); } else { - if (SP_EVENT_CONTEXT_CLASS(ink_node_tool_parent_class)->set) - SP_EVENT_CONTEXT_CLASS(ink_node_tool_parent_class)->set(ec, value); + SPEventContext::set(value); } } @@ -365,7 +321,10 @@ void gather_items(InkNodeTool *nt, SPItem *base, SPObject *obj, Inkscape::UI::Sh std::set<Inkscape::UI::ShapeRecord> &s) { using namespace Inkscape::UI; - if (!obj) return; + + if (!obj) { + return; + } //XML Tree being used directly here while it shouldn't be. if (SP_IS_PATH(obj) && obj->getRepr()->attribute("inkscape:original-d") != NULL) { @@ -385,11 +344,13 @@ void gather_items(InkNodeTool *nt, SPItem *base, SPObject *obj, Inkscape::UI::Sh // TODO add support for objectBoundingBox r.edit_transform = base ? base->i2doc_affine() : Geom::identity(); r.role = role; + if (s.insert(r).second) { // this item was encountered the first time if (nt->edit_clipping_paths && item->clip_ref) { gather_items(nt, item, item->clip_ref->getObject(), SHAPE_ROLE_CLIPPING_PATH, s); } + if (nt->edit_masks && item->mask_ref) { gather_items(nt, item, item->mask_ref->getObject(), SHAPE_ROLE_MASK, s); } @@ -397,8 +358,7 @@ void gather_items(InkNodeTool *nt, SPItem *base, SPObject *obj, Inkscape::UI::Sh } } -void ink_node_tool_selection_changed(InkNodeTool *nt, Inkscape::Selection *sel) -{ +void InkNodeTool::selection_changed(Inkscape::Selection *sel) { using namespace Inkscape::UI; std::set<ShapeRecord> shapes; @@ -407,20 +367,22 @@ void ink_node_tool_selection_changed(InkNodeTool *nt, Inkscape::Selection *sel) for (GSList *i = const_cast<GSList*>(ilist); i; i = i->next) { SPObject *obj = static_cast<SPObject*>(i->data); + if (SP_IS_ITEM(obj)) { - gather_items(nt, NULL, static_cast<SPItem*>(obj), SHAPE_ROLE_NORMAL, shapes); + gather_items(this, NULL, static_cast<SPItem*>(obj), SHAPE_ROLE_NORMAL, shapes); } } // use multiple ShapeEditors for now, to allow editing many shapes at once // needs to be rethought - for (ShapeEditors::iterator i = nt->_shape_editors.begin(); - i != nt->_shape_editors.end(); ) + for (boost::ptr_map<SPItem*, ShapeEditor>::iterator i = this->_shape_editors.begin(); + i != this->_shape_editors.end(); ) { ShapeRecord s; s.item = i->first; + if (shapes.find(s) == shapes.end()) { - nt->_shape_editors.erase(i++); + this->_shape_editors.erase(i++); } else { ++i; } @@ -428,22 +390,22 @@ void ink_node_tool_selection_changed(InkNodeTool *nt, Inkscape::Selection *sel) for (std::set<ShapeRecord>::iterator i = shapes.begin(); i != shapes.end(); ++i) { ShapeRecord const &r = *i; + if ((SP_IS_SHAPE(r.item) || SP_IS_TEXT(r.item)) && - nt->_shape_editors.find(r.item) == nt->_shape_editors.end()) + this->_shape_editors.find(r.item) == this->_shape_editors.end()) { - ShapeEditor *si = new ShapeEditor(nt->desktop); + ShapeEditor *si = new ShapeEditor(this->desktop); si->set_item(r.item, SH_KNOTHOLDER); - nt->_shape_editors.insert(const_cast<SPItem*&>(r.item), si); + this->_shape_editors.insert(const_cast<SPItem*&>(r.item), si); } } - nt->_multipath->setItems(shapes); - ink_node_tool_update_tip(nt, NULL); - nt->desktop->updateNow(); + this->_multipath->setItems(shapes); + this->update_tip(NULL); + this->desktop->updateNow(); } -gint ink_node_tool_root_handler(SPEventContext *event_context, GdkEvent *event) -{ +bool InkNodeTool::root_handler(GdkEvent* event) { /* things to handle here: * 1. selection of items * 2. passing events to manipulators @@ -451,14 +413,20 @@ gint ink_node_tool_root_handler(SPEventContext *event_context, GdkEvent *event) */ using namespace Inkscape::UI; // pull in event helpers - SPDesktop *desktop = event_context->desktop; Inkscape::Selection *selection = desktop->selection; - InkNodeTool *nt = static_cast<InkNodeTool*>(event_context); static Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - if (nt->_multipath->event(event_context, event)) return true; - if (nt->_selector->event(event_context, event)) return true; - if (nt->_selected_nodes->event(event_context, event)) return true; + if (this->_multipath->event(this, event)) { + return true; + } + + if (this->_selector->event(this, event)) { + return true; + } + + if (this->_selected_nodes->event(this, event)) { + return true; + } switch (event->type) { @@ -466,33 +434,52 @@ gint ink_node_tool_root_handler(SPEventContext *event_context, GdkEvent *event) combine_motion_events(desktop->canvas, event->motion, 0); SPItem *over_item = sp_event_context_find_item (desktop, event_point(event->button), FALSE, TRUE); - if (over_item != nt->_last_over) { - nt->_last_over = over_item; - ink_node_tool_update_tip(nt, event); + + if (over_item != this->_last_over) { + this->_last_over = over_item; + //ink_node_tool_update_tip(nt, event); + this->update_tip(event); } // create pathflash outline if (prefs->getBool("/tools/nodes/pathflash_enabled")) { - if (over_item == nt->flashed_item) break; - if (!prefs->getBool("/tools/nodes/pathflash_selected") && selection->includes(over_item)) break; - if (nt->flash_tempitem) { - desktop->remove_temporary_canvasitem(nt->flash_tempitem); - nt->flash_tempitem = NULL; - nt->flashed_item = NULL; + if (over_item == this->flashed_item) { + break; + } + + if (!prefs->getBool("/tools/nodes/pathflash_selected") && selection->includes(over_item)) { + break; } - if (!SP_IS_SHAPE(over_item)) break; // for now, handle only shapes - nt->flashed_item = over_item; + if (this->flash_tempitem) { + desktop->remove_temporary_canvasitem(this->flash_tempitem); + this->flash_tempitem = NULL; + this->flashed_item = NULL; + } + + if (!SP_IS_SHAPE(over_item)) { + break; // for now, handle only shapes + } + + this->flashed_item = over_item; SPCurve *c = SP_SHAPE(over_item)->getCurveBeforeLPE(); - if (!c) break; // break out when curve doesn't exist + + if (!c) { + break; // break out when curve doesn't exist + } + c->transform(over_item->i2dt_affine()); SPCanvasItem *flash = sp_canvas_bpath_new(sp_desktop_tempgroup(desktop), c); + sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(flash), prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff), 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); + sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(flash), 0, SP_WIND_RULE_NONZERO); - nt->flash_tempitem = desktop->add_temporary_canvasitem(flash, + + this->flash_tempitem = desktop->add_temporary_canvasitem(flash, prefs->getInt("/tools/nodes/pathflash_timeout", 500)); + c->unref(); } } break; // do not return true, because we need to pass this event to the parent context @@ -502,136 +489,152 @@ gint ink_node_tool_root_handler(SPEventContext *event_context, GdkEvent *event) switch (get_group0_keyval(&event->key)) { case GDK_KEY_Escape: // deselect everything - if (nt->_selected_nodes->empty()) { + if (this->_selected_nodes->empty()) { Inkscape::SelectionHelper::selectNone(desktop); } else { - nt->_selected_nodes->clear(); + this->_selected_nodes->clear(); } - ink_node_tool_update_tip(nt, event); + //ink_node_tool_update_tip(nt, event); + this->update_tip(event); return TRUE; + case GDK_KEY_a: case GDK_KEY_A: if (held_control(event->key) && held_alt(event->key)) { - nt->_selected_nodes->selectAll(); + this->_selected_nodes->selectAll(); // Ctrl+A is handled in selection-chemistry.cpp via verb - ink_node_tool_update_tip(nt, event); + //ink_node_tool_update_tip(nt, event); + this->update_tip(event); return TRUE; } break; + case GDK_KEY_h: case GDK_KEY_H: if (held_only_control(event->key)) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setBool("/tools/nodes/show_handles", !nt->show_handles); + prefs->setBool("/tools/nodes/show_handles", !this->show_handles); return TRUE; } break; + default: break; } - ink_node_tool_update_tip(nt, event); + //ink_node_tool_update_tip(nt, event); + this->update_tip(event); break; + case GDK_KEY_RELEASE: - ink_node_tool_update_tip(nt, event); + //ink_node_tool_update_tip(nt, event); + this->update_tip(event); break; - default: break; + + default: + break; } - if (SP_EVENT_CONTEXT_CLASS(ink_node_tool_parent_class)->root_handler) - return SP_EVENT_CONTEXT_CLASS(ink_node_tool_parent_class)->root_handler(event_context, event); - - return FALSE; + return SPEventContext::root_handler(event); } -void ink_node_tool_update_tip(InkNodeTool *nt, GdkEvent *event) -{ +void InkNodeTool::update_tip(GdkEvent *event) { using namespace Inkscape::UI; + if (event && (event->type == GDK_KEY_PRESS || event->type == GDK_KEY_RELEASE)) { unsigned new_state = state_after_event(event); - if (new_state == event->key.state) return; + + if (new_state == event->key.state) { + return; + } + if (state_held_shift(new_state)) { - if (nt->_last_over) { - nt->_node_message_context->set(Inkscape::NORMAL_MESSAGE, + if (this->_last_over) { + this->message_context->set(Inkscape::NORMAL_MESSAGE, C_("Node tool tip", "<b>Shift</b>: drag to add nodes to the selection, " "click to toggle object selection")); } else { - nt->_node_message_context->set(Inkscape::NORMAL_MESSAGE, + this->message_context->set(Inkscape::NORMAL_MESSAGE, C_("Node tool tip", "<b>Shift</b>: drag to add nodes to the selection")); } + return; } } - unsigned sz = nt->_selected_nodes->size(); - unsigned total = nt->_selected_nodes->allPoints().size(); + + unsigned sz = this->_selected_nodes->size(); + unsigned total = this->_selected_nodes->allPoints().size(); + if (sz != 0) { char *nodestring = g_strdup_printf( ngettext("<b>%u of %u</b> node selected.", "<b>%u of %u</b> nodes selected.", total), sz, total); - if (nt->_last_over) { + + if (this->_last_over) { // TRANSLATORS: The %s below is where the "%u of %u nodes selected" sentence gets put char *dyntip = g_strdup_printf(C_("Node tool tip", "%s Drag to select nodes, click to edit only this object (more: Shift)"), nodestring); - nt->_node_message_context->set(Inkscape::NORMAL_MESSAGE, dyntip); + this->message_context->set(Inkscape::NORMAL_MESSAGE, dyntip); g_free(dyntip); } else { char *dyntip = g_strdup_printf(C_("Node tool tip", "%s Drag to select nodes, click clear the selection"), nodestring); - nt->_node_message_context->set(Inkscape::NORMAL_MESSAGE, dyntip); + this->message_context->set(Inkscape::NORMAL_MESSAGE, dyntip); g_free(dyntip); } g_free(nodestring); - } else if (!nt->_multipath->empty()) { - if (nt->_last_over) { - nt->_node_message_context->set(Inkscape::NORMAL_MESSAGE, C_("Node tool tip", + } else if (!this->_multipath->empty()) { + if (this->_last_over) { + this->message_context->set(Inkscape::NORMAL_MESSAGE, C_("Node tool tip", "Drag to select nodes, click to edit only this object")); } else { - nt->_node_message_context->set(Inkscape::NORMAL_MESSAGE, C_("Node tool tip", + this->message_context->set(Inkscape::NORMAL_MESSAGE, C_("Node tool tip", "Drag to select nodes, click to clear the selection")); } } else { - if (nt->_last_over) { - nt->_node_message_context->set(Inkscape::NORMAL_MESSAGE, C_("Node tool tip", + if (this->_last_over) { + this->message_context->set(Inkscape::NORMAL_MESSAGE, C_("Node tool tip", "Drag to select objects to edit, click to edit this object (more: Shift)")); } else { - nt->_node_message_context->set(Inkscape::NORMAL_MESSAGE, C_("Node tool tip", + this->message_context->set(Inkscape::NORMAL_MESSAGE, C_("Node tool tip", "Drag to select objects to edit")); } } } -gint ink_node_tool_item_handler(SPEventContext *event_context, SPItem *item, GdkEvent *event) -{ - if (SP_EVENT_CONTEXT_CLASS(ink_node_tool_parent_class)->item_handler) - return SP_EVENT_CONTEXT_CLASS(ink_node_tool_parent_class)->item_handler(event_context, item, event); - - return FALSE; -} - -void ink_node_tool_select_area(InkNodeTool *nt, Geom::Rect const &sel, GdkEventButton *event) -{ +void InkNodeTool::select_area(Geom::Rect const &sel, GdkEventButton *event) { using namespace Inkscape::UI; - if (nt->_multipath->empty()) { + + if (this->_multipath->empty()) { // if multipath is empty, select rubberbanded items rather than nodes - Inkscape::Selection *selection = nt->desktop->selection; - GSList *items = sp_desktop_document(nt->desktop)->getItemsInBox(nt->desktop->dkey, sel); + Inkscape::Selection *selection = this->desktop->selection; + GSList *items = sp_desktop_document(this->desktop)->getItemsInBox(this->desktop->dkey, sel); selection->setList(items); g_slist_free(items); } else { - if (!held_shift(*event)) nt->_selected_nodes->clear(); - nt->_selected_nodes->selectArea(sel); + if (!held_shift(*event)) { + this->_selected_nodes->clear(); + } + + this->_selected_nodes->selectArea(sel); } } -void ink_node_tool_select_point(InkNodeTool *nt, Geom::Point const &/*sel*/, GdkEventButton *event) -{ + +void InkNodeTool::select_point(Geom::Point const &sel, GdkEventButton *event) { using namespace Inkscape::UI; // pull in event helpers - if (!event) return; - if (event->button != 1) return; - Inkscape::Selection *selection = nt->desktop->selection; + if (!event) { + return; + } + + if (event->button != 1) { + return; + } + + Inkscape::Selection *selection = this->desktop->selection; - SPItem *item_clicked = sp_event_context_find_item (nt->desktop, event_point(*event), + SPItem *item_clicked = sp_event_context_find_item (this->desktop, event_point(*event), (event->state & GDK_MOD1_MASK) && !(event->state & GDK_CONTROL_MASK), TRUE); if (item_clicked == NULL) { // nothing under cursor @@ -639,10 +642,10 @@ void ink_node_tool_select_point(InkNodeTool *nt, Geom::Point const &/*sel*/, Gdk // if there are nodes selected, the first click should deselect the nodes // and the second should deselect the items if (!state_held_shift(event->state)) { - if (nt->_selected_nodes->empty()) { + if (this->_selected_nodes->empty()) { selection->clear(); } else { - nt->_selected_nodes->clear(); + this->_selected_nodes->clear(); } } } else { @@ -651,35 +654,36 @@ void ink_node_tool_select_point(InkNodeTool *nt, Geom::Point const &/*sel*/, Gdk } else { selection->set(item_clicked); } - nt->desktop->updateNow(); + + this->desktop->updateNow(); } } -void ink_node_tool_mouseover_changed(InkNodeTool *nt, Inkscape::UI::ControlPoint *p) -{ +void InkNodeTool::mouseover_changed(Inkscape::UI::ControlPoint *p) { using Inkscape::UI::CurveDragPoint; + CurveDragPoint *cdp = dynamic_cast<CurveDragPoint*>(p); - if (cdp && !nt->cursor_drag) { - nt->cursor_shape = cursor_node_d_xpm; - nt->hot_x = 1; - nt->hot_y = 1; - sp_event_context_update_cursor(nt); - nt->cursor_drag = true; - } else if (!cdp && nt->cursor_drag) { - nt->cursor_shape = cursor_node_xpm; - nt->hot_x = 1; - nt->hot_y = 1; - sp_event_context_update_cursor(nt); - nt->cursor_drag = false; + + if (cdp && !this->cursor_drag) { + this->cursor_shape = cursor_node_d_xpm; + this->hot_x = 1; + this->hot_y = 1; + this->sp_event_context_update_cursor(); + this->cursor_drag = true; + } else if (!cdp && this->cursor_drag) { + this->cursor_shape = cursor_node_xpm; + this->hot_x = 1; + this->hot_y = 1; + this->sp_event_context_update_cursor(); + this->cursor_drag = false; } } -void handleControlUiStyleChange(InkNodeTool *nt) -{ - nt->_multipath->updateHandles(); +void InkNodeTool::handleControlUiStyleChange() { + this->_multipath->updateHandles(); } -} // anonymous namespace +//} // anonymous namespace /* Local Variables: diff --git a/src/ui/tool/node-tool.h b/src/ui/tool/node-tool.h index 341faf329..c41f50650 100644 --- a/src/ui/tool/node-tool.h +++ b/src/ui/tool/node-tool.h @@ -11,70 +11,77 @@ #ifndef SEEN_UI_TOOL_NODE_TOOL_H #define SEEN_UI_TOOL_NODE_TOOL_H -#include <memory> #include <boost/ptr_container/ptr_map.hpp> #include <glib.h> #include "event-context.h" -#define INK_TYPE_NODE_TOOL (ink_node_tool_get_type ()) -#define INK_NODE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INK_TYPE_NODE_TOOL, InkNodeTool)) -#define INK_NODE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INK_TYPE_NODE_TOOL, InkNodeToolClass)) -#define INK_IS_NODE_TOOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INK_TYPE_NODE_TOOL)) -#define INK_IS_NODE_TOOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INK_TYPE_NODE_TOOL)) - namespace Inkscape { + namespace Display { + class TemporaryItem; + } + + namespace UI { + class MultiPathManipulator; + class ControlPointSelection; + class Selector; + class ControlPoint; + + struct PathSharedData; + } +} + +#define INK_NODE_TOOL(obj) (dynamic_cast<InkNodeTool*>((SPEventContext*)obj)) +#define INK_IS_NODE_TOOL(obj) (dynamic_cast<const InkNodeTool*>((const SPEventContext*)obj)) + +class InkNodeTool : public SPEventContext { +public: + InkNodeTool(); + virtual ~InkNodeTool(); + + Inkscape::UI::ControlPointSelection* _selected_nodes; + Inkscape::UI::MultiPathManipulator* _multipath; + + bool edit_clipping_paths; + bool edit_masks; + + static const std::string prefsPath; -namespace Display { -class TemporaryItem; -} // namespace Display -namespace UI { -class MultiPathManipulator; -class ControlPointSelection; -class Selector; -struct PathSharedData; -} // namespace UI -} // namespace Inkscape - -typedef std::auto_ptr<Inkscape::UI::MultiPathManipulator> MultiPathPtr; -typedef std::auto_ptr<Inkscape::UI::ControlPointSelection> CSelPtr; -typedef std::auto_ptr<Inkscape::UI::Selector> SelectorPtr; -typedef std::auto_ptr<Inkscape::UI::PathSharedData> PathSharedDataPtr; -typedef boost::ptr_map<SPItem*, ShapeEditor> ShapeEditors; - -struct InkNodeTool : public SPEventContext -{ - sigc::connection _selection_changed_connection; + virtual void setup(); + virtual void set(const Inkscape::Preferences::Entry& val); + virtual bool root_handler(GdkEvent* event); + + virtual const std::string& getPrefsPath(); + +private: + sigc::connection _selection_changed_connection; sigc::connection _mouseover_changed_connection; - sigc::connection _selection_modified_connection; sigc::connection _sizeUpdatedConn; - Inkscape::MessageContext *_node_message_context; + SPItem *flashed_item; Inkscape::Display::TemporaryItem *flash_tempitem; - CSelPtr _selected_nodes; - MultiPathPtr _multipath; - SelectorPtr _selector; - PathSharedDataPtr _path_data; + Inkscape::UI::Selector* _selector; + Inkscape::UI::PathSharedData* _path_data; SPCanvasGroup *_transform_handle_group; SPItem *_last_over; - ShapeEditors _shape_editors; - - unsigned cursor_drag : 1; - unsigned show_handles : 1; - unsigned show_outline : 1; - unsigned live_outline : 1; - unsigned live_objects : 1; - unsigned show_path_direction : 1; - unsigned show_transform_handles : 1; - unsigned single_node_transform_handles : 1; - unsigned edit_clipping_paths : 1; - unsigned edit_masks : 1; -}; + boost::ptr_map<SPItem*, ShapeEditor> _shape_editors; -struct InkNodeToolClass { - SPEventContextClass parent_class; -}; + bool cursor_drag; + bool show_handles; + bool show_outline; + bool live_outline; + bool live_objects; + bool show_path_direction; + bool show_transform_handles; + bool single_node_transform_handles; + + void selection_changed(Inkscape::Selection *sel); -GType ink_node_tool_get_type (void); + void select_area(Geom::Rect const &sel, GdkEventButton *event); + void select_point(Geom::Point const &sel, GdkEventButton *event); + void mouseover_changed(Inkscape::UI::ControlPoint *p); + void update_tip(GdkEvent *event); + void handleControlUiStyleChange(); +}; #endif diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index dc6e0fbae..76ec68c3e 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -22,7 +22,6 @@ #include "preferences.h" #include "snap.h" #include "snap-preferences.h" -#include "sp-metrics.h" #include "sp-namedview.h" #include "ui/control-manager.h" #include "ui/tool/control-point-selection.h" @@ -490,9 +489,13 @@ Glib::ustring Handle::_getDragTip(GdkEventMotion */*event*/) const double angle = Geom::angle_between(Geom::Point(-1,0), position() - _parent->position()); angle += M_PI; // angle is (-M_PI...M_PI] - offset by +pi and scale to 0...360 angle *= 360.0 / (2 * M_PI); - GString *x = SP_PX_TO_METRIC_STRING(dist[Geom::X], _desktop->namedview->getDefaultMetric()); - GString *y = SP_PX_TO_METRIC_STRING(dist[Geom::Y], _desktop->namedview->getDefaultMetric()); - GString *len = SP_PX_TO_METRIC_STRING(length(), _desktop->namedview->getDefaultMetric()); + + Inkscape::Util::Quantity x_q = Inkscape::Util::Quantity(dist[Geom::X], "px"); + Inkscape::Util::Quantity y_q = Inkscape::Util::Quantity(dist[Geom::Y], "px"); + Inkscape::Util::Quantity len_q = Inkscape::Util::Quantity(length(), "px"); + GString *x = g_string_new(x_q.string(_desktop->namedview->doc_units).c_str()); + GString *y = g_string_new(y_q.string(_desktop->namedview->doc_units).c_str()); + GString *len = g_string_new(len_q.string(_desktop->namedview->doc_units).c_str()); Glib::ustring ret = format_tip(C_("Path handle tip", "Move handle by %s, %s; angle %.2f°, length %s"), x->str, y->str, angle, len->str); g_string_free(x, TRUE); @@ -1294,10 +1297,12 @@ Glib::ustring Node::_getTip(unsigned state) const Glib::ustring Node::_getDragTip(GdkEventMotion */*event*/) const { Geom::Point dist = position() - _last_drag_origin(); - GString *x = SP_PX_TO_METRIC_STRING(dist[Geom::X], _desktop->namedview->getDefaultMetric()); - GString *y = SP_PX_TO_METRIC_STRING(dist[Geom::Y], _desktop->namedview->getDefaultMetric()); - Glib::ustring ret = format_tip(C_("Path node tip", "Move node by %s, %s"), - x->str, y->str); + + Inkscape::Util::Quantity x_q = Inkscape::Util::Quantity(dist[Geom::X], "px"); + Inkscape::Util::Quantity y_q = Inkscape::Util::Quantity(dist[Geom::Y], "px"); + GString *x = g_string_new(x_q.string(_desktop->namedview->doc_units).c_str()); + GString *y = g_string_new(y_q.string(_desktop->namedview->doc_units).c_str()); + Glib::ustring ret = format_tip(C_("Path node tip", "Move node by %s, %s"), x->str, y->str); g_string_free(x, TRUE); g_string_free(y, TRUE); return ret; diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index ac023beaa..d12e2958b 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -203,7 +203,7 @@ void PathManipulator::writeXML() sp_object_ref(_path); _path->deleteObject(true, true); sp_object_unref(_path); - _path = 0; + _path = NULL; } _observer->unblock(); } @@ -459,7 +459,10 @@ void PathManipulator::weldSegments() if (j->selected()) ++num_selected; else ++num_unselected; } - if (num_selected < 3) continue; + + // if 2 or fewer nodes are selected, there can't be any middle points to remove. + if (num_selected <= 2) continue; + if (num_unselected == 0 && sp->closed()) { // if all nodes in a closed subpath are selected, the operation doesn't make much sense continue; @@ -489,14 +492,16 @@ void PathManipulator::weldSegments() } if (num_points > 2) { // remove nodes in the middle + // TODO: fit bezier to the former shape sel_beg = sel_beg.next(); while (sel_beg != sel_end.prev()) { NodeList::iterator next = sel_beg.next(); sp->erase(sel_beg); sel_beg = next; } - sel_beg = sel_end; } + sel_beg = sel_end; + // decrease num_selected by the number of points processed num_selected -= num_points; } } @@ -1201,8 +1206,9 @@ void PathManipulator::_createGeometryFromControlPoints(bool alert_LPE) Geom::PathVector pathv = builder.peek() * (_edit_transform * _i2d_transform).inverse(); _spcurve->set_pathvector(pathv); if (alert_LPE) { - if (SP_IS_LPE_ITEM(_path) && sp_lpe_item_has_path_effect(SP_LPE_ITEM(_path))) { - PathEffectList effect_list = sp_lpe_item_get_effect_list(SP_LPE_ITEM(_path)); + /// \todo note that _path can be an Inkscape::LivePathEffect::Effect* too, kind of confusing, rework member naming? + if (SP_IS_LPE_ITEM(_path) && _path->hasPathEffect()) { + PathEffectList effect_list = _path->getEffectList(); LivePathEffect::LPEPowerStroke *lpe_pwr = dynamic_cast<LivePathEffect::LPEPowerStroke*>( effect_list.front()->lpeobject->get_lpe() ); if (lpe_pwr) { lpe_pwr->adjustForNewPath(pathv); @@ -1304,6 +1310,10 @@ void PathManipulator::_getGeometry() } else { _spcurve->unref(); _spcurve = _path->get_curve_for_edit(); + // never allow NULL to sneak in here! + if (_spcurve == NULL) { + _spcurve = new SPCurve(); + } } } @@ -1328,7 +1338,7 @@ void PathManipulator::_setGeometry() if (_path->getRepr()->attribute("inkscape:original-d")) _path->set_original_curve(_spcurve, false, false); else - SP_SHAPE(_path)->setCurve(_spcurve, false); + _path->setCurve(_spcurve, false); } } diff --git a/src/ui/tool/path-manipulator.h b/src/ui/tool/path-manipulator.h index 1444272e8..e01e8617f 100644 --- a/src/ui/tool/path-manipulator.h +++ b/src/ui/tool/path-manipulator.h @@ -131,7 +131,7 @@ private: SubpathList _subpaths; MultiPathManipulator &_multi_path_manipulator; - SPPath *_path; + SPPath *_path; ///< can be an SPPath or an Inkscape::LivePathEffect::Effect !!! SPCurve *_spcurve; // in item coordinates SPCanvasItem *_outline; CurveDragPoint *_dragpoint; // an invisible control point hoverng over curve diff --git a/src/ui/tool/transform-handle-set.cpp b/src/ui/tool/transform-handle-set.cpp index 30963cabd..daed3a523 100644 --- a/src/ui/tool/transform-handle-set.cpp +++ b/src/ui/tool/transform-handle-set.cpp @@ -129,7 +129,8 @@ bool TransformHandle::grabbed(GdkEventMotion *) // Collect the snap-candidates, one for each selected node. These will be stored in the _snap_points vector. InkNodeTool *nt = INK_NODE_TOOL(_th._desktop->event_context); - ControlPointSelection *selection = nt->_selected_nodes.get(); + //ControlPointSelection *selection = nt->_selected_nodes.get(); + ControlPointSelection* selection = nt->_selected_nodes; selection->setOriginalPoints(); selection->getOriginalPoints(_snap_points); @@ -293,7 +294,7 @@ protected: private: static Glib::RefPtr<Gdk::Pixbuf> _corner_to_pixbuf(unsigned c) { - sp_select_context_get_type(); + //sp_select_context_get_type(); switch (c % 2) { case 0: return Glib::wrap(handles[1], true); @@ -376,7 +377,7 @@ protected: } private: static Glib::RefPtr<Gdk::Pixbuf> _side_to_pixbuf(unsigned c) { - sp_select_context_get_type(); + //sp_select_context_get_type(); switch (c % 2) { case 0: return Glib::wrap(handles[3], true); default: return Glib::wrap(handles[2], true); @@ -456,7 +457,7 @@ protected: private: static Glib::RefPtr<Gdk::Pixbuf> _corner_to_pixbuf(unsigned c) { - sp_select_context_get_type(); + //sp_select_context_get_type(); switch (c % 4) { case 0: return Glib::wrap(handles[7], true); case 1: return Glib::wrap(handles[6], true); @@ -603,7 +604,7 @@ protected: private: static Glib::RefPtr<Gdk::Pixbuf> _side_to_pixbuf(unsigned s) { - sp_select_context_get_type(); + //sp_select_context_get_type(); switch (s % 4) { case 0: return Glib::wrap(handles[10], true); case 1: return Glib::wrap(handles[9], true); @@ -658,7 +659,7 @@ protected: private: static Glib::RefPtr<Gdk::Pixbuf> _get_pixbuf() { - sp_select_context_get_type(); + //sp_select_context_get_type(); return Glib::wrap(handles[12], true); } diff --git a/src/ui/view/view-widget.h b/src/ui/view/view-widget.h index 295e7932b..668f9d19a 100644 --- a/src/ui/view/view-widget.h +++ b/src/ui/view/view-widget.h @@ -23,7 +23,7 @@ class View; } // namespace Inkscape class SPViewWidget; -struct SPNamedView; +class SPNamedView; #define SP_TYPE_VIEW_WIDGET (sp_view_widget_get_type ()) #define SP_VIEW_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_VIEW_WIDGET, SPViewWidget)) diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert index 2de954674..710b95c2b 100644 --- a/src/ui/widget/Makefile_insert +++ b/src/ui/widget/Makefile_insert @@ -79,5 +79,7 @@ ink_common_sources += \ ui/widget/tolerance-slider.cpp \ ui/widget/tolerance-slider.h \ ui/widget/unit-menu.cpp \ - ui/widget/unit-menu.h + ui/widget/unit-menu.h \ + ui/widget/unit-tracker.h \ + ui/widget/unit-tracker.cpp diff --git a/src/ui/widget/color-preview.cpp b/src/ui/widget/color-preview.cpp index 4b4a7b738..5bcd16528 100644 --- a/src/ui/widget/color-preview.cpp +++ b/src/ui/widget/color-preview.cpp @@ -73,9 +73,9 @@ ColorPreview::on_expose_event (GdkEventExpose *event) if (get_is_drawable()) { Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context(); - cr->rectangle(event->area.x, event->area.y, + cr->rectangle(event->area.x, event->area.y, event->area.width, event->area.height); - cr->clip(); + cr->clip(); result = on_draw(cr); } @@ -176,12 +176,7 @@ ColorPreview::toPixbuf (int width, int height) cairo_destroy(ct); cairo_surface_flush(s); - GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data( cairo_image_surface_get_data(s), - GDK_COLORSPACE_RGB, TRUE, 8, - width, height, cairo_image_surface_get_stride(s), - ink_cairo_pixbuf_cleanup, s); - convert_pixbuf_argb32_to_normal(pixbuf); - + GdkPixbuf* pixbuf = ink_pixbuf_create_from_cairo_surface(s); return pixbuf; } diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp index 988c4e5de..b13567adb 100644 --- a/src/ui/widget/page-sizer.cpp +++ b/src/ui/widget/page-sizer.cpp @@ -37,7 +37,7 @@ #include "desktop.h" #include "helper/action.h" #include "helper/action-context.h" -#include "helper/units.h" +#include "util/units.h" #include "inkscape.h" #include "sp-namedview.h" #include "sp-root.h" @@ -48,6 +48,7 @@ #include "xml/repr.h" using std::pair; +using Inkscape::Util::unit_table; namespace Inkscape { namespace UI { @@ -96,7 +97,7 @@ struct PaperSizeRec { char const * const name; //name double const smaller; //lesser dimension double const larger; //greater dimension - SPUnitId const unit; //units + Glib::ustring const unit; //units }; // list of page formats that should be in landscape automatically @@ -114,31 +115,31 @@ fill_landscape_papers() { } static PaperSizeRec const inkscape_papers[] = { - { "A4", 210, 297, SP_UNIT_MM }, - { "US Letter", 8.5, 11, SP_UNIT_IN }, - { "US Legal", 8.5, 14, SP_UNIT_IN }, - { "US Executive", 7.25, 10.5, SP_UNIT_IN }, - { "A0", 841, 1189, SP_UNIT_MM }, - { "A1", 594, 841, SP_UNIT_MM }, - { "A2", 420, 594, SP_UNIT_MM }, - { "A3", 297, 420, SP_UNIT_MM }, - { "A5", 148, 210, SP_UNIT_MM }, - { "A6", 105, 148, SP_UNIT_MM }, - { "A7", 74, 105, SP_UNIT_MM }, - { "A8", 52, 74, SP_UNIT_MM }, - { "A9", 37, 52, SP_UNIT_MM }, - { "A10", 26, 37, SP_UNIT_MM }, - { "B0", 1000, 1414, SP_UNIT_MM }, - { "B1", 707, 1000, SP_UNIT_MM }, - { "B2", 500, 707, SP_UNIT_MM }, - { "B3", 353, 500, SP_UNIT_MM }, - { "B4", 250, 353, SP_UNIT_MM }, - { "B5", 176, 250, SP_UNIT_MM }, - { "B6", 125, 176, SP_UNIT_MM }, - { "B7", 88, 125, SP_UNIT_MM }, - { "B8", 62, 88, SP_UNIT_MM }, - { "B9", 44, 62, SP_UNIT_MM }, - { "B10", 31, 44, SP_UNIT_MM }, + { "A4", 210, 297, "mm" }, + { "US Letter", 8.5, 11, "in" }, + { "US Legal", 8.5, 14, "in" }, + { "US Executive", 7.25, 10.5, "in" }, + { "A0", 841, 1189, "mm" }, + { "A1", 594, 841, "mm" }, + { "A2", 420, 594, "mm" }, + { "A3", 297, 420, "mm" }, + { "A5", 148, 210, "mm" }, + { "A6", 105, 148, "mm" }, + { "A7", 74, 105, "mm" }, + { "A8", 52, 74, "mm" }, + { "A9", 37, 52, "mm" }, + { "A10", 26, 37, "mm" }, + { "B0", 1000, 1414, "mm" }, + { "B1", 707, 1000, "mm" }, + { "B2", 500, 707, "mm" }, + { "B3", 353, 500, "mm" }, + { "B4", 250, 353, "mm" }, + { "B5", 176, 250, "mm" }, + { "B6", 125, 176, "mm" }, + { "B7", 88, 125, "mm" }, + { "B8", 62, 88, "mm" }, + { "B9", 44, 62, "mm" }, + { "B10", 31, 44, "mm" }, @@ -150,63 +151,63 @@ static PaperSizeRec const inkscape_papers[] = { don't know what D and E series are used for. */ - { "C0", 917, 1297, SP_UNIT_MM }, - { "C1", 648, 917, SP_UNIT_MM }, - { "C2", 458, 648, SP_UNIT_MM }, - { "C3", 324, 458, SP_UNIT_MM }, - { "C4", 229, 324, SP_UNIT_MM }, - { "C5", 162, 229, SP_UNIT_MM }, - { "C6", 114, 162, SP_UNIT_MM }, - { "C7", 81, 114, SP_UNIT_MM }, - { "C8", 57, 81, SP_UNIT_MM }, - { "C9", 40, 57, SP_UNIT_MM }, - { "C10", 28, 40, SP_UNIT_MM }, - { "D1", 545, 771, SP_UNIT_MM }, - { "D2", 385, 545, SP_UNIT_MM }, - { "D3", 272, 385, SP_UNIT_MM }, - { "D4", 192, 272, SP_UNIT_MM }, - { "D5", 136, 192, SP_UNIT_MM }, - { "D6", 96, 136, SP_UNIT_MM }, - { "D7", 68, 96, SP_UNIT_MM }, - { "E3", 400, 560, SP_UNIT_MM }, - { "E4", 280, 400, SP_UNIT_MM }, - { "E5", 200, 280, SP_UNIT_MM }, - { "E6", 140, 200, SP_UNIT_MM }, + { "C0", 917, 1297, "mm" }, + { "C1", 648, 917, "mm" }, + { "C2", 458, 648, "mm" }, + { "C3", 324, 458, "mm" }, + { "C4", 229, 324, "mm" }, + { "C5", 162, 229, "mm" }, + { "C6", 114, 162, "mm" }, + { "C7", 81, 114, "mm" }, + { "C8", 57, 81, "mm" }, + { "C9", 40, 57, "mm" }, + { "C10", 28, 40, "mm" }, + { "D1", 545, 771, "mm" }, + { "D2", 385, 545, "mm" }, + { "D3", 272, 385, "mm" }, + { "D4", 192, 272, "mm" }, + { "D5", 136, 192, "mm" }, + { "D6", 96, 136, "mm" }, + { "D7", 68, 96, "mm" }, + { "E3", 400, 560, "mm" }, + { "E4", 280, 400, "mm" }, + { "E5", 200, 280, "mm" }, + { "E6", 140, 200, "mm" }, //#endif - { "CSE", 462, 649, SP_UNIT_PT }, - { "US #10 Envelope", 4.125, 9.5, SP_UNIT_IN }, + { "CSE", 462, 649, "pt" }, + { "US #10 Envelope", 4.125, 9.5, "in" }, /* See http://www.hbp.com/content/PCR_envelopes.cfm for a much larger list of US envelope sizes. */ - { "DL Envelope", 110, 220, SP_UNIT_MM }, - { "Ledger/Tabloid", 11, 17, SP_UNIT_IN }, + { "DL Envelope", 110, 220, "mm" }, + { "Ledger/Tabloid", 11, 17, "in" }, /* Note that `Folio' (used in QPrinter/KPrinter) is deliberately absent from this list, as it means different sizes to different people: different people may expect the width to be either 8, 8.25 or 8.5 inches, and the height to be either 13 or 13.5 inches, even restricting our interpretation to foolscap folio. If you wish to introduce a folio-like page size to the list, then please consider using a name more specific than just `Folio' or `Foolscap Folio'. */ - { "Banner 468x60", 60, 468, SP_UNIT_PX }, - { "Icon 16x16", 16, 16, SP_UNIT_PX }, - { "Icon 32x32", 32, 32, SP_UNIT_PX }, - { "Icon 48x48", 48, 48, SP_UNIT_PX }, + { "Banner 468x60", 60, 468, "px" }, + { "Icon 16x16", 16, 16, "px" }, + { "Icon 32x32", 32, 32, "px" }, + { "Icon 48x48", 48, 48, "px" }, /* business cards */ - { "Business Card (ISO 7810)", 53.98, 85.60, SP_UNIT_MM }, - { "Business Card (US)", 2, 3.5, SP_UNIT_IN }, - { "Business Card (Europe)", 55, 85, SP_UNIT_MM }, - { "Business Card (Aus/NZ)", 55, 90, SP_UNIT_MM }, + { "Business Card (ISO 7810)", 53.98, 85.60, "mm" }, + { "Business Card (US)", 2, 3.5, "in" }, + { "Business Card (Europe)", 55, 85, "mm" }, + { "Business Card (Aus/NZ)", 55, 90, "mm" }, // Start Arch Series List - { "Arch A", 9, 12, SP_UNIT_IN }, // 229 x 305 mm - { "Arch B", 12, 18, SP_UNIT_IN }, // 305 x 457 mm - { "Arch C", 18, 24, SP_UNIT_IN }, // 457 x 610 mm - { "Arch D", 24, 36, SP_UNIT_IN }, // 610 x 914 mm - { "Arch E", 36, 48, SP_UNIT_IN }, // 914 x 1219 mm - { "Arch E1", 30, 42, SP_UNIT_IN }, // 762 x 1067 mm + { "Arch A", 9, 12, "in" }, // 229 x 305 mm + { "Arch B", 12, 18, "in" }, // 305 x 457 mm + { "Arch C", 18, 24, "in" }, // 457 x 610 mm + { "Arch D", 24, 36, "in" }, // 610 x 914 mm + { "Arch E", 36, 48, "in" }, // 914 x 1219 mm + { "Arch E1", 30, 42, "in" }, // 762 x 1067 mm /* * The above list of Arch sizes were taken from the following site: @@ -217,7 +218,7 @@ static PaperSizeRec const inkscape_papers[] = { * September 2009 - DAK */ - { NULL, 0, 0, SP_UNIT_PX }, + { NULL, 0, 0, "px" }, }; @@ -226,10 +227,6 @@ static PaperSizeRec const inkscape_papers[] = { //# P A G E S I Z E R //######################################################################## -//The default unit for this widget and its calculations -static const SPUnit _px_unit = sp_unit_get_by_id (SP_UNIT_PX); - - /** * Constructor */ @@ -280,13 +277,8 @@ PageSizer::PageSizer(Registry & _wr) char formatBuf[80]; snprintf(formatBuf, 79, "%0.1f x %0.1f", p->smaller, p->larger); Glib::ustring desc = formatBuf; - if (p->unit == SP_UNIT_IN) - desc.append(" in"); - else if (p->unit == SP_UNIT_MM) - desc.append(" mm"); - else if (p->unit == SP_UNIT_PX) - desc.append(" px"); - PaperSize paper(name, p->smaller, p->larger, p->unit); + desc.append(" " + p->unit); + PaperSize paper(name, p->smaller, p->larger, unit_table.getUnit(p->unit)); _paperSizeTable[name] = paper; Gtk::TreeModel::Row row = *(_paperSizeListStore->append()); row[_paperSizeListColumns.nameColumn] = name; @@ -320,9 +312,9 @@ PageSizer::PageSizer(Registry & _wr) SPNamedView *nv = sp_desktop_namedview(dt); _wr.setUpdating (true); if (nv->units) { - _dimensionUnits.setUnit(nv->units); + _dimensionUnits.setUnit(nv->units->abbr); } else if (nv->doc_units) { - _dimensionUnits.setUnit(nv->doc_units); + _dimensionUnits.setUnit(nv->doc_units->abbr); } _wr.setUpdating (false); @@ -450,6 +442,7 @@ PageSizer::init () _portrait_connection = _portraitButton.signal_toggled().connect (sigc::mem_fun (*this, &PageSizer::on_portrait)); _changedw_connection = _dimensionWidth.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_value_changed)); _changedh_connection = _dimensionHeight.signal_value_changed().connect (sigc::mem_fun (*this, &PageSizer::on_value_changed)); + _changedu_connection = _dimensionUnits.getUnitMenu()->signal_changed().connect (sigc::mem_fun (*this, &PageSizer::on_units_changed)); _fitPageButton.signal_clicked().connect(sigc::mem_fun(*this, &PageSizer::fire_fit_canvas_to_selection_or_drawing)); show_all_children(); @@ -462,11 +455,11 @@ PageSizer::init () * 'changeList' is true, then adjust the paperSizeList to show the closest * standard page size. * - * \param w, h given in px + * \param w, h * \param changeList whether to modify the paper size list */ void -PageSizer::setDim (double w, double h, bool changeList) +PageSizer::setDim (Inkscape::Util::Quantity w, Inkscape::Util::Quantity h, bool changeList) { static bool _called = false; if (_called) { @@ -481,14 +474,16 @@ PageSizer::setDim (double w, double h, bool changeList) _changedw_connection.block(); _changedh_connection.block(); + _unit = w.unit->abbr; + if (SP_ACTIVE_DESKTOP && !_widgetRegistry->isUpdating()) { SPDocument *doc = sp_desktop_document(SP_ACTIVE_DESKTOP); - double const old_height = doc->getHeight(); - doc->setWidth (w, &_px_unit); - doc->setHeight (h, &_px_unit); + Inkscape::Util::Quantity const old_height = doc->getHeight(); + doc->setWidth (w); + doc->setHeight (h); // The origin for the user is in the lower left corner; this point should remain stationary when // changing the page size. The SVG's origin however is in the upper left corner, so we must compensate for this - Geom::Translate const vert_offset(Geom::Point(0, (old_height - h))); + Geom::Translate const vert_offset(Geom::Point(0, (old_height.value("px") - h.value("px")))); doc->getRoot()->translateChildItems(vert_offset); DocumentUndo::done(doc, SP_VERB_NONE, _("Set page size")); } @@ -511,9 +506,10 @@ PageSizer::setDim (double w, double h, bool changeList) _paperSizeListSelection->select(row); } - Unit const& unit = _dimensionUnits.getUnit(); - _dimensionWidth.setValue (w / unit.factor); - _dimensionHeight.setValue (h / unit.factor); + _dimensionWidth.setUnit(w.unit->abbr); + _dimensionWidth.setValue (w.quantity); + _dimensionHeight.setUnit(h.unit->abbr); + _dimensionHeight.setValue (h.quantity); _paper_size_list_connection.unblock(); _landscape_connection.unblock(); @@ -555,12 +551,12 @@ PageSizer::updateFitMarginsUI(Inkscape::XML::Node *nv_repr) * paperSizeListStore->children().end() if no such paper exists. */ Gtk::ListStore::iterator -PageSizer::find_paper_size (double w, double h) const +PageSizer::find_paper_size (Inkscape::Util::Quantity w, Inkscape::Util::Quantity h) const { - double smaller = w; - double larger = h; + double smaller = w.quantity; + double larger = h.quantity; if ( h < w ) { - smaller = h; larger = w; + smaller = h.quantity; larger = w.quantity; } g_return_val_if_fail(smaller <= larger, _paperSizeListStore->children().end()); @@ -569,9 +565,8 @@ PageSizer::find_paper_size (double w, double h) const for (iter = _paperSizeTable.begin() ; iter != _paperSizeTable.end() ; ++iter) { PaperSize paper = iter->second; - SPUnit const &i_unit = sp_unit_get_by_id(paper.unit); - double smallX = sp_units_get_pixels(paper.smaller, i_unit); - double largeX = sp_units_get_pixels(paper.larger, i_unit); + double smallX = Inkscape::Util::Quantity::convert(paper.smaller, paper.unit, w.unit); + double largeX = Inkscape::Util::Quantity::convert(paper.larger, paper.unit, w.unit); g_return_val_if_fail(smallX <= largeX, _paperSizeListStore->children().end()); @@ -651,8 +646,8 @@ PageSizer::on_paper_size_list_changed() return; } PaperSize paper = piter->second; - double w = paper.smaller; - double h = paper.larger; + Inkscape::Util::Quantity w = Inkscape::Util::Quantity(paper.smaller, paper.unit); + Inkscape::Util::Quantity h = Inkscape::Util::Quantity(paper.larger, paper.unit); if (std::find(lscape_papers.begin(), lscape_papers.end(), paper.name.c_str()) != lscape_papers.end()) { // enforce landscape mode if this is desired for the given page format @@ -662,10 +657,6 @@ PageSizer::on_paper_size_list_changed() _landscape = _landscapeButton.get_active(); } - SPUnit const &src_unit = sp_unit_get_by_id (paper.unit); - sp_convert_distance (&w, &src_unit, &_px_unit); - sp_convert_distance (&h, &src_unit, &_px_unit); - if (_landscape) setDim (h, w, false); else @@ -682,8 +673,8 @@ PageSizer::on_portrait() { if (!_portraitButton.get_active()) return; - double w = _dimensionWidth.getValue ("px"); - double h = _dimensionHeight.getValue ("px"); + Inkscape::Util::Quantity w = Inkscape::Util::Quantity(_dimensionWidth.getValue(""), _dimensionWidth.getUnit()); + Inkscape::Util::Quantity h = Inkscape::Util::Quantity(_dimensionHeight.getValue(""), _dimensionHeight.getUnit()); if (h < w) { setDim (h, w); } @@ -698,8 +689,8 @@ PageSizer::on_landscape() { if (!_landscapeButton.get_active()) return; - double w = _dimensionWidth.getValue ("px"); - double h = _dimensionHeight.getValue ("px"); + Inkscape::Util::Quantity w = Inkscape::Util::Quantity(_dimensionWidth.getValue(""), _dimensionWidth.getUnit()); + Inkscape::Util::Quantity h = Inkscape::Util::Quantity(_dimensionHeight.getValue(""), _dimensionHeight.getUnit()); if (w < h) { setDim (h, w); } @@ -712,11 +703,18 @@ void PageSizer::on_value_changed() { if (_widgetRegistry->isUpdating()) return; - - setDim (_dimensionWidth.getValue("px"), - _dimensionHeight.getValue("px")); + if (_unit != _dimensionUnits.getUnit()->abbr) return; + setDim (Inkscape::Util::Quantity(_dimensionWidth.getValue(""), _dimensionUnits.getUnit()), + Inkscape::Util::Quantity(_dimensionHeight.getValue(""), _dimensionUnits.getUnit())); +} +void +PageSizer::on_units_changed() +{ + if (_widgetRegistry->isUpdating()) return; + _unit = _dimensionUnits.getUnit()->abbr; + setDim (Inkscape::Util::Quantity(_dimensionWidth.getValue(""), _dimensionUnits.getUnit()), + Inkscape::Util::Quantity(_dimensionHeight.getValue(""), _dimensionUnits.getUnit())); } - } // namespace Widget } // namespace UI diff --git a/src/ui/widget/page-sizer.h b/src/ui/widget/page-sizer.h index d1fbb56e0..dc8e34d82 100644 --- a/src/ui/widget/page-sizer.h +++ b/src/ui/widget/page-sizer.h @@ -18,7 +18,7 @@ #include "ui/widget/registered-widget.h" #include <sigc++/sigc++.h> -#include "helper/units.h" +#include "util/units.h" #include <gtkmm/alignment.h> #include <gtkmm/expander.h> @@ -64,7 +64,7 @@ public: PaperSize(const Glib::ustring &nameArg, double smallerArg, double largerArg, - SPUnitId unitArg) + Inkscape::Util::Unit const *unitArg) { name = nameArg; smaller = smallerArg; @@ -108,7 +108,7 @@ public: /** * The units (px, pt, mm, etc) of this specification */ - SPUnitId unit; + Inkscape::Util::Unit const *unit; /// pointer to object in UnitTable, do not delete private: @@ -117,7 +117,7 @@ private: name = ""; smaller = 0.0; larger = 0.0; - unit = SP_UNIT_PX; + unit = unit_table.getUnit("px"); } void assign(const PaperSize &other) @@ -161,7 +161,7 @@ public: * Set the page size to the given dimensions. If 'changeList' is * true, then reset the paper size list to the closest match */ - void setDim (double w, double h, bool changeList=true); + void setDim (Inkscape::Util::Quantity w, Inkscape::Util::Quantity h, bool changeList=true); /** * Updates the scalar widgets for the fit margins. (Just changes the value @@ -179,7 +179,7 @@ protected: /** * Find the closest standard paper size in the table, to the */ - Gtk::ListStore::iterator find_paper_size (double w, double h) const; + Gtk::ListStore::iterator find_paper_size (Inkscape::Util::Quantity w, Inkscape::Util::Quantity h) const; void fire_fit_canvas_to_selection_or_drawing(); @@ -252,13 +252,17 @@ protected: //callback void on_value_changed(); + void on_units_changed(); sigc::connection _changedw_connection; sigc::connection _changedh_connection; + sigc::connection _changedu_connection; Registry *_widgetRegistry; //### state - whether we are currently landscape or portrait bool _landscape; + + Glib::ustring _unit; }; diff --git a/src/ui/widget/preferences-widget.cpp b/src/ui/widget/preferences-widget.cpp index 567f29f91..3ba00c083 100644 --- a/src/ui/widget/preferences-widget.cpp +++ b/src/ui/widget/preferences-widget.cpp @@ -354,7 +354,7 @@ void PrefSpinUnit::on_my_value_changed() Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (getWidget()->get_visible()) //only take action if user changed value { - prefs->setDoubleUnit(_prefs_path, getValue(getUnit().abbr), getUnit().abbr); + prefs->setDoubleUnit(_prefs_path, getValue(getUnit()->abbr), getUnit()->abbr); } } diff --git a/src/ui/widget/registered-widget.cpp b/src/ui/widget/registered-widget.cpp index ea2bac867..ae6a7d1e0 100644 --- a/src/ui/widget/registered-widget.cpp +++ b/src/ui/widget/registered-widget.cpp @@ -27,7 +27,6 @@ #include "ui/widget/random.h" #include "widgets/spinbutton-events.h" -#include "helper/units.h" #include "xml/repr.h" #include "svg/svg-color.h" #include "svg/stringstream.h" @@ -118,9 +117,9 @@ RegisteredUnitMenu::RegisteredUnitMenu (const Glib::ustring& label, const Glib:: } void -RegisteredUnitMenu::setUnit (const SPUnit* unit) +RegisteredUnitMenu::setUnit (Glib::ustring unit) { - getUnitMenu()->setUnit (sp_unit_get_abbreviation (unit)); + getUnitMenu()->setUnit(unit); } void diff --git a/src/ui/widget/registered-widget.h b/src/ui/widget/registered-widget.h index fa35b815e..883a9e1a2 100644 --- a/src/ui/widget/registered-widget.h +++ b/src/ui/widget/registered-widget.h @@ -32,7 +32,6 @@ #include <gtkmm/checkbutton.h> -struct SPUnit; class SPDocument; namespace Gtk { @@ -128,6 +127,7 @@ private: repr = NULL; doc = NULL; write_undo = false; + event_type = -1; } }; @@ -166,8 +166,8 @@ public: Inkscape::XML::Node* repr_in = NULL, SPDocument *doc_in = NULL ); - void setUnit (const SPUnit*); - Unit getUnit() const { return static_cast<UnitMenu*>(_widget)->getUnit(); }; + void setUnit (const Glib::ustring); + Unit const * getUnit() const { return static_cast<UnitMenu*>(_widget)->getUnit(); }; UnitMenu* getUnitMenu() const { return static_cast<UnitMenu*>(_widget); }; sigc::connection _changed_connection; diff --git a/src/ui/widget/rendering-options.cpp b/src/ui/widget/rendering-options.cpp index f26e71553..d6248df69 100644 --- a/src/ui/widget/rendering-options.cpp +++ b/src/ui/widget/rendering-options.cpp @@ -13,7 +13,7 @@ #endif #include "rendering-options.h" -#include "unit-constants.h" +#include "util/units.h" #include <glibmm/i18n.h> namespace Inkscape { @@ -59,8 +59,8 @@ RenderingOptions::RenderingOptions () : _radio_bitmap.signal_toggled().connect(sigc::mem_fun(*this, &RenderingOptions::_toggled)); // configure default DPI - _dpi.setRange(PT_PER_IN,2400.0); - _dpi.setValue(PT_PER_IN); + _dpi.setRange(Inkscape::Util::Quantity::convert(1, "in", "pt"),2400.0); + _dpi.setValue(Inkscape::Util::Quantity::convert(1, "in", "pt")); _dpi.setIncrements(1.0,10.0); _dpi.setDigits(0); _dpi.update(); diff --git a/src/ui/widget/scalar-unit.cpp b/src/ui/widget/scalar-unit.cpp index 99ff70846..4fa1a7584 100644 --- a/src/ui/widget/scalar-unit.cpp +++ b/src/ui/widget/scalar-unit.cpp @@ -16,6 +16,8 @@ #include "scalar-unit.h" #include "spinbutton.h" +using Inkscape::Util::unit_table; + namespace Inkscape { namespace UI { namespace Widget { @@ -100,7 +102,7 @@ void ScalarUnit::resetUnitType(UnitType unit_type) lastUnits = _unit_menu->getUnitAbbr(); } -Unit ScalarUnit::getUnit() const +Unit const * ScalarUnit::getUnit() const { g_assert(_unit_menu != NULL); return _unit_menu->getUnit(); @@ -226,14 +228,13 @@ void ScalarUnit::on_unit_changed() Glib::ustring abbr = _unit_menu->getUnitAbbr(); _suffix->set_label(abbr); - Inkscape::Util::UnitTable &table = _unit_menu->getUnitTable(); - Inkscape::Util::Unit new_unit = (table.getUnit(abbr)); - Inkscape::Util::Unit old_unit = (table.getUnit(lastUnits)); + Inkscape::Util::Unit const *new_unit = unit_table.getUnit(abbr); + Inkscape::Util::Unit const *old_unit = unit_table.getUnit(lastUnits); double convertedVal = 0; - if (old_unit.type == UNIT_TYPE_DIMENSIONLESS && new_unit.type == UNIT_TYPE_LINEAR) { + if (old_unit->type == UNIT_TYPE_DIMENSIONLESS && new_unit->type == UNIT_TYPE_LINEAR) { convertedVal = PercentageToAbsolute(Scalar::getValue()); - } else if (old_unit.type == UNIT_TYPE_LINEAR && new_unit.type == UNIT_TYPE_DIMENSIONLESS) { + } else if (old_unit->type == UNIT_TYPE_LINEAR && new_unit->type == UNIT_TYPE_DIMENSIONLESS) { convertedVal = AbsoluteToPercentage(Scalar::getValue()); } else { double conversion = _unit_menu->getConversion(lastUnits); diff --git a/src/ui/widget/scalar-unit.h b/src/ui/widget/scalar-unit.h index 4f22f438c..9e310d3bd 100644 --- a/src/ui/widget/scalar-unit.h +++ b/src/ui/widget/scalar-unit.h @@ -82,7 +82,7 @@ public: /** * Gets the object for the currently selected unit. */ - Unit getUnit() const; + Unit const * getUnit() const; /** * Gets the UnitType ID for the unit. diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp index 18dbb984b..3a6b0c7df 100644 --- a/src/ui/widget/selected-style.cpp +++ b/src/ui/widget/selected-style.cpp @@ -24,8 +24,8 @@ #include "style.h" #include "desktop-style.h" #include "sp-namedview.h" -#include "sp-linear-gradient-fns.h" -#include "sp-radial-gradient-fns.h" +#include "sp-linear-gradient.h" +#include "sp-radial-gradient.h" #include "sp-pattern.h" #include "ui/dialog/dialog-manager.h" #include "ui/dialog/fill-and-stroke.h" @@ -50,6 +50,9 @@ #include "pixmaps/cursor-adj-a.xpm" #include "sp-cursor.h" #include "gradient-chemistry.h" +#include "util/units.h" + +using Inkscape::Util::unit_table; 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"}; @@ -306,15 +309,17 @@ SelectedStyle::SelectedStyle(bool /*layout*/) { int row = 0; - // List of units should match with Fill/Stroke dialog stroke style width list - for (GSList *l = sp_unit_get_list(SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE); l != NULL; l = l->next) { - SPUnit const *u = static_cast<SPUnit*>(l->data); + Inkscape::Util::UnitTable::UnitMap m = unit_table.units(Inkscape::Util::UNIT_TYPE_LINEAR); + Inkscape::Util::UnitTable::UnitMap::iterator iter = m.begin(); + while(iter != m.end()) { Gtk::RadioMenuItem *mi = Gtk::manage(new Gtk::RadioMenuItem(_sw_group)); - mi->add(*(new Gtk::Label(u->abbr, 0.0, 0.5))); + mi->add(*(new Gtk::Label(iter->first, 0.0, 0.5))); _unit_mis = g_slist_append(_unit_mis, mi); - mi->signal_activate().connect(sigc::bind<SPUnitId>(sigc::mem_fun(*this, &SelectedStyle::on_popup_units), u->unit_id)); + Inkscape::Util::Unit const *u = unit_table.getUnit(iter->first); + mi->signal_activate().connect(sigc::bind<Inkscape::Util::Unit const *>(sigc::mem_fun(*this, &SelectedStyle::on_popup_units), u)); _popup_sw.attach(*mi, 0,1, row, row+1); row++; + ++iter; } _popup_sw.attach(*(new Gtk::SeparatorMenuItem()), 0,1, row, row+1); @@ -476,13 +481,13 @@ SelectedStyle::setDesktop(SPDesktop *desktop) this ) )); - _sw_unit = const_cast<SPUnit*>(sp_desktop_namedview(desktop)->doc_units); + _sw_unit = sp_desktop_namedview(desktop)->doc_units; // Set the doc default unit active in the units list gint length = g_slist_length(_unit_mis); for (int i = 0; i < length; i++) { Gtk::RadioMenuItem *mi = (Gtk::RadioMenuItem *) g_slist_nth_data(_unit_mis, i); - if (mi && mi->get_label() == Glib::ustring(_sw_unit->abbr)) { + if (mi && mi->get_label() == _sw_unit->abbr) { mi->set_active(); break; } @@ -926,8 +931,8 @@ SelectedStyle::on_opacity_click(GdkEventButton *event) return false; } -void SelectedStyle::on_popup_units(SPUnitId id) { - _sw_unit = (SPUnit *) &(sp_unit_get_by_id(id)); +void SelectedStyle::on_popup_units(Inkscape::Util::Unit const *unit) { + _sw_unit = unit; update(); } @@ -935,7 +940,7 @@ void SelectedStyle::on_popup_preset(int i) { SPCSSAttr *css = sp_repr_css_attr_new (); gdouble w; if (_sw_unit) { - w = sp_units_get_pixels (_sw_presets[i], *_sw_unit); + w = Inkscape::Util::Quantity::convert(_sw_presets[i], _sw_unit, "px"); } else { w = _sw_presets[i]; } @@ -1114,7 +1119,7 @@ SelectedStyle::update() { double w; if (_sw_unit) { - w = sp_pixels_get_units(query->stroke_width.computed, *_sw_unit); + w = Inkscape::Util::Quantity::convert(query->stroke_width.computed, "px", _sw_unit); } else { w = query->stroke_width.computed; } @@ -1128,7 +1133,7 @@ SelectedStyle::update() { gchar *str = g_strdup_printf(_("Stroke width: %.5g%s%s"), w, - _sw_unit? sp_unit_get_abbreviation(_sw_unit) : "px", + _sw_unit? _sw_unit->abbr.c_str() : "px", (result_sw == QUERY_STYLE_MULTIPLE_AVERAGED)? _(" (averaged)") : ""); _stroke_width_place.set_tooltip_text(str); @@ -1351,25 +1356,25 @@ RotateableSwatch::do_motion(double by, guint modifier) { DocumentUndo::maybeDone(sp_desktop_document(parent->getDesktop()), undokey, SP_VERB_DIALOG_FILL_STROKE, (_("Adjust alpha"))); double ch = hsla[3]; - parent->getDesktop()->event_context->_message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("Adjusting <b>alpha</b>: was %.3g, now <b>%.3g</b> (diff %.3g); with <b>Ctrl</b> to adjust lightness, with <b>Shift</b> to adjust saturation, without modifiers to adjust hue"), ch - diff, ch, diff); + parent->getDesktop()->event_context->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("Adjusting <b>alpha</b>: was %.3g, now <b>%.3g</b> (diff %.3g); with <b>Ctrl</b> to adjust lightness, with <b>Shift</b> to adjust saturation, without modifiers to adjust hue"), ch - diff, ch, diff); } else if (modifier == 2) { // saturation DocumentUndo::maybeDone(sp_desktop_document(parent->getDesktop()), undokey, SP_VERB_DIALOG_FILL_STROKE, (_("Adjust saturation"))); double ch = hsla[1]; - parent->getDesktop()->event_context->_message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("Adjusting <b>saturation</b>: was %.3g, now <b>%.3g</b> (diff %.3g); with <b>Ctrl</b> to adjust lightness, with <b>Alt</b> to adjust alpha, without modifiers to adjust hue"), ch - diff, ch, diff); + parent->getDesktop()->event_context->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("Adjusting <b>saturation</b>: was %.3g, now <b>%.3g</b> (diff %.3g); with <b>Ctrl</b> to adjust lightness, with <b>Alt</b> to adjust alpha, without modifiers to adjust hue"), ch - diff, ch, diff); } else if (modifier == 1) { // lightness DocumentUndo::maybeDone(sp_desktop_document(parent->getDesktop()), undokey, SP_VERB_DIALOG_FILL_STROKE, (_("Adjust lightness"))); double ch = hsla[2]; - parent->getDesktop()->event_context->_message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("Adjusting <b>lightness</b>: was %.3g, now <b>%.3g</b> (diff %.3g); with <b>Shift</b> to adjust saturation, with <b>Alt</b> to adjust alpha, without modifiers to adjust hue"), ch - diff, ch, diff); + parent->getDesktop()->event_context->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("Adjusting <b>lightness</b>: was %.3g, now <b>%.3g</b> (diff %.3g); with <b>Shift</b> to adjust saturation, with <b>Alt</b> to adjust alpha, without modifiers to adjust hue"), ch - diff, ch, diff); } else { // hue DocumentUndo::maybeDone(sp_desktop_document(parent->getDesktop()), undokey, SP_VERB_DIALOG_FILL_STROKE, (_("Adjust hue"))); double ch = hsla[0]; - parent->getDesktop()->event_context->_message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("Adjusting <b>hue</b>: was %.3g, now <b>%.3g</b> (diff %.3g); with <b>Shift</b> to adjust saturation, with <b>Alt</b> to adjust alpha, with <b>Ctrl</b> to adjust lightness"), ch - diff, ch, diff); + parent->getDesktop()->event_context->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("Adjusting <b>hue</b>: was %.3g, now <b>%.3g</b> (diff %.3g); with <b>Shift</b> to adjust saturation, with <b>Alt</b> to adjust alpha, with <b>Ctrl</b> to adjust lightness"), ch - diff, ch, diff); } } @@ -1424,7 +1429,7 @@ RotateableSwatch::do_release(double by, guint modifier) { undokey = "ssrot1"; } - parent->getDesktop()->event_context->_message_context->clear(); + parent->getDesktop()->event_context->message_context->clear(); startcolor_set = false; } @@ -1490,7 +1495,7 @@ RotateableStrokeWidth::do_motion(double by, guint modifier) { double diff = value_adjust(startvalue, by, modifier, false); DocumentUndo::maybeDone(sp_desktop_document(parent->getDesktop()), undokey, SP_VERB_DIALOG_FILL_STROKE, (_("Adjust stroke width"))); - parent->getDesktop()->event_context->_message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("Adjusting <b>stroke width</b>: was %.3g, now <b>%.3g</b> (diff %.3g)"), startvalue, startvalue + diff, diff); + parent->getDesktop()->event_context->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("Adjusting <b>stroke width</b>: was %.3g, now <b>%.3g</b> (diff %.3g)"), startvalue, startvalue + diff, diff); } } @@ -1511,7 +1516,7 @@ RotateableStrokeWidth::do_release(double by, guint modifier) { } else { undokey = "swrot1"; } - parent->getDesktop()->event_context->_message_context->clear(); + parent->getDesktop()->event_context->message_context->clear(); } void diff --git a/src/ui/widget/selected-style.h b/src/ui/widget/selected-style.h index e5bc4f883..21e5575ed 100644 --- a/src/ui/widget/selected-style.h +++ b/src/ui/widget/selected-style.h @@ -41,12 +41,15 @@ #include <sigc++/sigc++.h> #include "rotateable.h" -#include "helper/units.h" class SPDesktop; -struct SPUnit; namespace Inkscape { + +namespace Util { + class Unit; +} + namespace UI { namespace Widget { @@ -273,11 +276,11 @@ protected: Gtk::Menu _popup_sw; Gtk::RadioButtonGroup _sw_group; GSList *_unit_mis; - void on_popup_units(SPUnitId id); + void on_popup_units(Inkscape::Util::Unit const *u); void on_popup_preset(int i); Gtk::MenuItem _popup_sw_remove; - SPUnit *_sw_unit; + Inkscape::Util::Unit const *_sw_unit; /// points to object in UnitTable, do not delete void *_drop[2]; bool _dropEnabled[2]; diff --git a/src/ui/widget/spinbutton.cpp b/src/ui/widget/spinbutton.cpp index c107979a8..6cbc15c1b 100644 --- a/src/ui/widget/spinbutton.cpp +++ b/src/ui/widget/spinbutton.cpp @@ -14,6 +14,7 @@ #include "spinbutton.h" #include "unit-menu.h" +#include "unit-tracker.h" #include "util/expression-evaluator.h" #include "event-context.h" @@ -32,16 +33,23 @@ SpinButton::connect_signals() { int SpinButton::on_input(double* newvalue) { try { - Inkscape::Util::GimpEevlQuantity result; - if (_unit_menu) { - Unit unit = _unit_menu->getUnit(); - result = Inkscape::Util::gimp_eevl_evaluate (get_text().c_str(), &unit); + Inkscape::Util::EvaluatorQuantity result; + if (_unit_menu || _unit_tracker) { + Unit const *unit = NULL; + if (_unit_menu) { + unit = _unit_menu->getUnit(); + } else { + unit = _unit_tracker->getActiveUnit(); + } + Inkscape::Util::ExpressionEvaluator eval = Inkscape::Util::ExpressionEvaluator(get_text().c_str(), unit); + result = eval.evaluate(); // check if output dimension corresponds to input unit - if (result.dimension != (unit.isAbsolute() ? 1 : 0) ) { + if (result.dimension != (unit->isAbsolute() ? 1 : 0) ) { throw Inkscape::Util::EvaluatorException("Input dimensions do not match with parameter dimensions.",""); } } else { - result = Inkscape::Util::gimp_eevl_evaluate (get_text().c_str(), NULL); + Inkscape::Util::ExpressionEvaluator eval = Inkscape::Util::ExpressionEvaluator(get_text().c_str(), NULL); + result = eval.evaluate(); } *newvalue = result.value; @@ -57,7 +65,7 @@ int SpinButton::on_input(double* newvalue) bool SpinButton::on_my_focus_in_event(GdkEventFocus* /*event*/) { - on_focus_in_value = get_value(); + _on_focus_in_value = get_value(); return false; // do not consume the event } @@ -84,7 +92,7 @@ bool SpinButton::on_my_key_press_event(GdkEventKey* event) void SpinButton::undo() { - set_value(on_focus_in_value); + set_value(_on_focus_in_value); } diff --git a/src/ui/widget/spinbutton.h b/src/ui/widget/spinbutton.h index fe5d699e7..812b5f515 100644 --- a/src/ui/widget/spinbutton.h +++ b/src/ui/widget/spinbutton.h @@ -25,6 +25,7 @@ namespace UI { namespace Widget { class UnitMenu; +class UnitTracker; /** * SpinButton widget, that allows entry of simple math expressions (also units, when linked with UnitMenu), @@ -37,7 +38,9 @@ class SpinButton : public Gtk::SpinButton public: SpinButton(double climb_rate = 0.0, guint digits = 0) : Gtk::SpinButton(climb_rate, digits), - _unit_menu(NULL) + _unit_menu(NULL), + _unit_tracker(NULL), + _on_focus_in_value(0.) { connect_signals(); }; @@ -47,7 +50,9 @@ public: explicit SpinButton(Gtk::Adjustment& adjustment, double climb_rate = 0.0, guint digits = 0) #endif : Gtk::SpinButton(adjustment, climb_rate, digits), - _unit_menu(NULL) + _unit_menu(NULL), + _unit_tracker(NULL), + _on_focus_in_value(0.) { connect_signals(); }; @@ -55,9 +60,13 @@ public: virtual ~SpinButton() {}; void setUnitMenu(UnitMenu* unit_menu) { _unit_menu = unit_menu; }; + + void addUnitTracker(UnitTracker* ut) { _unit_tracker = ut; }; protected: UnitMenu *_unit_menu; /// Linked unit menu for unit conversion in entered expressions. + UnitTracker *_unit_tracker; // Linked unit tracker for unit conversion in entered expressions. + double _on_focus_in_value; void connect_signals(); @@ -90,8 +99,6 @@ protected: */ void undo(); - double on_focus_in_value; - private: // noncopyable SpinButton(const SpinButton&); diff --git a/src/ui/widget/style-swatch.cpp b/src/ui/widget/style-swatch.cpp index aedab3fa5..a33c1d09f 100644 --- a/src/ui/widget/style-swatch.cpp +++ b/src/ui/widget/style-swatch.cpp @@ -20,13 +20,13 @@ #include "ui/widget/color-preview.h" #include "style.h" -#include "sp-linear-gradient-fns.h" -#include "sp-radial-gradient-fns.h" +#include "sp-linear-gradient.h" +#include "sp-radial-gradient.h" #include "sp-pattern.h" #include "xml/repr.h" #include "xml/sp-css-attr.h" #include "widgets/widget-sizes.h" -#include "helper/units.h" +#include "util/units.h" #include "helper/action.h" #include "helper/action-context.h" #include "preferences.h" @@ -333,7 +333,7 @@ void StyleSwatch::setStyle(SPStyle *query) if (has_stroke) { double w; if (_sw_unit) { - w = sp_pixels_get_units(query->stroke_width.computed, *_sw_unit); + w = Inkscape::Util::Quantity::convert(query->stroke_width.computed, "px", _sw_unit); } else { w = query->stroke_width.computed; } @@ -346,7 +346,7 @@ void StyleSwatch::setStyle(SPStyle *query) { gchar *str = g_strdup_printf(_("Stroke width: %.5g%s"), w, - _sw_unit? sp_unit_get_abbreviation(_sw_unit) : "px"); + _sw_unit? _sw_unit->abbr.c_str() : "px"); _stroke_width_place.set_tooltip_text(str); g_free (str); } diff --git a/src/ui/widget/style-swatch.h b/src/ui/widget/style-swatch.h index 6bdb5e248..6da58a2dd 100644 --- a/src/ui/widget/style-swatch.h +++ b/src/ui/widget/style-swatch.h @@ -30,7 +30,6 @@ #include "button.h" #include "preferences.h" -struct SPUnit; struct SPStyle; class SPCSSAttr; @@ -43,6 +42,11 @@ class Table; } namespace Inkscape { + +namespace Util { + class Unit; +} + namespace UI { namespace Widget { @@ -93,7 +97,7 @@ private: Gtk::EventBox _stroke_width_place; Gtk::Label _stroke_width; - SPUnit *_sw_unit; + Inkscape::Util::Unit *_sw_unit; friend class ToolObserver; }; diff --git a/src/ui/widget/unit-menu.cpp b/src/ui/widget/unit-menu.cpp index 18b7bcab9..7416a2f02 100644 --- a/src/ui/widget/unit-menu.cpp +++ b/src/ui/widget/unit-menu.cpp @@ -15,6 +15,8 @@ #include "unit-menu.h" +using Inkscape::Util::unit_table; + namespace Inkscape { namespace UI { namespace Widget { @@ -30,15 +32,13 @@ UnitMenu::~UnitMenu() { bool UnitMenu::setUnitType(UnitType unit_type) { // Expand the unit widget with unit entries from the unit table - UnitTable::UnitMap m = _unit_table.units(unit_type); - UnitTable::UnitMap::iterator iter = m.begin(); - while(iter != m.end()) { - Glib::ustring text = (*iter).first; - append(text); - ++iter; + UnitTable::UnitMap m = unit_table.units(unit_type); + + for (UnitTable::UnitMap::iterator i = m.begin(); i != m.end(); ++i) { + append(i->first); } _type = unit_type; - set_active_text(_unit_table.primary(unit_type)); + set_active_text(unit_table.primary(unit_type)); return true; } @@ -52,17 +52,17 @@ bool UnitMenu::resetUnitType(UnitType unit_type) void UnitMenu::addUnit(Unit const& u) { - _unit_table.addUnit(u, false); + unit_table.addUnit(u, false); append(u.abbr); } -Unit UnitMenu::getUnit() const +Unit const * UnitMenu::getUnit() const { if (get_active_text() == "") { g_assert(_type != UNIT_TYPE_NONE); - return _unit_table.getUnit(_unit_table.primary(_type)); + return unit_table.getUnit(unit_table.primary(_type)); } - return _unit_table.getUnit(get_active_text()); + return unit_table.getUnit(get_active_text()); } bool UnitMenu::setUnit(Glib::ustring const & unit) @@ -79,27 +79,27 @@ Glib::ustring UnitMenu::getUnitAbbr() const if (get_active_text() == "") { return ""; } - return getUnit().abbr; + return getUnit()->abbr; } UnitType UnitMenu::getUnitType() const { - return getUnit().type; + return getUnit()->type; } double UnitMenu::getUnitFactor() const { - return getUnit().factor; + return getUnit()->factor; } int UnitMenu::getDefaultDigits() const { - return getUnit().defaultDigits(); + return getUnit()->defaultDigits(); } double UnitMenu::getDefaultStep() const { - int factor_digits = -1*int(log10(getUnit().factor)); + int factor_digits = -1*int(log10(getUnit()->factor)); return pow(10.0, factor_digits); } @@ -110,19 +110,20 @@ double UnitMenu::getDefaultPage() const double UnitMenu::getConversion(Glib::ustring const &new_unit_abbr, Glib::ustring const &old_unit_abbr) const { - double old_factor = getUnit().factor; - if (old_unit_abbr != "no_unit") - old_factor = _unit_table.getUnit(old_unit_abbr).factor; - Unit new_unit = _unit_table.getUnit(new_unit_abbr); + double old_factor = getUnit()->factor; + if (old_unit_abbr != "no_unit") { + old_factor = unit_table.getUnit(old_unit_abbr)->factor; + } + Unit const * new_unit = unit_table.getUnit(new_unit_abbr); // Catch the case of zero or negative unit factors (error!) if (old_factor < 0.0000001 || - new_unit.factor < 0.0000001) { + new_unit->factor < 0.0000001) { // TODO: Should we assert here? return 0.00; } - return old_factor / new_unit.factor; + return old_factor / new_unit->factor; } bool UnitMenu::isAbsolute() const diff --git a/src/ui/widget/unit-menu.h b/src/ui/widget/unit-menu.h index 3104d5aef..114c536c9 100644 --- a/src/ui/widget/unit-menu.h +++ b/src/ui/widget/unit-menu.h @@ -74,7 +74,7 @@ public: * Returns the Unit object corresponding to the current selection * in the dropdown widget. */ - Unit getUnit() const; + Unit const * getUnit() const; /** * Returns the abbreviated unit name of the selected unit. @@ -127,10 +127,7 @@ public: */ bool isRadial() const; - UnitTable &getUnitTable() {return _unit_table;} - protected: - UnitTable _unit_table; UnitType _type; }; diff --git a/src/ui/widget/unit-tracker.cpp b/src/ui/widget/unit-tracker.cpp new file mode 100644 index 000000000..67eb1f48d --- /dev/null +++ b/src/ui/widget/unit-tracker.cpp @@ -0,0 +1,264 @@ +/* + * Inkscape::UI::Widget::UnitTracker + * Simple mediator to synchronize changes to unit menus + * + * Authors: + * Jon A. Cruz <jon@joncruz.org> + * Matthew Petroff <matthew@mpetroff.net> + * + * Copyright (C) 2007 Jon A. Cruz + * Copyright (C) 2013 Matthew Petroff + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "unit-tracker.h" +#include "ege-select-one-action.h" + +#define COLUMN_STRING 0 + +using Inkscape::Util::UnitTable; +using Inkscape::Util::unit_table; + +namespace Inkscape { +namespace UI { +namespace Widget { + +UnitTracker::UnitTracker(UnitType unit_type) : + _active(0), + _isUpdating(false), + _activeUnit(NULL), + _activeUnitInitialized(false), + _store(0), + _unitList(0), + _actionList(0), + _adjList(0), + _priorValues() +{ + _store = gtk_list_store_new(1, G_TYPE_STRING); + + GtkTreeIter iter; + UnitTable::UnitMap m = unit_table.units(unit_type); + + + for (UnitTable::UnitMap::iterator m_iter = m.begin(); m_iter != m.end(); ++m_iter) { + Glib::ustring text = m_iter->first; + gtk_list_store_append(_store, &iter); + gtk_list_store_set(_store, &iter, COLUMN_STRING, text.c_str(), -1); + } + gint count = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(_store), 0); + if ((count > 0) && (_active > count)) { + _setActive(--count); + } else { + _setActive(_active); + } +} + +UnitTracker::~UnitTracker() +{ + // Unhook weak references to GtkActions + while (_actionList) { + g_signal_handlers_disconnect_by_func(G_OBJECT(_actionList->data), (gpointer) _unitChangedCB, this); + g_object_weak_unref(G_OBJECT(_actionList->data), _actionFinalizedCB, this); + _actionList = g_slist_delete_link(_actionList, _actionList); + } + + // Unhook weak references to GtkAdjustments + while (_adjList) { + g_object_weak_unref(G_OBJECT(_adjList->data), _adjustmentFinalizedCB, this); + _adjList = g_slist_delete_link(_adjList, _adjList); + } +} + +bool UnitTracker::isUpdating() const +{ + return _isUpdating; +} + +Inkscape::Util::Unit const * UnitTracker::getActiveUnit() const +{ + return _activeUnit; +} + +void UnitTracker::setActiveUnit(Inkscape::Util::Unit const *unit) +{ + if (unit) { + GtkTreeIter iter; + int index = 0; + gboolean found = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(_store), &iter); + while (found) { + gchar *storedUnit = 0; + gtk_tree_model_get(GTK_TREE_MODEL(_store), &iter, COLUMN_STRING, &storedUnit, -1); + if (storedUnit && (!unit->abbr.compare(storedUnit))) { + _setActive(index); + break; + } + + found = gtk_tree_model_iter_next(GTK_TREE_MODEL(_store), &iter); + index++; + } + } +} + +void UnitTracker::setActiveUnitByAbbr(gchar const *abbr) +{ + Inkscape::Util::Unit const *u = unit_table.getUnit(abbr); + setActiveUnit(u); +} + +void UnitTracker::addAdjustment(GtkAdjustment *adj) +{ + if (!g_slist_find(_adjList, adj)) { + g_object_weak_ref(G_OBJECT(adj), _adjustmentFinalizedCB, this); + _adjList = g_slist_append(_adjList, adj); + } +} + +void UnitTracker::addUnit(Inkscape::Util::Unit const *u) +{ + GtkTreeIter iter; + gtk_list_store_append(_store, &iter); + gtk_list_store_set(_store, &iter, COLUMN_STRING, u ? u->abbr.c_str() : "NULL", -1); +} + +void UnitTracker::setFullVal(GtkAdjustment *adj, gdouble val) +{ + _priorValues[adj] = val; +} + +GtkAction *UnitTracker::createAction(gchar const *name, gchar const *label, gchar const *tooltip) +{ + EgeSelectOneAction *act1 = ege_select_one_action_new(name, label, tooltip, NULL, GTK_TREE_MODEL(_store)); + ege_select_one_action_set_label_column(act1, COLUMN_STRING); + if (_active) { + ege_select_one_action_set_active(act1, _active); + } + + ege_select_one_action_set_appearance(act1, "minimal"); + g_object_weak_ref(G_OBJECT(act1), _actionFinalizedCB, this); + g_signal_connect(G_OBJECT(act1), "changed", G_CALLBACK(_unitChangedCB), this); + _actionList = g_slist_append(_actionList, act1); + + return GTK_ACTION(act1); +} + +void UnitTracker::_unitChangedCB(GtkAction *action, gpointer data) +{ + if (action && data) { + EgeSelectOneAction *act = EGE_SELECT_ONE_ACTION(action); + gint active = ege_select_one_action_get_active(act); + UnitTracker *self = reinterpret_cast<UnitTracker *>(data); + self->_setActive(active); + } +} + +void UnitTracker::_actionFinalizedCB(gpointer data, GObject *where_the_object_was) +{ + if (data && where_the_object_was) { + UnitTracker *self = reinterpret_cast<UnitTracker *>(data); + self->_actionFinalized(where_the_object_was); + } +} + +void UnitTracker::_adjustmentFinalizedCB(gpointer data, GObject *where_the_object_was) +{ + if (data && where_the_object_was) { + UnitTracker *self = reinterpret_cast<UnitTracker *>(data); + self->_adjustmentFinalized(where_the_object_was); + } +} + +void UnitTracker::_actionFinalized(GObject *where_the_object_was) +{ + GSList *target = g_slist_find(_actionList, where_the_object_was); + if (target) { + _actionList = g_slist_remove(_actionList, where_the_object_was); + } else { + g_warning("Received a finalization callback for unknown object %p", where_the_object_was); + } +} + +void UnitTracker::_adjustmentFinalized(GObject *where_the_object_was) +{ + GSList *target = g_slist_find(_adjList, where_the_object_was); + if (target) { + _adjList = g_slist_remove(_adjList, where_the_object_was); + } else { + g_warning("Received a finalization callback for unknown object %p", where_the_object_was); + } +} + +void UnitTracker::_setActive(gint active) +{ + if ( active != _active || !_activeUnitInitialized ) { + gint oldActive = _active; + + GtkTreeIter iter; + gboolean found = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(_store), &iter, NULL, oldActive); + if (found) { + gchar *abbr; + gtk_tree_model_get(GTK_TREE_MODEL(_store), &iter, COLUMN_STRING, &abbr, -1); + Inkscape::Util::Unit const *unit = unit_table.getUnit(abbr); + + found = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(_store), &iter, NULL, active); + if (found) { + gchar *newAbbr; + gtk_tree_model_get(GTK_TREE_MODEL(_store), &iter, COLUMN_STRING, &newAbbr, -1); + Inkscape::Util::Unit const *newUnit = unit_table.getUnit(newAbbr); + _activeUnit = newUnit; + + if (_adjList) { + _fixupAdjustments(unit, newUnit); + } + + } else { + g_warning("Did not find new unit"); + } + } else { + g_warning("Did not find old unit"); + } + + _active = active; + + for ( GSList *cur = _actionList ; cur ; cur = g_slist_next(cur) ) { + if (IS_EGE_SELECT_ONE_ACTION(cur->data)) { + EgeSelectOneAction *act = EGE_SELECT_ONE_ACTION(cur->data); + ege_select_one_action_set_active(act, active); + } + } + + _activeUnitInitialized = true; + } +} + +void UnitTracker::_fixupAdjustments(Inkscape::Util::Unit const *oldUnit, Inkscape::Util::Unit const *newUnit) +{ + _isUpdating = true; + for ( GSList *cur = _adjList ; cur ; cur = g_slist_next(cur) ) { + GtkAdjustment *adj = GTK_ADJUSTMENT(cur->data); + gdouble oldVal = gtk_adjustment_get_value(adj); + gdouble val = oldVal; + + if ( (oldUnit->type != Inkscape::Util::UNIT_TYPE_DIMENSIONLESS) + && (newUnit->type == Inkscape::Util::UNIT_TYPE_DIMENSIONLESS) ) + { + val = newUnit->factor * 100; + _priorValues[adj] = Inkscape::Util::Quantity::convert(oldVal, oldUnit, "px"); + } else if ( (oldUnit->type == Inkscape::Util::UNIT_TYPE_DIMENSIONLESS) + && (newUnit->type != Inkscape::Util::UNIT_TYPE_DIMENSIONLESS) ) + { + if (_priorValues.find(adj) != _priorValues.end()) { + val = Inkscape::Util::Quantity::convert(_priorValues[adj], "px", newUnit); + } + } else { + val = Inkscape::Util::Quantity::convert(oldVal, oldUnit, newUnit); + } + + gtk_adjustment_set_value(adj, val); + } + _isUpdating = false; +} + +} // namespace Widget +} // namespace UI +} // namespace Inkscape diff --git a/src/ui/widget/unit-tracker.h b/src/ui/widget/unit-tracker.h new file mode 100644 index 000000000..61bb556ef --- /dev/null +++ b/src/ui/widget/unit-tracker.h @@ -0,0 +1,74 @@ +/* + * Inkscape::UI::Widget::UnitTracker + * Simple mediator to synchronize changes to unit menus + * + * Authors: + * Jon A. Cruz <jon@joncruz.org> + * Matthew Petroff <matthew@mpetroff.net> + * + * Copyright (C) 2007 Jon A. Cruz + * Copyright (C) 2013 Matthew Petroff + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef INKSCAPE_UI_WIDGET_UNIT_TRACKER_H +#define INKSCAPE_UI_WIDGET_UNIT_TRACKER_H + +#include <map> +#include <gtk/gtk.h> + +#include "util/units.h" + +using Inkscape::Util::Unit; +using Inkscape::Util::UnitType; + +namespace Inkscape { +namespace UI { +namespace Widget { + +class UnitTracker { +public: + UnitTracker(UnitType unit_type); + virtual ~UnitTracker(); + + bool isUpdating() const; + + void setActiveUnit(Inkscape::Util::Unit const *unit); + void setActiveUnitByAbbr(gchar const *abbr); + Inkscape::Util::Unit const * getActiveUnit() const; + + void addUnit(Inkscape::Util::Unit const *u); + void addAdjustment(GtkAdjustment *adj); + void setFullVal(GtkAdjustment *adj, gdouble val); + + GtkAction *createAction(gchar const *name, gchar const *label, gchar const *tooltip); + +protected: + UnitType _type; + +private: + static void _unitChangedCB(GtkAction *action, gpointer data); + static void _actionFinalizedCB(gpointer data, GObject *where_the_object_was); + static void _adjustmentFinalizedCB(gpointer data, GObject *where_the_object_was); + void _setActive(gint index); + void _fixupAdjustments(Inkscape::Util::Unit const *oldUnit, Inkscape::Util::Unit const *newUnit); + void _actionFinalized(GObject *where_the_object_was); + void _adjustmentFinalized(GObject *where_the_object_was); + + gint _active; + bool _isUpdating; + Inkscape::Util::Unit const *_activeUnit; + bool _activeUnitInitialized; + GtkListStore *_store; + GSList *_unitList; + GSList *_actionList; + GSList *_adjList; + std::map <GtkAdjustment *, gdouble> _priorValues; +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_UNIT_TRACKER_H |
