diff options
| author | su_v <suv-sf@users.sourceforge.net> | 2012-12-16 05:41:25 +0000 |
|---|---|---|
| committer | ~suv <suv-sf@users.sourceforge.net> | 2012-12-16 05:41:25 +0000 |
| commit | 7ec903c9898f872dbd9426ed7a62e1969fdb7be7 (patch) | |
| tree | a306139e829118a83516af02279c9eafd3440eaa /src/ui | |
| parent | Hershey Text: whitespace; py: docstring, modeline; inx: fix attribute value (diff) | |
| parent | Translations.Spanish translation update by Lucas Vieites. (diff) | |
| download | inkscape-7ec903c9898f872dbd9426ed7a62e1969fdb7be7.tar.gz inkscape-7ec903c9898f872dbd9426ed7a62e1969fdb7be7.zip | |
merge from trunk (r11955)
(bzr r11687.1.3)
Diffstat (limited to 'src/ui')
88 files changed, 4776 insertions, 899 deletions
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index b3bcb3fdd..8fd8eb4e3 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -42,6 +42,7 @@ set(ui_SRC dialog/filter-effects-dialog.cpp dialog/find.cpp dialog/floating-behavior.cpp + dialog/font-substitution.cpp dialog/glyphs.cpp dialog/guides.cpp dialog/icon-preview.cpp @@ -59,6 +60,7 @@ set(ui_SRC 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 @@ -82,6 +84,7 @@ set(ui_SRC widget/entry.cpp widget/filter-effect-chooser.cpp widget/frame.cpp + widget/gimpspinscale.c widget/imageicon.cpp widget/imagetoggler.cpp widget/labelled.cpp @@ -101,6 +104,7 @@ set(ui_SRC widget/scalar-unit.cpp widget/scalar.cpp widget/selected-style.cpp + widget/spin-scale.cpp widget/spin-slider.cpp widget/spinbutton.cpp widget/style-subject.cpp @@ -117,6 +121,7 @@ set(ui_SRC # Headers clipboard.h control-manager.h + control-types.h icon-names.h previewable.h previewfillable.h @@ -148,6 +153,7 @@ set(ui_SRC dialog/filter-effects-dialog.h dialog/find.h dialog/floating-behavior.h + dialog/font-substitution.h dialog/glyphs.h dialog/guides.h dialog/icon-preview.h @@ -169,6 +175,7 @@ set(ui_SRC dialog/spellcheck.h dialog/svg-fonts-dialog.h dialog/swatches.h + dialog/symbols.h dialog/text-edit.h dialog/tile.h dialog/tracedialog.h @@ -204,6 +211,7 @@ set(ui_SRC widget/entry.h widget/filter-effect-chooser.h widget/frame.h + widget/gimpspinscale.h widget/imageicon.h widget/imagetoggler.h widget/labelled.h @@ -224,6 +232,7 @@ set(ui_SRC widget/scalar-unit.h widget/scalar.h widget/selected-style.h + widget/spin-scale.h widget/spin-slider.h widget/spinbutton.h widget/style-subject.h diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index f1f6c4ab4..8cdb37f4f 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -7,9 +7,11 @@ * Jon A. Cruz <jon@joncruz.org> * Incorporates some code from selection-chemistry.cpp, see that file for more credits. * Abhishek Sharma + * Tavmjong Bah * * Copyright (C) 2008 authors * Copyright (C) 2010 Jon A. Cruz + * Copyright (C) 2012 Tavmjong Bah (Symbol additions) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -66,6 +68,8 @@ #include "sp-mask.h" #include "sp-textpath.h" #include "sp-rect.h" +#include "sp-use.h" +#include "sp-symbol.h" #include "live_effects/lpeobject.h" #include "live_effects/lpeobject-reference.h" #include "live_effects/parameter/path.h" @@ -109,6 +113,7 @@ class ClipboardManagerImpl : public ClipboardManager { public: virtual void copy(SPDesktop *desktop); virtual void copyPathParameter(Inkscape::LivePathEffect::PathParam *); + virtual void copySymbol(Inkscape::XML::Node* symbol, gchar const* style); virtual bool paste(SPDesktop *desktop, bool in_place); virtual bool pasteStyle(SPDesktop *desktop); virtual bool pasteSize(SPDesktop *desktop, bool separately, bool apply_x, bool apply_y); @@ -295,6 +300,43 @@ void ClipboardManagerImpl::copyPathParameter(Inkscape::LivePathEffect::PathParam } /** + * Copy a symbol from the symbol dialog. + * @param symbol The Inkscape::XML::Node for the symbol. + */ +void ClipboardManagerImpl::copySymbol(Inkscape::XML::Node* symbol, gchar const* style) +{ + //std::cout << "ClipboardManagerImpl::copySymbol" << std::endl; + if ( symbol == NULL ) { + return; + } + + _discardInternalClipboard(); + _createInternalClipboard(); + + // We add "_duplicate" to have a well defined symbol name that + // bypasses the "prevent_id_classes" routine. We'll get rid of it + // when we paste. + Inkscape::XML::Node *repr = symbol->duplicate(_doc); + Glib::ustring symbol_name = repr->attribute("id"); + + symbol_name += "_inkscape_duplicate"; + repr->setAttribute("id", symbol_name.c_str()); + _defs->appendChild(repr); + + Glib::ustring id("#"); + id += symbol->attribute("id"); + + Inkscape::XML::Node *use = _doc->createElement("svg:use"); + use->setAttribute("xlink:href", id.c_str() ); + // Set a default style in <use> rather than <symbol> so it can be changed. + use->setAttribute("style", style ); + _root->appendChild(use); + + fit_canvas_to_drawing(_clipboardSPDoc); + _setClipboardTargets(); +} + +/** * Paste from the system clipboard into the active desktop. * @param in_place Whether to put the contents where they were when copied. */ @@ -725,6 +767,14 @@ void ClipboardManagerImpl::_copyUsedDefs(SPItem *item) } } + // Copy symbols: We may want to be more clever... + // if (SP_IS_USE(item)) { + // SPObject *symbol = SP_USE(item)->child; + // if( symbol && SP_IS_SYMBOL(symbol) ) { + // _copyNode(symbol->getRepr(), _doc, _defs); + // } + // } + // recurse for (SPObject *o = item->children ; o != NULL ; o = o->next) { if (SP_IS_ITEM(o)) { diff --git a/src/ui/clipboard.h b/src/ui/clipboard.h index fb28bfc14..b565740c3 100644 --- a/src/ui/clipboard.h +++ b/src/ui/clipboard.h @@ -25,6 +25,7 @@ class SPDesktop; namespace Inkscape { class Selection; +namespace XML { class Node; } namespace LivePathEffect { class PathParam; } namespace UI { @@ -43,6 +44,7 @@ class ClipboardManager { public: virtual void copy(SPDesktop *desktop) = 0; virtual void copyPathParameter(Inkscape::LivePathEffect::PathParam *) = 0; + virtual void copySymbol(Inkscape::XML::Node* symbol, gchar const* style) = 0; virtual bool paste(SPDesktop *desktop, bool in_place = false) = 0; virtual bool pasteStyle(SPDesktop *desktop) = 0; virtual bool pasteSize(SPDesktop *desktop, bool separately, bool apply_x, bool apply_y) = 0; diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index ba2f53a9e..580b47522 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -89,6 +89,8 @@ ink_common_sources += \ ui/dialog/svg-fonts-dialog.h \ ui/dialog/swatches.cpp \ ui/dialog/swatches.h \ + ui/dialog/symbols.cpp \ + ui/dialog/symbols.h \ ui/dialog/text-edit.cpp \ ui/dialog/text-edit.h \ ui/dialog/tile.cpp \ diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp index 67980cdc1..dbd06d9e8 100644 --- a/src/ui/dialog/align-and-distribute.cpp +++ b/src/ui/dialog/align-and-distribute.cpp @@ -755,7 +755,7 @@ struct Baselines {} }; -bool operator< (const Baselines &a, const Baselines &b) +static bool operator< (const Baselines &a, const Baselines &b) { return (a._base[a._orientation] < b._base[b._orientation]); } @@ -873,14 +873,14 @@ private : -void on_tool_changed(Inkscape::Application */*inkscape*/, SPEventContext */*context*/, AlignAndDistribute *daad) +static void on_tool_changed(Inkscape::Application */*inkscape*/, SPEventContext */*context*/, AlignAndDistribute *daad) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (desktop && sp_desktop_event_context(desktop)) daad->setMode(tools_active(desktop) == TOOLS_NODES); } -void on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, AlignAndDistribute *daad) +static void on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, AlignAndDistribute *daad) { daad->randomize_bbox = Geom::OptRect(); } @@ -1040,7 +1040,6 @@ AlignAndDistribute::AlignAndDistribute() //Rest of the widgetry -#if WITH_GTKMM_2_24 _combo.append(_("Last selected")); _combo.append(_("First selected")); _combo.append(_("Biggest object")); @@ -1048,15 +1047,6 @@ AlignAndDistribute::AlignAndDistribute() _combo.append(_("Page")); _combo.append(_("Drawing")); _combo.append(_("Selection")); -#else - _combo.append_text(_("Last selected")); - _combo.append_text(_("First selected")); - _combo.append_text(_("Biggest object")); - _combo.append_text(_("Smallest object")); - _combo.append_text(_("Page")); - _combo.append_text(_("Drawing")); - _combo.append_text(_("Selection")); -#endif _combo.set_active(prefs->getInt("/dialogs/align/align-to", 6)); _combo.signal_changed().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_ref_change)); @@ -1154,21 +1144,12 @@ void AlignAndDistribute::on_selgrp_toggled(){ void AlignAndDistribute::setMode(bool nodeEdit) { //Act on widgets used in node mode -#if WITH_GTKMM_2_24 void ( Gtk::Widget::*mNode) () = nodeEdit ? &Gtk::Widget::show_all : &Gtk::Widget::hide; //Act on widgets used in selection mode void ( Gtk::Widget::*mSel) () = nodeEdit ? &Gtk::Widget::hide : &Gtk::Widget::show_all; -#else - void ( Gtk::Widget::*mNode) () = nodeEdit ? - &Gtk::Widget::show_all : &Gtk::Widget::hide_all; - - //Act on widgets used in selection mode - void ( Gtk::Widget::*mSel) () = nodeEdit ? - &Gtk::Widget::hide_all : &Gtk::Widget::show_all; -#endif ((_alignFrame).*(mSel))(); ((_distributeFrame).*(mSel))(); @@ -1314,7 +1295,6 @@ std::list<SPItem *>::iterator AlignAndDistribute::find_master( std::list<SPItem } } return master; - break; } case SMALLEST: @@ -1331,7 +1311,6 @@ std::list<SPItem *>::iterator AlignAndDistribute::find_master( std::list<SPItem } } return master; - break; } default: diff --git a/src/ui/dialog/align-and-distribute.h b/src/ui/dialog/align-and-distribute.h index 969703807..c9165a83e 100644 --- a/src/ui/dialog/align-and-distribute.h +++ b/src/ui/dialog/align-and-distribute.h @@ -213,7 +213,7 @@ private : SPDesktop *desktop = _dialog.getDesktop(); if (!desktop) return; - ActionAlign::do_action(desktop, _index); + do_action(desktop, _index); } static void do_action(SPDesktop *desktop, int index); diff --git a/src/ui/dialog/calligraphic-profile-rename.cpp b/src/ui/dialog/calligraphic-profile-rename.cpp index c6633df0b..77a4f4f03 100644 --- a/src/ui/dialog/calligraphic-profile-rename.cpp +++ b/src/ui/dialog/calligraphic-profile-rename.cpp @@ -30,6 +30,8 @@ namespace Dialog { CalligraphicProfileRename::CalligraphicProfileRename() : _applied(false) { + set_title(_("Edit profile")); + Gtk::Box *mainVBox = get_vbox(); _layout_table.set_spacings(4); _layout_table.resize (1, 2); @@ -49,19 +51,27 @@ CalligraphicProfileRename::CalligraphicProfileRename() : _close_button.set_label(Gtk::Stock::CANCEL.id); _close_button.set_can_default(); + _delete_button.set_use_underline(true); + _delete_button.set_label(_("Delete")); + _delete_button.set_can_default(); + _delete_button.set_visible(false); + _apply_button.set_use_underline(true); _apply_button.set_label(_("Save")); _apply_button.set_can_default(); _close_button.signal_clicked() - .connect(sigc::mem_fun(*this, &CalligraphicProfileRename::_close)); + .connect(sigc::mem_fun(*this, &CalligraphicProfileRename::_close)); + _delete_button.signal_clicked() + .connect(sigc::mem_fun(*this, &CalligraphicProfileRename::_delete)); _apply_button.signal_clicked() - .connect(sigc::mem_fun(*this, &CalligraphicProfileRename::_apply)); + .connect(sigc::mem_fun(*this, &CalligraphicProfileRename::_apply)); signal_delete_event().connect( sigc::bind_return( sigc::hide(sigc::mem_fun(*this, &CalligraphicProfileRename::_close)), true ) ); add_action_widget(_close_button, Gtk::RESPONSE_CLOSE); + add_action_widget(_delete_button, Gtk::RESPONSE_DELETE_EVENT); add_action_widget(_apply_button, Gtk::RESPONSE_APPLY); _apply_button.grab_default(); @@ -73,6 +83,15 @@ void CalligraphicProfileRename::_apply() { _profile_name = _profile_name_entry.get_text(); _applied = true; + _deleted = false; + _close(); +} + +void CalligraphicProfileRename::_delete() +{ + _profile_name = _profile_name_entry.get_text(); + _applied = true; + _deleted = true; _close(); } @@ -81,11 +100,25 @@ void CalligraphicProfileRename::_close() this->Gtk::Dialog::hide(); } -void CalligraphicProfileRename::show(SPDesktop *desktop) +void CalligraphicProfileRename::show(SPDesktop *desktop, const Glib::ustring profile_name) { CalligraphicProfileRename &dial = instance(); dial._applied=false; + dial._deleted=false; dial.set_modal(true); + + dial._profile_name = profile_name; + dial._profile_name_entry.set_text(profile_name); + + if (profile_name.empty()) { + dial.set_title(_("Add profile")); + dial._delete_button.set_visible(false); + + } else { + dial.set_title(_("Edit profile")); + dial._delete_button.set_visible(true); + } + desktop->setWindowTransient (dial.gobj()); dial.property_destroy_with_parent() = true; // dial.Gtk::Dialog::show(); diff --git a/src/ui/dialog/calligraphic-profile-rename.h b/src/ui/dialog/calligraphic-profile-rename.h index f0eb0b491..8fe82d7bb 100644 --- a/src/ui/dialog/calligraphic-profile-rename.h +++ b/src/ui/dialog/calligraphic-profile-rename.h @@ -29,10 +29,13 @@ public: return "CalligraphicProfileRename"; } - static void show(SPDesktop *desktop); + static void show(SPDesktop *desktop, const Glib::ustring profile_name); static bool applied() { return instance()._applied; } + static bool deleted() { + return instance()._deleted; + } static Glib::ustring getProfileName() { return instance()._profile_name; } @@ -40,14 +43,17 @@ public: protected: void _close(); void _apply(); + void _delete(); Gtk::Label _profile_name_label; Gtk::Entry _profile_name_entry; Gtk::Table _layout_table; Gtk::Button _close_button; + Gtk::Button _delete_button; Gtk::Button _apply_button; Glib::ustring _profile_name; bool _applied; + bool _deleted; private: static CalligraphicProfileRename &instance() { static CalligraphicProfileRename instance_; diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp index 47ec03b30..e971cfb09 100644 --- a/src/ui/dialog/clonetiler.cpp +++ b/src/ui/dialog/clonetiler.cpp @@ -815,9 +815,15 @@ CloneTiler::CloneTiler (void) : GtkWidget *frame = gtk_frame_new (_("1. Pick from the drawing:")); gtk_box_pack_start (GTK_BOX (vvb), frame, FALSE, FALSE, 0); +#if GTK_CHECK_VERSION(3,0,0) + GtkWidget *table = gtk_grid_new(); + gtk_grid_set_row_spacing(GTK_GRID(table), 4); + gtk_grid_set_column_spacing(GTK_GRID(table), 6); +#else GtkWidget *table = gtk_table_new (3, 3, FALSE); gtk_table_set_row_spacings (GTK_TABLE (table), 4); gtk_table_set_col_spacings (GTK_TABLE (table), 6); +#endif gtk_container_add(GTK_CONTAINER(frame), table); @@ -893,9 +899,16 @@ CloneTiler::CloneTiler (void) : GtkWidget *frame = gtk_frame_new (_("2. Tweak the picked value:")); gtk_box_pack_start (GTK_BOX (vvb), frame, FALSE, FALSE, VB_MARGIN); +#if GTK_CHECK_VERSION(3,0,0) + GtkWidget *table = gtk_grid_new(); + gtk_grid_set_row_spacing(GTK_GRID(table), 4); + gtk_grid_set_column_spacing(GTK_GRID(table), 6); +#else GtkWidget *table = gtk_table_new (4, 2, FALSE); gtk_table_set_row_spacings (GTK_TABLE (table), 4); gtk_table_set_col_spacings (GTK_TABLE (table), 6); +#endif + gtk_container_add(GTK_CONTAINER(frame), table); { @@ -935,10 +948,15 @@ CloneTiler::CloneTiler (void) : GtkWidget *frame = gtk_frame_new (_("3. Apply the value to the clones':")); gtk_box_pack_start (GTK_BOX (vvb), frame, FALSE, FALSE, 0); - +#if GTK_CHECK_VERSION(3,0,0) + GtkWidget *table = gtk_grid_new(); + gtk_grid_set_row_spacing(GTK_GRID(table), 4); + gtk_grid_set_column_spacing(GTK_GRID(table), 6); +#else GtkWidget *table = gtk_table_new (2, 2, FALSE); gtk_table_set_row_spacings (GTK_TABLE (table), 4); gtk_table_set_col_spacings (GTK_TABLE (table), 6); +#endif gtk_container_add(GTK_CONTAINER(frame), table); { @@ -987,10 +1005,17 @@ CloneTiler::CloneTiler (void) : // Rows/columns, width/height { +#if GTK_CHECK_VERSION(3,0,0) + GtkWidget *table = gtk_grid_new(); + gtk_grid_set_row_spacing(GTK_GRID(table), 4); + gtk_grid_set_column_spacing(GTK_GRID(table), 6); +#else GtkWidget *table = gtk_table_new (2, 2, FALSE); - gtk_container_set_border_width (GTK_CONTAINER (table), VB_MARGIN); gtk_table_set_row_spacings (GTK_TABLE (table), 4); gtk_table_set_col_spacings (GTK_TABLE (table), 6); +#endif + + gtk_container_set_border_width (GTK_CONTAINER (table), VB_MARGIN); gtk_box_pack_start (GTK_BOX (mainbox), table, FALSE, FALSE, 0); { @@ -1326,8 +1351,8 @@ void CloneTiler::on_picker_color_changed(guint rgba) void CloneTiler::clonetiler_change_selection(Inkscape::Application * /*inkscape*/, Inkscape::Selection *selection, GtkWidget *dlg) { - GtkWidget *buttons = (GtkWidget *) g_object_get_data (G_OBJECT(dlg), "buttons_on_tiles"); - GtkWidget *status = (GtkWidget *) g_object_get_data (G_OBJECT(dlg), "status"); + GtkWidget *buttons = GTK_WIDGET(g_object_get_data (G_OBJECT(dlg), "buttons_on_tiles")); + GtkWidget *status = GTK_WIDGET(g_object_get_data (G_OBJECT(dlg), "status")); if (selection->isEmpty()) { gtk_widget_set_sensitive (buttons, FALSE); @@ -2204,7 +2229,7 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg) desktop->setWaitingCursor(); // set statusbar text - GtkWidget *status = (GtkWidget *) g_object_get_data (G_OBJECT(dlg), "status"); + GtkWidget *status = GTK_WIDGET(g_object_get_data (G_OBJECT(dlg), "status")); gtk_label_set_markup (GTK_LABEL(status), _("<small>Creating tiled clones...</small>")); gtk_widget_queue_draw(GTK_WIDGET(status)); gdk_window_process_all_updates(); @@ -2807,15 +2832,29 @@ void CloneTiler::clonetiler_table_attach(GtkWidget *table, GtkWidget *widget, fl { GtkWidget *a = gtk_alignment_new (align, 0, 0, 0); gtk_container_add(GTK_CONTAINER(a), widget); - gtk_table_attach ( GTK_TABLE (table), a, col, col + 1, row, row + 1, (GtkAttachOptions)4, (GtkAttachOptions)0, 0, 0 ); + +#if GTK_CHECK_VERSION(3,0,0) + gtk_widget_set_halign(table, GTK_ALIGN_FILL); + gtk_widget_set_valign(table, GTK_ALIGN_CENTER); + gtk_grid_attach(GTK_GRID(table), a, col, row, 1, 1); +#else + gtk_table_attach ( GTK_TABLE (table), a, col, col + 1, row, row + 1, GTK_FILL, (GtkAttachOptions)0, 0, 0 ); +#endif } GtkWidget * CloneTiler::clonetiler_table_x_y_rand(int values) { +#if GTK_CHECK_VERSION(3,0,0) + GtkWidget *table = gtk_grid_new(); + gtk_grid_set_row_spacing(GTK_GRID(table), 6); + gtk_grid_set_column_spacing(GTK_GRID(table), 8); +#else GtkWidget *table = gtk_table_new (values + 2, 5, FALSE); - gtk_container_set_border_width (GTK_CONTAINER (table), VB_MARGIN); gtk_table_set_row_spacings (GTK_TABLE (table), 6); gtk_table_set_col_spacings (GTK_TABLE (table), 8); +#endif + + gtk_container_set_border_width (GTK_CONTAINER (table), VB_MARGIN); { #if GTK_CHECK_VERSION(3,0,0) @@ -2870,10 +2909,10 @@ void CloneTiler::clonetiler_pick_switched(GtkToggleButton */*tb*/, gpointer data } -void CloneTiler::clonetiler_switch_to_create(GtkToggleButton */*tb*/, GtkWidget *dlg) +void CloneTiler::clonetiler_switch_to_create(GtkToggleButton * /*tb*/, GtkWidget *dlg) { - GtkWidget *rowscols = (GtkWidget *) g_object_get_data (G_OBJECT(dlg), "rowscols"); - GtkWidget *widthheight = (GtkWidget *) g_object_get_data (G_OBJECT(dlg), "widthheight"); + GtkWidget *rowscols = GTK_WIDGET(g_object_get_data (G_OBJECT(dlg), "rowscols")); + GtkWidget *widthheight = GTK_WIDGET(g_object_get_data (G_OBJECT(dlg), "widthheight")); if (rowscols) { gtk_widget_set_sensitive (rowscols, TRUE); @@ -2887,10 +2926,10 @@ void CloneTiler::clonetiler_switch_to_create(GtkToggleButton */*tb*/, GtkWidget } -void CloneTiler::clonetiler_switch_to_fill(GtkToggleButton */*tb*/, GtkWidget *dlg) +void CloneTiler::clonetiler_switch_to_fill(GtkToggleButton * /*tb*/, GtkWidget *dlg) { - GtkWidget *rowscols = (GtkWidget *) g_object_get_data (G_OBJECT(dlg), "rowscols"); - GtkWidget *widthheight = (GtkWidget *) g_object_get_data (G_OBJECT(dlg), "widthheight"); + GtkWidget *rowscols = GTK_WIDGET(g_object_get_data (G_OBJECT(dlg), "rowscols")); + GtkWidget *widthheight = GTK_WIDGET(g_object_get_data (G_OBJECT(dlg), "widthheight")); if (rowscols) { gtk_widget_set_sensitive (rowscols, FALSE); @@ -2929,7 +2968,7 @@ void CloneTiler::clonetiler_fill_height_changed(GtkAdjustment *adj, GtkWidget *u void CloneTiler::clonetiler_do_pick_toggled(GtkToggleButton *tb, GtkWidget *dlg) { - GtkWidget *vvb = (GtkWidget *) g_object_get_data (G_OBJECT(dlg), "dotrace"); + GtkWidget *vvb = GTK_WIDGET(g_object_get_data (G_OBJECT(dlg), "dotrace")); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setBool(prefs_path + "dotrace", gtk_toggle_button_get_active (tb)); diff --git a/src/ui/dialog/color-item.cpp b/src/ui/dialog/color-item.cpp index b0da4aecc..e370a0342 100644 --- a/src/ui/dialog/color-item.cpp +++ b/src/ui/dialog/color-item.cpp @@ -35,6 +35,7 @@ #include "xml/node.h" #include "xml/repr.h" #include "verbs.h" +#include "widgets/gradient-vector.h" #include "color.h" // for SP_RGBA32_U_COMPOSE @@ -143,7 +144,7 @@ static void dieDieDie( GObject *obj, gpointer user_data ) g_message("die die die %p %p", obj, user_data ); } -static bool getBlock( std::string& dst, guchar ch, std::string const str ) +static bool getBlock( std::string& dst, guchar ch, std::string const & str ) { bool good = false; std::string::size_type pos = str.find(ch); @@ -355,6 +356,23 @@ void ColorItem::setGradient(SPGradient *grad) _grad = grad; // TODO regen and push to listeners } + + setName( gr_prepare_label(_grad) ); +} + +void ColorItem::setName(const Glib::ustring name) +{ + //def.descr = name; + + for ( std::vector<Gtk::Widget*>::iterator it = _previews.begin(); it != _previews.end(); ++it ) { + Gtk::Widget* widget = *it; + if ( IS_EEK_PREVIEW(widget->gobj()) ) { + gtk_widget_set_tooltip_text(GTK_WIDGET(widget->gobj()), name.c_str()); + } + else if ( GTK_IS_LABEL(widget->gobj()) ) { + gtk_label_set_text(GTK_LABEL(widget->gobj()), name.c_str()); + } + } } void ColorItem::setPattern(cairo_pattern_t *pattern) @@ -366,6 +384,7 @@ void ColorItem::setPattern(cairo_pattern_t *pattern) cairo_pattern_destroy(_pattern); } _pattern = pattern; + _updatePreviews(); } @@ -546,7 +565,7 @@ void ColorItem::_regenPreview(EekPreview * preview) | (_isLive ? PREVIEW_LINK_OTHER:0)) ); } -Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewSize size, guint ratio) +Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewSize size, guint ratio, guint border) { Gtk::Widget* widget = 0; if ( style == PREVIEW_STYLE_BLURB) { @@ -565,7 +584,7 @@ Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewS _regenPreview(preview); - eek_preview_set_details( preview, (::PreviewStyle)style, (::ViewType)view, (::PreviewSize)size, ratio ); + eek_preview_set_details( preview, (::PreviewStyle)style, (::ViewType)view, (::PreviewSize)size, ratio, border ); def.addCallback( _colorDefChanged, this ); diff --git a/src/ui/dialog/color-item.h b/src/ui/dialog/color-item.h index e6f5c7b76..3a0b33193 100644 --- a/src/ui/dialog/color-item.h +++ b/src/ui/dialog/color-item.h @@ -53,12 +53,14 @@ public: virtual Gtk::Widget* getPreview(PreviewStyle style, ViewType view, ::PreviewSize size, - guint ratio); + guint ratio, + guint border); void buttonClicked(bool secondary = false); void setGradient(SPGradient *grad); SPGradient * getGradient() const { return _grad; } void setPattern(cairo_pattern_t *pattern); + void setName(const Glib::ustring name); void setState( bool fill, bool stroke ); bool isFill() { return _isFill; } diff --git a/src/ui/dialog/debug.cpp b/src/ui/dialog/debug.cpp index a026f3501..da38e2dde 100644 --- a/src/ui/dialog/debug.cpp +++ b/src/ui/dialog/debug.cpp @@ -171,10 +171,10 @@ void DebugDialog::showInstance() /*##### THIS IS THE IMPORTANT PART ##### */ -void dialogLoggingFunction(const gchar */*log_domain*/, - GLogLevelFlags /*log_level*/, - const gchar *messageText, - gpointer user_data) +static void dialogLoggingFunction(const gchar */*log_domain*/, + GLogLevelFlags /*log_level*/, + const gchar *messageText, + gpointer user_data) { DebugDialogImpl *dlg = static_cast<DebugDialogImpl *>(user_data); dlg->message(messageText); diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 60011ca9d..faba47769 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -33,6 +33,7 @@ #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/transformation.h" @@ -121,6 +122,7 @@ DialogManager::DialogManager() { registerFactory("SvgFontsDialog", &create<SvgFontsDialog, FloatingBehavior>); #endif registerFactory("Swatches", &create<SwatchesPanel, FloatingBehavior>); + registerFactory("Symbols", &create<SymbolsDialog, FloatingBehavior>); registerFactory("TileDialog", &create<TileDialog, FloatingBehavior>); registerFactory("Trace", &create<TraceDialog, FloatingBehavior>); registerFactory("Transformation", &create<Transformation, FloatingBehavior>); @@ -156,6 +158,7 @@ DialogManager::DialogManager() { registerFactory("SvgFontsDialog", &create<SvgFontsDialog, DockBehavior>); #endif registerFactory("Swatches", &create<SwatchesPanel, DockBehavior>); + registerFactory("Symbols", &create<SymbolsDialog, DockBehavior>); registerFactory("TileDialog", &create<TileDialog, DockBehavior>); registerFactory("Trace", &create<TraceDialog, DockBehavior>); registerFactory("Transformation", &create<Transformation, DockBehavior>); diff --git a/src/ui/dialog/dialog.cpp b/src/ui/dialog/dialog.cpp index f5f712103..f27d344fa 100644 --- a/src/ui/dialog/dialog.cpp +++ b/src/ui/dialog/dialog.cpp @@ -61,7 +61,7 @@ void sp_dialog_shutdown(GObject * /*object*/, gpointer dlgPtr) } -void hideCallback(GObject * /*object*/, gpointer dlgPtr) +static void hideCallback(GObject * /*object*/, gpointer dlgPtr) { g_return_if_fail( dlgPtr != NULL ); @@ -69,7 +69,7 @@ void hideCallback(GObject * /*object*/, gpointer dlgPtr) dlg->onHideF12(); } -void unhideCallback(GObject * /*object*/, gpointer dlgPtr) +static void unhideCallback(GObject * /*object*/, gpointer dlgPtr) { g_return_if_fail( dlgPtr != NULL ); diff --git a/src/ui/dialog/document-metadata.cpp b/src/ui/dialog/document-metadata.cpp index 6318ffbbb..efe25d843 100644 --- a/src/ui/dialog/document-metadata.cpp +++ b/src/ui/dialog/document-metadata.cpp @@ -61,13 +61,30 @@ DocumentMetadata::getInstance() DocumentMetadata::DocumentMetadata() +#if WITH_GTKMM_3_0 + : UI::Widget::Panel ("", "/dialogs/documentmetadata", SP_VERB_DIALOG_METADATA) +#else : UI::Widget::Panel ("", "/dialogs/documentmetadata", SP_VERB_DIALOG_METADATA), _page_metadata1(1, 1), _page_metadata2(1, 1) +#endif { hide(); _getContents()->set_spacing (4); _getContents()->pack_start(_notebook, true, true); + _page_metadata1.set_border_width(2); + _page_metadata2.set_border_width(2); + +#if WITH_GTKMM_3_0 + _page_metadata1.set_column_spacing(2); + _page_metadata2.set_column_spacing(2); + _page_metadata1.set_row_spacing(2); + _page_metadata2.set_row_spacing(2); +#else + _page_metadata1.set_spacings(2); + _page_metadata2.set_spacings(2); +#endif + _notebook.append_page(_page_metadata1, _("Metadata")); _notebook.append_page(_page_metadata2, _("License")); @@ -98,50 +115,6 @@ DocumentMetadata::~DocumentMetadata() delete (*it); } -//======================================================================== - -/** - * Helper function that attachs widgets in a 3xn table. The widgets come in an - * array that has two entries per table row. The two entries code for four - * possible cases: (0,0) means insert space in first column; (0, non-0) means - * widget in columns 2-3; (non-0, 0) means label in columns 1-3; and - * (non-0, non-0) means two widgets in columns 2 and 3. - */ -inline void attach_all(Gtk::Table &table, const Gtk::Widget *arr[], unsigned size, int start = 0) -{ - for (unsigned i=0, r=start; i<size/sizeof(Gtk::Widget*); i+=2) - { - if (arr[i] && arr[i+1]) - { - table.attach (const_cast<Gtk::Widget&>(*arr[i]), 1, 2, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); - table.attach (const_cast<Gtk::Widget&>(*arr[i+1]), 2, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); - } - else - { - if (arr[i+1]) - table.attach (const_cast<Gtk::Widget&>(*arr[i+1]), 1, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); - else if (arr[i]) - { - Gtk::Label& label = static_cast<Gtk::Label&> (const_cast<Gtk::Widget&>(*arr[i])); - label.set_alignment (0.0); - table.attach (label, 0, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); - } - else - { - Gtk::HBox *space = manage (new Gtk::HBox); - space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y); - table.attach (*space, 0, 1, r, r+1, - (Gtk::AttachOptions)0, (Gtk::AttachOptions)0,0,0); - } - } - ++r; - } -} - void DocumentMetadata::build_metadata() { @@ -152,7 +125,14 @@ DocumentMetadata::build_metadata() Gtk::Label *label = manage (new Gtk::Label); label->set_markup (_("<b>Dublin Core Entities</b>")); label->set_alignment (0.0); - _page_metadata1.table().attach (*label, 0,3,0,1, Gtk::FILL, (Gtk::AttachOptions)0,0,0); + +#if WITH_GTKMM_3_0 + label->set_valign(Gtk::ALIGN_CENTER); + _page_metadata1.attach(*label, 0, 0, 3, 1); +#else + _page_metadata1.attach(*label, 0,3,0,1, Gtk::FILL, (Gtk::AttachOptions)0,0,0); +#endif + /* add generic metadata entry areas */ struct rdf_work_entity_t * entity; int row = 1; @@ -162,9 +142,22 @@ DocumentMetadata::build_metadata() _rdflist.push_back (w); Gtk::HBox *space = manage (new Gtk::HBox); space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y); - _page_metadata1.table().attach (*space, 0,1, row, row+1, Gtk::FILL, (Gtk::AttachOptions)0,0,0); - _page_metadata1.table().attach (w->_label, 1,2, row, row+1, Gtk::FILL, (Gtk::AttachOptions)0,0,0); - _page_metadata1.table().attach (*w->_packable, 2,3, row, row+1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); + +#if WITH_GTKMM_3_0 + space->set_valign(Gtk::ALIGN_CENTER); + _page_metadata1.attach(*space, 0, row, 1, 1); + + w->_label.set_valign(Gtk::ALIGN_CENTER); + _page_metadata1.attach(w->_label, 1, row, 1, 1); + + w->_packable->set_hexpand(); + w->_packable->set_valign(Gtk::ALIGN_CENTER); + _page_metadata1.attach(*w->_packable, 2, row, 1, 1); +#else + _page_metadata1.attach(*space, 0,1, row, row+1, Gtk::FILL, (Gtk::AttachOptions)0,0,0); + _page_metadata1.attach(w->_label, 1,2, row, row+1, Gtk::FILL, (Gtk::AttachOptions)0,0,0); + _page_metadata1.attach(*w->_packable, 2,3, row, row+1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); +#endif } } @@ -174,14 +167,31 @@ DocumentMetadata::build_metadata() Gtk::Label *llabel = manage (new Gtk::Label); llabel->set_markup (_("<b>License</b>")); llabel->set_alignment (0.0); - _page_metadata2.table().attach (*llabel, 0,3, row, row+1, Gtk::FILL, (Gtk::AttachOptions)0,0,0); + +#if WITH_GTKMM_3_0 + llabel->set_valign(Gtk::ALIGN_CENTER); + _page_metadata2.attach(*llabel, 0, row, 3, 1); +#else + _page_metadata2.attach(*llabel, 0,3, row, row+1, Gtk::FILL, (Gtk::AttachOptions)0,0,0); +#endif + /* add license selector pull-down and URI */ ++row; _licensor.init (_wr); Gtk::HBox *space = manage (new Gtk::HBox); space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y); - _page_metadata2.table().attach (*space, 0,1, row, row+1, Gtk::FILL, (Gtk::AttachOptions)0,0,0); - _page_metadata2.table().attach (_licensor, 1,3, row, row+1, Gtk::EXPAND|Gtk::FILL, (Gtk::AttachOptions)0,0,0); + +#if WITH_GTKMM_3_0 + space->set_valign(Gtk::ALIGN_CENTER); + _page_metadata2.attach(*space, 0, row, 1, 1); + + _licensor.set_hexpand(); + _licensor.set_valign(Gtk::ALIGN_CENTER); + _page_metadata2.attach(_licensor, 1, row, 2, 1); +#else + _page_metadata2.attach(*space, 0,1, row, row+1, Gtk::FILL, (Gtk::AttachOptions)0,0,0); + _page_metadata2.attach(_licensor, 1,3, row, row+1, Gtk::EXPAND|Gtk::FILL, (Gtk::AttachOptions)0,0,0); +#endif } /** diff --git a/src/ui/dialog/document-metadata.h b/src/ui/dialog/document-metadata.h index f201679b5..3b7ed1ec8 100644 --- a/src/ui/dialog/document-metadata.h +++ b/src/ui/dialog/document-metadata.h @@ -13,12 +13,22 @@ #ifndef INKSCAPE_UI_DIALOG_DOCUMENT_METADATA_H #define INKSCAPE_UI_DIALOG_DOCUMENT_METADATA_H +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + #include <list> #include <stddef.h> #include "ui/widget/panel.h" #include <gtkmm/notebook.h> + +#if WITH_GTKMM_3_0 +# include <gtkmm/grid.h> +#else +# include <gtkmm/table.h> +#endif + #include "ui/widget/licensor.h" -#include "ui/widget/notebook-page.h" #include "ui/widget/registry.h" namespace Inkscape { @@ -51,8 +61,13 @@ protected: Gtk::Notebook _notebook; - UI::Widget::NotebookPage _page_metadata1; - UI::Widget::NotebookPage _page_metadata2; +#if WITH_GTKMM_3_0 + Gtk::Grid _page_metadata1; + Gtk::Grid _page_metadata2; +#else + Gtk::Table _page_metadata1; + Gtk::Table _page_metadata2; +#endif //--------------------------------------------------------------- RDElist _rdflist; diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp index c7be0877d..ab1e8fbd8 100644 --- a/src/ui/dialog/document-properties.cpp +++ b/src/ui/dialog/document-properties.cpp @@ -150,6 +150,7 @@ DocumentProperties::DocumentProperties() _notebook.append_page(_page_metadata1, _("Metadata")); _notebook.append_page(_page_metadata2, _("License")); + _wr.setUpdating (true); build_page(); build_guides(); build_gridspage(); @@ -159,6 +160,7 @@ DocumentProperties::DocumentProperties() #endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) build_scripting(); build_metadata(); + _wr.setUpdating (false); _grids_button_new.signal_clicked().connect(sigc::mem_fun(*this, &DocumentProperties::onNewGrid)); _grids_button_remove.signal_clicked().connect(sigc::mem_fun(*this, &DocumentProperties::onRemoveGrid)); @@ -201,41 +203,36 @@ DocumentProperties::~DocumentProperties() * widget in columns 2-3; (non-0, 0) means label in columns 1-3; and * (non-0, non-0) means two widgets in columns 2 and 3. */ -inline void attach_all(Gtk::Table &table, Gtk::Widget *const arr[], unsigned const n, int start = 0) +inline void attach_all(Gtk::Table &table, Gtk::Widget *const arr[], unsigned const n, int start = 0, int docum_prop_flag = 0) { - for (unsigned i = 0, r = start; i < n; i += 2) - { - if (arr[i] && arr[i+1]) - { - table.attach(*arr[i], 1, 2, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); - table.attach(*arr[i+1], 2, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); - } - else - { + for (unsigned i = 0, r = start; i < n; i += 2) { + if (arr[i] && arr[i+1]) { + table.attach(*arr[i], 1, 2, r, r+1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); + table.attach(*arr[i+1], 2, 3, r, r+1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); + } else { if (arr[i+1]) { Gtk::AttachOptions yoptions = (Gtk::AttachOptions)0; if (dynamic_cast<Inkscape::UI::Widget::PageSizer*>(arr[i+1])) { // only the PageSizer in Document Properties|Page should be stretched vertically yoptions = Gtk::FILL|Gtk::EXPAND; } - table.attach(*arr[i+1], 1, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, yoptions, 0,0); - } - else if (arr[i]) - { + if (docum_prop_flag) { + if( i==(n-4) || i==(n-6) ) { + table.attach(*arr[i+1], 1, 3, r, r+1, Gtk::FILL|Gtk::EXPAND, yoptions, 20,0); + } else { + table.attach(*arr[i+1], 1, 3, r, r+1, Gtk::FILL|Gtk::EXPAND, yoptions, 0,0); + } + } else { + table.attach(*arr[i+1], 1, 3, r, r+1, Gtk::FILL|Gtk::EXPAND, yoptions, 0,0); + } + } else if (arr[i]) { Gtk::Label& label = reinterpret_cast<Gtk::Label&>(*arr[i]); label.set_alignment (0.0); - table.attach (label, 0, 3, r, r+1, - Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); - } - else - { + table.attach (label, 0, 3, r, r+1, Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0); + } else { Gtk::HBox *space = manage (new Gtk::HBox); space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y); - table.attach (*space, 0, 1, r, r+1, - (Gtk::AttachOptions)0, (Gtk::AttachOptions)0,0,0); + table.attach (*space, 0, 1, r, r+1, (Gtk::AttachOptions)0, (Gtk::AttachOptions)0,0,0); } } ++r; @@ -273,7 +270,12 @@ void DocumentProperties::build_page() _rcp_bord._label, &_rcp_bord, }; - attach_all(_page_page.table(), widget_array, G_N_ELEMENTS(widget_array)); + std::list<Gtk::Widget*> _slaveList; + _slaveList.push_back(&_rcb_bord); + _slaveList.push_back(&_rcb_shad); + _rcb_canb.setSlaveWidgets(_slaveList); + + attach_all(_page_page.table(), widget_array, G_N_ELEMENTS(widget_array),0,1); } void DocumentProperties::build_guides() @@ -331,21 +333,13 @@ void DocumentProperties::build_snap() #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) /// Populates the available color profiles combo box void DocumentProperties::populate_available_profiles(){ -#if WITH_GTKMM_2_24 _combo_avail.remove_all(); // Clear any existing items in the combo box -#else - _combo_avail.clear_items(); // Clear any existing items in the combo box -#endif // Iterate through the list of profiles and add the name to the combo box. std::vector<std::pair<Glib::ustring, Glib::ustring> > pairs = ColorProfile::getProfileFilesWithNames(); for ( std::vector<std::pair<Glib::ustring, Glib::ustring> >::const_iterator it = pairs.begin(); it != pairs.end(); ++it ) { Glib::ustring name = it->second; -#if WITH_GTKMM_2_24 _combo_avail.append(name); -#else - _combo_avail.append_text(name); -#endif } } @@ -926,7 +920,7 @@ void DocumentProperties::removeExternalScript(){ while ( current ) { if (current->data && SP_IS_OBJECT(current->data)) { SPObject* obj = SP_OBJECT(current->data); - SPScript* script = (SPScript*) obj; + SPScript* script = SP_SCRIPT(obj); if (name == script->xlinkhref){ //XML Tree being used directly here while it shouldn't be. @@ -959,16 +953,18 @@ void DocumentProperties::removeEmbeddedScript(){ const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "script" ); while ( current ) { - SPObject* obj = SP_OBJECT(current->data); - if (id == obj->getId()){ + if (current->data && SP_IS_OBJECT(current->data)) { + SPObject* obj = SP_OBJECT(current->data); + if (id == obj->getId()){ - //XML Tree being used directly here while it shouldn't be. - Inkscape::XML::Node *repr = obj->getRepr(); - if (repr){ - sp_repr_unparent(repr); + //XML Tree being used directly here while it shouldn't be. + Inkscape::XML::Node *repr = obj->getRepr(); + if (repr){ + sp_repr_unparent(repr); - // inform the document, so we can undo - DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_EDIT_REMOVE_EMBEDDED_SCRIPT, _("Remove embedded script")); + // inform the document, so we can undo + DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_EDIT_REMOVE_EMBEDDED_SCRIPT, _("Remove embedded script")); + } } } current = g_slist_next(current); @@ -1081,7 +1077,7 @@ void DocumentProperties::populate_script_lists(){ if (current) _scripts_observer.set(SP_OBJECT(current->data)->parent); while ( current ) { SPObject* obj = SP_OBJECT(current->data); - SPScript* script = (SPScript*) obj; + SPScript* script = SP_SCRIPT(obj); if (script->xlinkhref) { Gtk::TreeModel::Row row = *(_ExternalScriptsListStore->append()); @@ -1156,11 +1152,7 @@ void DocumentProperties::build_gridspage() _grids_hbox_crea.pack_start(_grids_button_new, true, true); for (gint t = 0; t <= GRID_MAXTYPENR; t++) { -#if WITH_GTKMM_2_24 _grids_combo_gridtype.append( CanvasGrid::getName( (GridType) t ) ); -#else - _grids_combo_gridtype.append_text( CanvasGrid::getName( (GridType) t ) ); -#endif } _grids_combo_gridtype.set_active_text( CanvasGrid::getName(GRID_RECTANGULAR) ); diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 62dd93126..f267c5ae9 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -296,7 +296,7 @@ Export::Export (void) : batch_box.pack_start(batch_export, false, false); hide_export.set_sensitive(true); - hide_export.set_active (true); + hide_export.set_active (prefs->getBool("/dialogs/export/hideexceptselected/value", false)); hide_box.pack_start(hide_export, false, false); @@ -328,6 +328,7 @@ Export::Export (void) : browse_button.signal_clicked().connect(sigc::mem_fun(*this, &Export::onBrowse)); batch_export.signal_clicked().connect(sigc::mem_fun(*this, &Export::onBatchClicked)); export_button.signal_clicked().connect(sigc::mem_fun(*this, &Export::onExport)); + hide_export.signal_clicked().connect(sigc::mem_fun(*this, &Export::onHideExceptSelected)); desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &Export::setTargetDesktop) ); deskTrack.connect(GTK_WIDGET(gobj())); @@ -547,7 +548,7 @@ void Export::updateCheckbuttons () batch_export.set_sensitive(false); } - hide_export.set_sensitive (num > 0 && current_key == SELECTION_SELECTION); + //hide_export.set_sensitive (num > 0); } inline void Export::findDefaultSelection() @@ -786,8 +787,6 @@ void Export::onAreaToggled () } } - hide_export.set_sensitive (key == SELECTION_SELECTION); - return; } // end of sp_export_area_toggled() @@ -919,6 +918,11 @@ Glib::ustring Export::absolutize_path_from_document_location (SPDocument *doc, c return path; } +void Export::onHideExceptSelected () +{ + prefs->setBool("/dialogs/export/hideexceptselected/value", hide_export.get_active()); +} + /// Called when export button is clicked void Export::onExport () { @@ -1256,6 +1260,14 @@ void Export::onBrowse () WCHAR* title_string = (WCHAR*)g_utf8_to_utf16(_("Select a filename for exporting"), -1, NULL, NULL, NULL); WCHAR* extension_string = (WCHAR*)g_utf8_to_utf16("*.png", -1, NULL, NULL, NULL); // Copy the selected file name, converting from UTF-8 to UTF-16 + std::string dirname = Glib::path_get_dirname(filename.raw()); + if ( !Glib::file_test(dirname, Glib::FILE_TEST_EXISTS) || + Glib::file_test(filename, Glib::FILE_TEST_IS_DIR) || + dirname.empty() ) + { + Glib::ustring tmp; + filename = create_filepath_from_id(tmp, tmp); + } WCHAR _filename[_MAX_PATH + 1]; memset(_filename, 0, sizeof(_filename)); gunichar2* utf16_path_string = g_utf8_to_utf16(filename.c_str(), -1, NULL, NULL, NULL); @@ -1434,7 +1446,7 @@ void Export::areaXChange (Gtk::Adjustment *adj) return; } - if (sp_unit_selector_update_test ((SPUnitSelector *)unit_selector->gobj())) { + if (sp_unit_selector_update_test(SP_UNIT_SELECTOR(unit_selector->gobj()))) { return; } @@ -1481,7 +1493,7 @@ void Export::areaYChange (Gtk::Adjustment *adj) return; } - if (sp_unit_selector_update_test ((SPUnitSelector *)unit_selector->gobj())) { + if (sp_unit_selector_update_test (SP_UNIT_SELECTOR(unit_selector->gobj()))) { return; } @@ -1636,7 +1648,7 @@ void Export::onBitmapWidthChange () return; } - if (sp_unit_selector_update_test ((SPUnitSelector *)unit_selector->gobj())) { + if (sp_unit_selector_update_test(SP_UNIT_SELECTOR(unit_selector->gobj()))) { return; } @@ -1670,7 +1682,7 @@ void Export::onBitmapHeightChange () return; } - if (sp_unit_selector_update_test ((SPUnitSelector *)unit_selector->gobj())) { + if (sp_unit_selector_update_test(SP_UNIT_SELECTOR(unit_selector->gobj()))) { return; } @@ -1730,7 +1742,7 @@ void Export::onExportXdpiChange() return; } - if (sp_unit_selector_update_test ((SPUnitSelector *)unit_selector->gobj())) { + if (sp_unit_selector_update_test(SP_UNIT_SELECTOR(unit_selector->gobj()))) { return; } @@ -1832,7 +1844,7 @@ 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 ((SPUnitSelector *)unit_selector->gobj() ); + const SPUnit *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(unit_selector->gobj()) ); setValue(adj, sp_pixels_get_units (val, *unit)); @@ -1882,7 +1894,7 @@ float Export::getValuePx( Gtk::Adjustment *adj ) #endif { float value = getValue( adj); - const SPUnit *unit = sp_unit_selector_get_unit ((SPUnitSelector *)unit_selector->gobj()); + const SPUnit *unit = sp_unit_selector_get_unit(SP_UNIT_SELECTOR(unit_selector->gobj())); return sp_units_get_pixels (value, *unit); } // end of sp_export_value_get_px() diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index e899009a7..c8376cdcb 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -178,6 +178,11 @@ private: #endif /** + * Hide except selected callback + */ + void onHideExceptSelected (); + + /** * Area width value changed callback */ void onAreaWidthChange (); diff --git a/src/ui/dialog/filedialog.cpp b/src/ui/dialog/filedialog.cpp index 47ba6c748..b3af6fc00 100644 --- a/src/ui/dialog/filedialog.cpp +++ b/src/ui/dialog/filedialog.cpp @@ -152,6 +152,9 @@ Glib::ustring FileSaveDialog::getDocTitle() void FileSaveDialog::appendExtension(Glib::ustring& path, Inkscape::Extension::Output* outputExtension) { + if (!outputExtension) + return; + try { bool appendExtension = true; Glib::ustring utf8Name = Glib::filename_to_utf8( path ); diff --git a/src/ui/dialog/filedialog.h b/src/ui/dialog/filedialog.h index 6a3436aea..63cee6bdc 100644 --- a/src/ui/dialog/filedialog.h +++ b/src/ui/dialog/filedialog.h @@ -208,6 +208,8 @@ public: virtual Glib::ustring getCurrentDirectory() = 0; + virtual void addFileType(Glib::ustring name, Glib::ustring pattern) = 0; + protected: /** diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp index 1663eb0b6..553acac84 100644 --- a/src/ui/dialog/filedialogimpl-gtkmm.cpp +++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp @@ -141,13 +141,12 @@ bool SVGPreview::setDocument(SPDocument *doc) //This should remove it from the box, and free resources if (viewerGtk) - gtk_widget_destroy(viewerGtk); - - viewerGtk = sp_svg_view_widget_new(doc); - GtkWidget *vbox = (GtkWidget *)gobj(); - gtk_box_pack_start(GTK_BOX(vbox), viewerGtk, TRUE, TRUE, 0); - gtk_widget_show(viewerGtk); + Gtk::Container::remove(*viewerGtk); + viewerGtk = Glib::wrap(sp_svg_view_widget_new(doc)); + Gtk::VBox *vbox = Glib::wrap(gobj()); + vbox->pack_start(*viewerGtk, TRUE, TRUE, 0); + viewerGtk->show(); return true; } @@ -1048,7 +1047,9 @@ FileSaveDialogImplGtk::FileSaveDialogImplGtk( Gtk::Window &parentWindow, fileTypeCheckbox.set_active(prefs->getBool("/dialogs/save_as/append_extension", true)); } - createFileTypeMenu(); + if (_dialogType != CUSTOM_TYPE) + createFileTypeMenu(); + fileTypeComboBox.set_size_request(200,40); fileTypeComboBox.signal_changed().connect( sigc::mem_fun(*this, &FileSaveDialogImplGtk::fileTypeChangedCallback) ); @@ -1175,8 +1176,21 @@ void FileSaveDialogImplGtk::fileTypeChangedCallback() updateNameAndExtension(); } +void FileSaveDialogImplGtk::addFileType(Glib::ustring name, Glib::ustring pattern) +{ + //#Let user choose + FileType guessType; + guessType.name = name; + guessType.pattern = pattern; + guessType.extension = NULL; + fileTypeComboBox.append(guessType.name); + fileTypes.push_back(guessType); + fileTypeComboBox.set_active(0); + fileTypeChangedCallback(); //call at least once to set the filter +} + void FileSaveDialogImplGtk::createFileTypeMenu() { Inkscape::Extension::DB::OutputList extension_list; @@ -1198,11 +1212,7 @@ void FileSaveDialogImplGtk::createFileTypeMenu() knownExtensions.insert( extension.casefold() ); fileDialogExtensionToPattern (type.pattern, extension); type.extension= omod; -#if WITH_GTKMM_2_24 fileTypeComboBox.append(type.name); -#else - fileTypeComboBox.append_text(type.name); -#endif fileTypes.push_back(type); } @@ -1211,11 +1221,7 @@ void FileSaveDialogImplGtk::createFileTypeMenu() guessType.name = _("Guess from extension"); guessType.pattern = "*"; guessType.extension = NULL; -#if WITH_GTKMM_2_24 fileTypeComboBox.append(guessType.name); -#else - fileTypeComboBox.append_text(guessType.name); -#endif fileTypes.push_back(guessType); diff --git a/src/ui/dialog/filedialogimpl-gtkmm.h b/src/ui/dialog/filedialogimpl-gtkmm.h index 2c22e7367..7501b5e14 100644 --- a/src/ui/dialog/filedialogimpl-gtkmm.h +++ b/src/ui/dialog/filedialogimpl-gtkmm.h @@ -121,7 +121,7 @@ private: /** * The sp_svg_view widget */ - GtkWidget *viewerGtk; + Gtk::Widget *viewerGtk; /** * are we currently showing the "no preview" image? @@ -291,6 +291,7 @@ public: virtual void setSelectionType( Inkscape::Extension::Extension * key ); Glib::ustring getCurrentDirectory(); + void addFileType(Glib::ustring name, Glib::ustring pattern); private: //void change_title(const Glib::ustring& title); diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp index 5891f25ac..6425d9fee 100644 --- a/src/ui/dialog/filedialogimpl-win32.cpp +++ b/src/ui/dialog/filedialogimpl-win32.cpp @@ -188,7 +188,8 @@ FileOpenDialogImplWin32::FileOpenDialogImplWin32(Gtk::Window &parent, _mutex = NULL; - createFilterMenu(); + if (dialogType != CUSTOM_TYPE) + createFilterMenu(); } @@ -1748,6 +1749,72 @@ void FileSaveDialogImplWin32::createFilterMenu() _filter_index = 1; // A value of 1 selects the 1st filter - NOT the 2nd } + +void FileSaveDialogImplWin32::addFileType(Glib::ustring name, Glib::ustring pattern) +{ + list<Filter> filter_list; + + knownExtensions.clear(); + + int extension_index = 0; + int filter_length = 1; + + ustring all_exe_files_filter = pattern; + Filter all_exe_files; + + const gchar *all_exe_files_filter_name = name.data(); + + // Calculate the amount of memory required + int filter_count = 1; + + + // Filter Executable Files + all_exe_files.name = g_utf8_to_utf16(all_exe_files_filter_name, + -1, NULL, &all_exe_files.name_length, NULL); + all_exe_files.filter = g_utf8_to_utf16(all_exe_files_filter.data(), + -1, NULL, &all_exe_files.filter_length, NULL); + all_exe_files.mod = NULL; + filter_list.push_front(all_exe_files); + + knownExtensions.insert( Glib::ustring(all_exe_files_filter).casefold() ); + + _extension_map = new Inkscape::Extension::Extension*[filter_count]; + + _filter = new wchar_t[filter_length]; + wchar_t *filterptr = _filter; + + for(list<Filter>::iterator filter_iterator = filter_list.begin(); + filter_iterator != filter_list.end(); ++filter_iterator) + { + const Filter &filter = *filter_iterator; + + wcsncpy(filterptr, (wchar_t*)filter.name, filter.name_length); + filterptr += filter.name_length; + g_free(filter.name); + + *(filterptr++) = L'\0'; + *(filterptr++) = L'*'; + + if(filter.filter != NULL) + { + wcsncpy(filterptr, (wchar_t*)filter.filter, filter.filter_length); + filterptr += filter.filter_length; + g_free(filter.filter); + } + + *(filterptr++) = L'\0'; + + // Associate this input extension with the file type name + _extension_map[extension_index++] = filter.mod; + } + *(filterptr++) = L'\0'; + + _filter_count = extension_index; + _filter_index = 1; // Select the 1st filter in the list + + +} + void FileSaveDialogImplWin32::GetSaveFileName_thread() { OPENFILENAMEEXW ofn; @@ -1814,7 +1881,7 @@ FileSaveDialogImplWin32::show() if(Glib::Thread::create(sigc::mem_fun(*this, &FileSaveDialogImplWin32::GetSaveFileName_thread), true)) g_main_loop_run(_main_loop); - if(_result) + if(_result && _extension) appendExtension(myFilename, (Inkscape::Extension::Output*)_extension); } @@ -1827,6 +1894,7 @@ void FileSaveDialogImplWin32::setSelectionType( Inkscape::Extension::Extension * } + UINT_PTR CALLBACK FileSaveDialogImplWin32::GetSaveFileName_hookproc( HWND hdlg, UINT uiMsg, WPARAM, LPARAM lParam) { diff --git a/src/ui/dialog/filedialogimpl-win32.h b/src/ui/dialog/filedialogimpl-win32.h index d016b0a24..15953f9d8 100644 --- a/src/ui/dialog/filedialogimpl-win32.h +++ b/src/ui/dialog/filedialogimpl-win32.h @@ -343,6 +343,8 @@ public: virtual void setSelectionType( Inkscape::Extension::Extension *key ); + virtual void addFileType(Glib::ustring name, Glib::ustring pattern); + private: /// A handle to the title label and edit box HWND _title_label; diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index 74c19fea7..5ba4e7e39 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -22,6 +22,7 @@ #include "filter-chemistry.h" #include "inkscape.h" #include "selection.h" +#include "preferences.h" #include "style.h" #include "svg/css-ostringstream.h" #include "ui/icon-names.h" @@ -59,11 +60,13 @@ FillAndStroke::FillAndStroke() _notebook.append_page(_page_stroke_paint, _createPageTabLabel(_("Stroke _paint"), INKSCAPE_ICON("object-stroke"))); _notebook.append_page(_page_stroke_style, _createPageTabLabel(_("Stroke st_yle"), INKSCAPE_ICON("object-stroke-style"))); + _notebook.signal_switch_page().connect(sigc::mem_fun(this, &FillAndStroke::_onSwitchPage)); + _layoutPageFill(); _layoutPageStrokePaint(); _layoutPageStrokeStyle(); - contents->pack_start(_composite_settings, false, false, 0); + contents->pack_start(_composite_settings, true, true, 0); show_all_children(); @@ -105,6 +108,23 @@ void FillAndStroke::setTargetDesktop(SPDesktop *desktop) } } +#if WITH_GTKMM_3_0 +void FillAndStroke::_onSwitchPage(Gtk::Widget * /*page*/, guint pagenum) +#else +void FillAndStroke::_onSwitchPage(GtkNotebookPage * /*page*/, guint pagenum) +#endif +{ + _savePagePref(pagenum); +} + +void +FillAndStroke::_savePagePref(guint page_num) +{ + // remember the current page + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setInt("/dialogs/fillstroke/page", page_num); +} + void FillAndStroke::_layoutPageFill() { @@ -133,6 +153,8 @@ FillAndStroke::showPageFill() { present(); _notebook.set_current_page(0); + _savePagePref(0); + } void @@ -140,6 +162,7 @@ FillAndStroke::showPageStrokePaint() { present(); _notebook.set_current_page(1); + _savePagePref(1); } void @@ -147,6 +170,8 @@ FillAndStroke::showPageStrokeStyle() { present(); _notebook.set_current_page(2); + _savePagePref(2); + } Gtk::HBox& diff --git a/src/ui/dialog/fill-and-stroke.h b/src/ui/dialog/fill-and-stroke.h index 596205c58..255cea89a 100644 --- a/src/ui/dialog/fill-and-stroke.h +++ b/src/ui/dialog/fill-and-stroke.h @@ -60,6 +60,12 @@ protected: void _layoutPageFill(); void _layoutPageStrokePaint(); void _layoutPageStrokeStyle(); + void _savePagePref(guint page_num); +#if WITH_GTKMM_3_0 + void _onSwitchPage(Gtk::Widget *page, guint pagenum); +#else + void _onSwitchPage(GtkNotebookPage *page, guint pagenum); +#endif private: FillAndStroke(FillAndStroke const &d); diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp index 317cb2773..ddafcd481 100644 --- a/src/ui/dialog/filter-effects-dialog.cpp +++ b/src/ui/dialog/filter-effects-dialog.cpp @@ -62,6 +62,7 @@ #include "io/sys.h" #include <iostream> +#include "selection-chemistry.h" #include <gtkmm/checkbutton.h> #include <gtkmm/colorbutton.h> @@ -78,12 +79,12 @@ namespace Dialog { using Inkscape::UI::Widget::AttrWidget; using Inkscape::UI::Widget::ComboBoxEnum; -using Inkscape::UI::Widget::DualSpinSlider; -using Inkscape::UI::Widget::SpinSlider; +using Inkscape::UI::Widget::DualSpinScale; +using Inkscape::UI::Widget::SpinScale; // Returns the number of inputs available for the filter primitive type -int input_count(const SPFilterPrimitive* prim) +static int input_count(const SPFilterPrimitive* prim) { if(!prim) return 0; @@ -484,8 +485,8 @@ public: : AttrWidget(SP_ATTR_VALUES), // TRANSLATORS: this dialog is accessible via menu Filters - Filter editor _matrix(SP_ATTR_VALUES, _("This matrix determines a linear transform on color space. Each line affects one of the color components. Each column determines how much of each color component from the input is passed to the output. The last column does not depend on input colors, so can be used to adjust a constant component value.")), - _saturation(0, 0, 1, 0.1, 0.01, 2, SP_ATTR_VALUES), - _angle(0, 0, 360, 0.1, 0.01, 1, SP_ATTR_VALUES), + _saturation("", 0, 0, 1, 0.1, 0.01, 2, SP_ATTR_VALUES), + _angle("", 0, 0, 360, 0.1, 0.01, 1, SP_ATTR_VALUES), _label(_("None"), Gtk::ALIGN_START), _use_stored(false), _saturation_store(0), @@ -567,8 +568,8 @@ private: } MatrixAttr _matrix; - SpinSlider _saturation; - SpinSlider _angle; + SpinScale _saturation; + SpinScale _angle; Gtk::Label _label; // Store separate values for the different color modes @@ -808,22 +809,22 @@ public: return cmv; } - // SpinSlider - SpinSlider* add_spinslider(double def, const SPAttributeEnum attr, const Glib::ustring& label, + // SpinScale + SpinScale* add_spinscale(double def, const SPAttributeEnum attr, const Glib::ustring& label, const double lo, const double hi, const double step_inc, const double climb, const int digits, char* tip_text = NULL) { - SpinSlider* spinslider = new SpinSlider(def, lo, hi, step_inc, climb, digits, attr, tip_text); + SpinScale* spinslider = new SpinScale("", def, lo, hi, step_inc, climb, digits, attr, tip_text); add_widget(spinslider, label); add_attr_widget(spinslider); return spinslider; } - // DualSpinSlider - DualSpinSlider* add_dualspinslider(const SPAttributeEnum attr, const Glib::ustring& label, + // DualSpinScale + DualSpinScale* add_dualspinscale(const SPAttributeEnum attr, const Glib::ustring& label, const double lo, const double hi, const double step_inc, const double climb, const int digits, char* tip_text1 = NULL, char* tip_text2 = NULL) { - DualSpinSlider* dss = new DualSpinSlider(lo, lo, hi, step_inc, climb, digits, attr, tip_text1, tip_text2); + DualSpinScale* dss = new DualSpinScale("", "", lo, lo, hi, step_inc, climb, digits, attr, tip_text1, tip_text2); add_widget(dss, label); add_attr_widget(dss); return dss; @@ -971,8 +972,8 @@ public: // FIXME: these range values are complete crap _settings.type(LIGHT_DISTANT); - _settings.add_spinslider(0, SP_ATTR_AZIMUTH, _("Azimuth"), 0, 360, 1, 1, 0, _("Direction angle for the light source on the XY plane, in degrees")); - _settings.add_spinslider(0, SP_ATTR_ELEVATION, _("Elevation"), 0, 360, 1, 1, 0, _("Direction angle for the light source on the YZ plane, in degrees")); + _settings.add_spinscale(0, SP_ATTR_AZIMUTH, _("Azimuth"), 0, 360, 1, 1, 0, _("Direction angle for the light source on the XY plane, in degrees")); + _settings.add_spinscale(0, SP_ATTR_ELEVATION, _("Elevation"), 0, 360, 1, 1, 0, _("Direction angle for the light source on the YZ plane, in degrees")); _settings.type(LIGHT_POINT); _settings.add_multispinbutton(/*default x:*/ (double) 0, /*default y:*/ (double) 0, /*default z:*/ (double) 0, SP_ATTR_X, SP_ATTR_Y, SP_ATTR_Z, _("Location:"), -99999, 99999, 1, 100, 0, _("X coordinate"), _("Y coordinate"), _("Z coordinate")); @@ -982,9 +983,9 @@ public: _settings.add_multispinbutton(/*default x:*/ (double) 0, /*default y:*/ (double) 0, /*default z:*/ (double) 0, SP_ATTR_POINTSATX, SP_ATTR_POINTSATY, SP_ATTR_POINTSATZ, _("Points At"), -99999, 99999, 1, 100, 0, _("X coordinate"), _("Y coordinate"), _("Z coordinate")); - _settings.add_spinslider(1, SP_ATTR_SPECULAREXPONENT, _("Specular Exponent"), 1, 100, 1, 1, 0, _("Exponent value controlling the focus for the light source")); + _settings.add_spinscale(1, SP_ATTR_SPECULAREXPONENT, _("Specular Exponent"), 1, 100, 1, 1, 0, _("Exponent value controlling the focus for the light source")); //TODO: here I have used 100 degrees as default value. But spec says that if not specified, no limiting cone is applied. So, there should be a way for the user to set a "no limiting cone" option. - _settings.add_spinslider(100, SP_ATTR_LIMITINGCONEANGLE, _("Cone Angle"), 1, 100, 1, 1, 0, _("This is the angle between the spot light axis (i.e. the axis between the light source and the point to which it is pointing at) and the spot light cone. No light is projected outside this cone.")); + _settings.add_spinscale(100, SP_ATTR_LIMITINGCONEANGLE, _("Cone Angle"), 1, 100, 1, 1, 0, _("This is the angle between the spot light axis (i.e. the axis between the light source and the point to which it is pointing at) and the spot light cone. No light is projected outside this cone.")); } Gtk::VBox& get_box() @@ -1057,11 +1058,7 @@ private: void update() { -#if WITH_GTKMM_2_24 - _box.hide(); -#else - _box.hide_all(); -#endif + _box.hide(); _box.show(); _light_box.show_all(); @@ -1087,8 +1084,8 @@ FilterEffectsDialog::LightSourceControl* FilterEffectsDialog::Settings::add_ligh return ls; } -Glib::RefPtr<Gtk::Menu> create_popup_menu(Gtk::Widget& parent, sigc::slot<void> dup, - sigc::slot<void> rem) +static Glib::RefPtr<Gtk::Menu> create_popup_menu(Gtk::Widget& parent, sigc::slot<void> dup, + sigc::slot<void> rem) { Glib::RefPtr<Gtk::Menu> menu(new Gtk::Menu); @@ -1127,13 +1124,8 @@ FilterEffectsDialog::FilterModifier::FilterModifier(FilterEffectsDialog& d) if(col) col->add_attribute(_cell_toggle.property_active(), _columns.sel); _list.append_column_editable(_("_Filter"), _columns.label); -#if WITH_GTKMM_2_24 ((Gtk::CellRendererText*)_list.get_column(1)->get_first_cell())-> signal_edited().connect(sigc::mem_fun(*this, &FilterEffectsDialog::FilterModifier::on_name_edited)); -#else - ((Gtk::CellRendererText*)_list.get_column(1)->get_first_cell_renderer())-> - signal_edited().connect(sigc::mem_fun(*this, &FilterEffectsDialog::FilterModifier::on_name_edited)); -#endif sw->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); sw->set_shadow_type(Gtk::SHADOW_IN); @@ -1193,6 +1185,17 @@ void FilterEffectsDialog::FilterModifier::setTargetDesktop(SPDesktop *desktop) } } +// When the document changes, update connection to resources +void FilterEffectsDialog::FilterModifier::on_document_replaced(SPDesktop *desktop, SPDocument *document) +{ + if (_resource_changed) { + _resource_changed.disconnect(); + } + _resource_changed = document->connectResourcesChanged("filter",sigc::mem_fun(*this, &FilterModifier::update_filters)); + + update_filters(); +} + // When the selection changes, show the active filter(s) in the dialog void FilterEffectsDialog::FilterModifier::on_change_selection() { @@ -1316,7 +1319,7 @@ void FilterEffectsDialog::FilterModifier::update_filters() for(const GSList *l = filters; l; l = l->next) { Gtk::TreeModel::Row row = *_model->append(); - SPFilter* f = (SPFilter*)l->data; + SPFilter* f = SP_FILTER(l->data); row[_columns.filter] = f; const gchar* lbl = f->label(); const gchar* id = f->getId(); @@ -1387,6 +1390,29 @@ void FilterEffectsDialog::FilterModifier::remove_filter() if(filter) { SPDocument* doc = filter->document; + // Delete all references to this filter + GSList *all = get_all_items(NULL, _desktop->currentRoot(), _desktop, false, false, true, NULL); + for (GSList *i = all; i != NULL; i = i->next) { + if (!SP_IS_ITEM(i->data)) { + continue; + } + SPItem *item = SP_ITEM(i->data); + if (!item->style) { + continue; + } + + const SPIFilter *ifilter = &(item->style->filter); + if (ifilter && ifilter->href) { + const SPObject *obj = ifilter->href->getObject(); + if (obj && obj == (SPObject *)filter) { + ::remove_filter(item, false); + } + } + } + if (all) { + g_slist_free(all); + } + //XML Tree being used directly here while it shouldn't be. sp_repr_unparent(filter->getRepr()); @@ -1443,7 +1469,7 @@ void FilterEffectsDialog::CellRendererConnection::get_size_vfunc( if(height) { // Scale the height depending on the number of inputs, unless it's // the first primitive, in which case there are no connections - SPFilterPrimitive* prim = (SPFilterPrimitive*)_primitive.get_value(); + SPFilterPrimitive* prim = SP_FILTER_PRIMITIVE(_primitive.get_value()); (*height) = size * input_count(prim); } } @@ -1525,11 +1551,10 @@ void FilterEffectsDialog::PrimitiveList::update() { SPFilter* f = _dialog._filter_modifier.get_selected_filter(); const SPFilterPrimitive* active_prim = get_selected(); - bool active_found = false; - _model->clear(); if(f) { + bool active_found = false; _dialog._primitive_box.set_sensitive(true); _dialog.update_filter_general_settings_view(); for(SPObject *prim_obj = f->children; @@ -1635,8 +1660,30 @@ bool FilterEffectsDialog::PrimitiveList::on_draw(const Cairo::RefPtr<Cairo::Cont { cr->set_line_width(1.0); - // TODO: Use Gtk::StyleContext instead +#if GTK_CHECK_VERSION(3,0,0) + GtkStyleContext *sc = gtk_widget_get_style_context(GTK_WIDGET(gobj())); + GdkRGBA bg_color, fg_color; + gtk_style_context_get_background_color(sc, GTK_STATE_FLAG_NORMAL, &bg_color); + gtk_style_context_get_color(sc, GTK_STATE_FLAG_NORMAL, &fg_color); + + GdkRGBA mid_color = {(bg_color.red + fg_color.red)/2.0, + (bg_color.green + fg_color.green)/2.0, + (bg_color.blue + fg_color.blue)/2.0, + (bg_color.alpha + fg_color.alpha)/2.0}; + + GdkRGBA bg_color_active, fg_color_active; + gtk_style_context_get_background_color(sc, GTK_STATE_FLAG_ACTIVE, &bg_color_active); + gtk_style_context_get_color(sc, GTK_STATE_FLAG_ACTIVE, &fg_color_active); + + GdkRGBA mid_color_active = {(bg_color_active.red + fg_color_active.red)/2.0, + (bg_color_active.green + fg_color_active.green)/2.0, + (bg_color_active.blue + fg_color_active.blue)/2.0, + (bg_color_active.alpha + fg_color_active.alpha)/2.0}; + + GdkRGBA black = {0,0,0,1}; +#else GtkStyle *style = gtk_widget_get_style(GTK_WIDGET(gobj())); +#endif SPFilterPrimitive* prim = get_selected(); int row_count = get_model()->children().size(); @@ -1655,13 +1702,25 @@ bool FilterEffectsDialog::PrimitiveList::on_draw(const Cairo::RefPtr<Cairo::Cont const int x = text_start_x + get_input_type_width() * i; cr->save(); cr->rectangle(x, 0, get_input_type_width(), vis.get_height()); +#if GTK_CHECK_VERSION(3,0,0) + gdk_cairo_set_source_rgba(cr->cobj(), &bg_color); + cr->fill_preserve(); + + gdk_cairo_set_source_rgba(cr->cobj(), &fg_color); +#else gdk_cairo_set_source_color(cr->cobj(), &(style->bg[GTK_STATE_NORMAL])); cr->fill_preserve(); gdk_cairo_set_source_color(cr->cobj(), &(style->text[GTK_STATE_NORMAL])); +#endif cr->move_to(x+get_input_type_width(), 0); cr->rotate_degrees(90); _vertical_layout->show_in_cairo_context(cr); + +#if GTK_CHECK_VERSION(3,0,0) + gdk_cairo_set_source_rgba(cr->cobj(), &mid_color); +#else gdk_cairo_set_source_color(cr->cobj(), &(style->dark[GTK_STATE_NORMAL])); +#endif cr->move_to(x, 0); cr->line_to(x, vis.get_height()); cr->stroke(); @@ -1682,7 +1741,13 @@ bool FilterEffectsDialog::PrimitiveList::on_draw(const Cairo::RefPtr<Cairo::Cont // Outline the bottom of the connection area const int outline_x = x + fheight * (row_count - row_index); cr->save(); + +#if GTK_CHECK_VERSION(3,0,0) + gdk_cairo_set_source_rgba(cr->cobj(), &mid_color); +#else gdk_cairo_set_source_color(cr->cobj(), &(style->dark[GTK_STATE_NORMAL])); +#endif + cr->move_to(x, y + h); cr->line_to(outline_x, y + h); // Side outline @@ -1703,10 +1768,17 @@ bool FilterEffectsDialog::PrimitiveList::on_draw(const Cairo::RefPtr<Cairo::Cont cr->save(); +#if GTK_CHECK_VERSION(3,0,0) + gdk_cairo_set_source_rgba(cr->cobj(), + inside && mask & GDK_BUTTON1_MASK ? + &mid_color : + &mid_color_active); +#else gdk_cairo_set_source_color(cr->cobj(), inside && mask & GDK_BUTTON1_MASK ? &(style->dark[GTK_STATE_NORMAL]) : &(style->dark[GTK_STATE_ACTIVE])); +#endif draw_connection_node(cr, con_poly, inside); @@ -1726,10 +1798,17 @@ bool FilterEffectsDialog::PrimitiveList::on_draw(const Cairo::RefPtr<Cairo::Cont cr->save(); +#if GTK_CHECK_VERSION(3,0,0) + gdk_cairo_set_source_rgba(cr->cobj(), + inside && mask & GDK_BUTTON1_MASK ? + &mid_color : + &mid_color_active); +#else gdk_cairo_set_source_color(cr->cobj(), inside && mask & GDK_BUTTON1_MASK ? &(style->dark[GTK_STATE_NORMAL]) : &(style->dark[GTK_STATE_ACTIVE])); +#endif draw_connection_node(cr, con_poly, inside); @@ -1747,10 +1826,17 @@ bool FilterEffectsDialog::PrimitiveList::on_draw(const Cairo::RefPtr<Cairo::Cont cr->save(); +#if GTK_CHECK_VERSION(3,0,0) + gdk_cairo_set_source_rgba(cr->cobj(), + inside && mask & GDK_BUTTON1_MASK ? + &mid_color : + &mid_color_active); +#else gdk_cairo_set_source_color(cr->cobj(), inside && mask & GDK_BUTTON1_MASK ? &(style->dark[GTK_STATE_NORMAL]) : &(style->dark[GTK_STATE_ACTIVE])); +#endif draw_connection_node(cr, con_poly, inside); @@ -1765,7 +1851,11 @@ bool FilterEffectsDialog::PrimitiveList::on_draw(const Cairo::RefPtr<Cairo::Cont // Draw drag connection if(row_prim == prim && _in_drag) { cr->save(); +#if GTK_CHECK_VERSION(3,0,0) + gdk_cairo_set_source_rgba(cr->cobj(), &black); +#else gdk_cairo_set_source_color(cr->cobj(), &(style->black)); +#endif cr->move_to(outline_x, con_drag_y); cr->line_to(mx, con_drag_y); cr->line_to(mx, my); @@ -1784,8 +1874,22 @@ void FilterEffectsDialog::PrimitiveList::draw_connection(const Cairo::RefPtr<Cai { cr->save(); - // TODO: Use Gtk::StyleContext instead +#if GTK_CHECK_VERSION(3,0,0) + GtkStyleContext *sc = gtk_widget_get_style_context(GTK_WIDGET(gobj())); + + GdkRGBA bg_color, fg_color; + gtk_style_context_get_background_color(sc, GTK_STATE_FLAG_NORMAL, &bg_color); + gtk_style_context_get_color(sc, GTK_STATE_FLAG_NORMAL, &fg_color); + + GdkRGBA mid_color = {(bg_color.red + fg_color.red)/2.0, + (bg_color.green + fg_color.green)/2.0, + (bg_color.blue + fg_color.blue)/2.0, + (bg_color.alpha + fg_color.alpha)/2.0}; + + GdkRGBA black = {0,0,0,1}; +#else GtkStyle *style = gtk_widget_get_style(GTK_WIDGET(gobj())); +#endif int src_id = 0; Gtk::TreeIter res = find_result(input, attr, src_id); @@ -1800,10 +1904,17 @@ void FilterEffectsDialog::PrimitiveList::draw_connection(const Cairo::RefPtr<Cai const int tw = get_input_type_width(); gint end_x = text_start_x + tw * src_id + (int)(tw * 0.5f) + 1; +#if GTK_CHECK_VERSION(3,0,0) + if(use_default && is_first) + gdk_cairo_set_source_rgba(cr->cobj(), &mid_color); + else + gdk_cairo_set_source_rgba(cr->cobj(), &black); +#else if(use_default && is_first) gdk_cairo_set_source_color(cr->cobj(), &(style->dark[GTK_STATE_NORMAL])); else gdk_cairo_set_source_color(cr->cobj(), &(style->black)); +#endif cr->rectangle(end_x-2, y1-2, 5, 5); cr->fill_preserve(); @@ -1831,7 +1942,11 @@ void FilterEffectsDialog::PrimitiveList::draw_connection(const Cairo::RefPtr<Cai const int y2 = rct.get_y() + rct.get_height(); // Draw a bevelled 'L'-shaped connection +#if GTK_CHECK_VERSION(3,0,0) + gdk_cairo_set_source_rgba(cr->cobj(), &black); +#else gdk_cairo_set_source_color(cr->cobj(), &(style->black)); +#endif cr->move_to(x1, y1); cr->line_to(x2-fheight/4, y1); cr->line_to(x2, y1-fheight/4); @@ -2123,7 +2238,7 @@ bool FilterEffectsDialog::PrimitiveList::on_button_release_event(GdkEventButton* } // Checks all of prim's inputs, removes any that use result -void check_single_connection(SPFilterPrimitive* prim, const int result) +static void check_single_connection(SPFilterPrimitive* prim, const int result) { if (prim && (result >= 0)) { if (prim->image_in == result) { @@ -2331,7 +2446,7 @@ void FilterEffectsDialog::show_all_vfunc() void FilterEffectsDialog::init_settings_widgets() { - // TODO: Find better range/climb-rate/digits values for the SpinSliders, + // TODO: Find better range/climb-rate/digits values for the SpinScales, // most of the current values are complete guesses! _empty_settings.set_sensitive(false); @@ -2358,18 +2473,18 @@ void FilterEffectsDialog::init_settings_widgets() /* //TRANSLATORS: for info on "Slope" and "Intercept", see http://id.mind.net/~zona/mmts/functionInstitute/linearFunctions/lsif.html _settings->add_combo(COMPONENTTRANSFER_TYPE_IDENTITY, SP_ATTR_TYPE, _("Type"), ComponentTransferTypeConverter); - _ct_slope = _settings->add_spinslider(1, SP_ATTR_SLOPE, _("Slope"), -10, 10, 0.1, 0.01, 2); - _ct_intercept = _settings->add_spinslider(0, SP_ATTR_INTERCEPT, _("Intercept"), -10, 10, 0.1, 0.01, 2); - _ct_amplitude = _settings->add_spinslider(1, SP_ATTR_AMPLITUDE, _("Amplitude"), 0, 10, 0.1, 0.01, 2); - _ct_exponent = _settings->add_spinslider(1, SP_ATTR_EXPONENT, _("Exponent"), 0, 10, 0.1, 0.01, 2); - _ct_offset = _settings->add_spinslider(0, SP_ATTR_OFFSET, _("Offset"), -10, 10, 0.1, 0.01, 2);*/ + _ct_slope = _settings->add_spinscale(1, SP_ATTR_SLOPE, _("Slope"), -10, 10, 0.1, 0.01, 2); + _ct_intercept = _settings->add_spinscale(0, SP_ATTR_INTERCEPT, _("Intercept"), -10, 10, 0.1, 0.01, 2); + _ct_amplitude = _settings->add_spinscale(1, SP_ATTR_AMPLITUDE, _("Amplitude"), 0, 10, 0.1, 0.01, 2); + _ct_exponent = _settings->add_spinscale(1, SP_ATTR_EXPONENT, _("Exponent"), 0, 10, 0.1, 0.01, 2); + _ct_offset = _settings->add_spinscale(0, SP_ATTR_OFFSET, _("Offset"), -10, 10, 0.1, 0.01, 2);*/ _settings->type(NR_FILTER_COMPOSITE); _settings->add_combo(COMPOSITE_OVER, SP_ATTR_OPERATOR, _("Operator:"), CompositeOperatorConverter); - _k1 = _settings->add_spinslider(0, SP_ATTR_K1, _("K1:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); - _k2 = _settings->add_spinslider(0, SP_ATTR_K2, _("K2:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); - _k3 = _settings->add_spinslider(0, SP_ATTR_K3, _("K3:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); - _k4 = _settings->add_spinslider(0, SP_ATTR_K4, _("K4:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); + _k1 = _settings->add_spinscale(0, SP_ATTR_K1, _("K1:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); + _k2 = _settings->add_spinscale(0, SP_ATTR_K2, _("K2:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); + _k3 = _settings->add_spinscale(0, SP_ATTR_K3, _("K3:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); + _k4 = _settings->add_spinscale(0, SP_ATTR_K4, _("K4:"), -10, 10, 0.1, 0.01, 2, _("If the arithmetic operation is chosen, each result pixel is computed using the formula k1*i1*i2 + k2*i1 + k3*i2 + k4 where i1 and i2 are the pixel values of the first and second inputs respectively.")); _settings->type(NR_FILTER_CONVOLVEMATRIX); _convolve_order = _settings->add_dualspinbutton((char*)"3", SP_ATTR_ORDER, _("Size:"), 1, 5, 1, 1, 0, _("width of the convolve matrix"), _("height of the convolve matrix")); @@ -2377,50 +2492,50 @@ void FilterEffectsDialog::init_settings_widgets() //TRANSLATORS: for info on "Kernel", see http://en.wikipedia.org/wiki/Kernel_(matrix) _convolve_matrix = _settings->add_matrix(SP_ATTR_KERNELMATRIX, _("Kernel:"), _("This matrix describes the convolve operation that is applied to the input image in order to calculate the pixel colors at the output. Different arrangements of values in this matrix result in various possible visual effects. An identity matrix would lead to a motion blur effect (parallel to the matrix diagonal) while a matrix filled with a constant non-zero value would lead to a common blur effect.")); _convolve_order->signal_attr_changed().connect(sigc::mem_fun(*this, &FilterEffectsDialog::convolve_order_changed)); - _settings->add_spinslider(0, SP_ATTR_DIVISOR, _("Divisor:"), 0, 1000, 1, 0.1, 2, _("After applying the kernelMatrix to the input image to yield a number, that number is divided by divisor to yield the final destination color value. A divisor that is the sum of all the matrix values tends to have an evening effect on the overall color intensity of the result.")); - _settings->add_spinslider(0, SP_ATTR_BIAS, _("Bias:"), -10, 10, 1, 0.01, 1, _("This value is added to each component. This is useful to define a constant value as the zero response of the filter.")); + _settings->add_spinscale(0, SP_ATTR_DIVISOR, _("Divisor:"), 0, 1000, 1, 0.1, 2, _("After applying the kernelMatrix to the input image to yield a number, that number is divided by divisor to yield the final destination color value. A divisor that is the sum of all the matrix values tends to have an evening effect on the overall color intensity of the result.")); + _settings->add_spinscale(0, SP_ATTR_BIAS, _("Bias:"), -10, 10, 1, 0.01, 1, _("This value is added to each component. This is useful to define a constant value as the zero response of the filter.")); _settings->add_combo(CONVOLVEMATRIX_EDGEMODE_DUPLICATE, SP_ATTR_EDGEMODE, _("Edge Mode:"), ConvolveMatrixEdgeModeConverter, _("Determines how to extend the input image as necessary with color values so that the matrix operations can be applied when the kernel is positioned at or near the edge of the input image.")); _settings->add_checkbutton(false, SP_ATTR_PRESERVEALPHA, _("Preserve Alpha"), "true", "false", _("If set, the alpha channel won't be altered by this filter primitive.")); _settings->type(NR_FILTER_DIFFUSELIGHTING); _settings->add_color(/*default: white*/ 0xffffffff, SP_PROP_LIGHTING_COLOR, _("Diffuse Color:"), _("Defines the color of the light source")); - _settings->add_spinslider(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.01, 0.001, 3, _("This value amplifies the heights of the bump map defined by the input alpha channel")); - _settings->add_spinslider(1, SP_ATTR_DIFFUSECONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model.")); - _settings->add_dualspinslider(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1); + _settings->add_spinscale(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.01, 0.001, 3, _("This value amplifies the heights of the bump map defined by the input alpha channel")); + _settings->add_spinscale(1, SP_ATTR_DIFFUSECONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model.")); + _settings->add_dualspinscale(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1); _settings->add_lightsource(); _settings->type(NR_FILTER_DISPLACEMENTMAP); - _settings->add_spinslider(0, SP_ATTR_SCALE, _("Scale:"), 0, 100, 1, 0.01, 1, _("This defines the intensity of the displacement effect.")); + _settings->add_spinscale(0, SP_ATTR_SCALE, _("Scale:"), 0, 100, 1, 0.01, 1, _("This defines the intensity of the displacement effect.")); _settings->add_combo(DISPLACEMENTMAP_CHANNEL_ALPHA, SP_ATTR_XCHANNELSELECTOR, _("X displacement:"), DisplacementMapChannelConverter, _("Color component that controls the displacement in the X direction")); _settings->add_combo(DISPLACEMENTMAP_CHANNEL_ALPHA, SP_ATTR_YCHANNELSELECTOR, _("Y displacement:"), DisplacementMapChannelConverter, _("Color component that controls the displacement in the Y direction")); _settings->type(NR_FILTER_FLOOD); _settings->add_color(/*default: black*/ 0, SP_PROP_FLOOD_COLOR, _("Flood Color:"), _("The whole filter region will be filled with this color.")); - _settings->add_spinslider(1, SP_PROP_FLOOD_OPACITY, _("Opacity:"), 0, 1, 0.1, 0.01, 2); + _settings->add_spinscale(1, SP_PROP_FLOOD_OPACITY, _("Opacity:"), 0, 1, 0.1, 0.01, 2); _settings->type(NR_FILTER_GAUSSIANBLUR); - _settings->add_dualspinslider(SP_ATTR_STDDEVIATION, _("Standard Deviation:"), 0.01, 100, 1, 0.01, 1, _("The standard deviation for the blur operation.")); + _settings->add_dualspinscale(SP_ATTR_STDDEVIATION, _("Standard Deviation:"), 0.01, 100, 1, 0.01, 1, _("The standard deviation for the blur operation.")); _settings->type(NR_FILTER_MERGE); _settings->add_no_params(); _settings->type(NR_FILTER_MORPHOLOGY); _settings->add_combo(MORPHOLOGY_OPERATOR_ERODE, SP_ATTR_OPERATOR, _("Operator:"), MorphologyOperatorConverter, _("Erode: performs \"thinning\" of input image.\nDilate: performs \"fattenning\" of input image.")); - _settings->add_dualspinslider(SP_ATTR_RADIUS, _("Radius:"), 0, 100, 1, 0.01, 1); + _settings->add_dualspinscale(SP_ATTR_RADIUS, _("Radius:"), 0, 100, 1, 0.01, 1); _settings->type(NR_FILTER_IMAGE); _settings->add_fileorelement(SP_ATTR_XLINK_HREF, _("Source of Image:")); _settings->type(NR_FILTER_OFFSET); - _settings->add_spinslider(0, SP_ATTR_DX, _("Delta X:"), -100, 100, 1, 0.01, 1, _("This is how far the input image gets shifted to the right")); - _settings->add_spinslider(0, SP_ATTR_DY, _("Delta Y:"), -100, 100, 1, 0.01, 1, _("This is how far the input image gets shifted downwards")); + _settings->add_spinscale(0, SP_ATTR_DX, _("Delta X:"), -100, 100, 1, 0.01, 1, _("This is how far the input image gets shifted to the right")); + _settings->add_spinscale(0, SP_ATTR_DY, _("Delta Y:"), -100, 100, 1, 0.01, 1, _("This is how far the input image gets shifted downwards")); _settings->type(NR_FILTER_SPECULARLIGHTING); _settings->add_color(/*default: white*/ 0xffffffff, SP_PROP_LIGHTING_COLOR, _("Specular Color:"), _("Defines the color of the light source")); - _settings->add_spinslider(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.1, 0.01, 2, _("This value amplifies the heights of the bump map defined by the input alpha channel")); - _settings->add_spinslider(1, SP_ATTR_SPECULARCONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model.")); - _settings->add_spinslider(1, SP_ATTR_SPECULAREXPONENT, _("Exponent:"), 1, 50, 1, 0.01, 1, _("Exponent for specular term, larger is more \"shiny\".")); - _settings->add_dualspinslider(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1); + _settings->add_spinscale(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.1, 0.01, 2, _("This value amplifies the heights of the bump map defined by the input alpha channel")); + _settings->add_spinscale(1, SP_ATTR_SPECULARCONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model.")); + _settings->add_spinscale(1, SP_ATTR_SPECULAREXPONENT, _("Exponent:"), 1, 50, 1, 0.01, 1, _("Exponent for specular term, larger is more \"shiny\".")); + _settings->add_dualspinscale(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1); _settings->add_lightsource(); _settings->type(NR_FILTER_TILE); @@ -2429,9 +2544,9 @@ void FilterEffectsDialog::init_settings_widgets() _settings->type(NR_FILTER_TURBULENCE); // _settings->add_checkbutton(false, SP_ATTR_STITCHTILES, _("Stitch Tiles"), "stitch", "noStitch"); _settings->add_combo(TURBULENCE_TURBULENCE, SP_ATTR_TYPE, _("Type:"), TurbulenceTypeConverter, _("Indicates whether the filter primitive should perform a noise or turbulence function.")); - _settings->add_dualspinslider(SP_ATTR_BASEFREQUENCY, _("Base Frequency:"), 0, 1, 0.001, 0.01, 3); - _settings->add_spinslider(1, SP_ATTR_NUMOCTAVES, _("Octaves:"), 1, 10, 1, 1, 0); - _settings->add_spinslider(0, SP_ATTR_SEED, _("Seed:"), 0, 1000, 1, 1, 0, _("The starting number for the pseudo random number generator.")); + _settings->add_dualspinscale(SP_ATTR_BASEFREQUENCY, _("Base Frequency:"), 0, 1, 0.001, 0.01, 3); + _settings->add_spinscale(1, SP_ATTR_NUMOCTAVES, _("Octaves:"), 1, 10, 1, 1, 0); + _settings->add_spinscale(0, SP_ATTR_SEED, _("Seed:"), 0, 1000, 1, 1, 0, _("The starting number for the pseudo random number generator.")); } void FilterEffectsDialog::add_primitive() @@ -2614,11 +2729,7 @@ void FilterEffectsDialog::update_filter_general_settings_view() } else { std::vector<Gtk::Widget*> vect = _settings_tab2.get_children(); -#if WITH_GTKMM_2_24 vect[0]->hide(); -#else - vect[0]->hide_all(); -#endif _no_filter_selected.show(); } @@ -2637,11 +2748,7 @@ void FilterEffectsDialog::update_settings_view() std::vector<Gtk::Widget*> vect1 = _settings_tab1.get_children(); for(unsigned int i=0; i<vect1.size(); i++) -#if WITH_GTKMM_2_24 vect1[i]->hide(); -#else - vect1[i]->hide_all(); -#endif _empty_settings.show(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -2665,11 +2772,7 @@ void FilterEffectsDialog::update_settings_view() //Second Tab std::vector<Gtk::Widget*> vect2 = _settings_tab2.get_children(); -#if WITH_GTKMM_2_24 vect2[0]->hide(); -#else - vect2[0]->hide_all(); -#endif _no_filter_selected.show(); SPFilter* filter = _filter_modifier.get_selected_filter(); diff --git a/src/ui/dialog/filter-effects-dialog.h b/src/ui/dialog/filter-effects-dialog.h index 38811354e..1652a314f 100644 --- a/src/ui/dialog/filter-effects-dialog.h +++ b/src/ui/dialog/filter-effects-dialog.h @@ -20,6 +20,7 @@ #include "sp-filter.h" #include "ui/widget/combo-enums.h" #include "ui/widget/spin-slider.h" +#include "ui/widget/spin-scale.h" #include "xml/helper-observer.h" #include "ui/dialog/desktop-tracker.h" @@ -76,12 +77,8 @@ private: }; void setTargetDesktop(SPDesktop *desktop); - - void on_document_replaced(SPDesktop*, SPDocument*) - { - update_filters(); - } + void on_document_replaced(SPDesktop *desktop, SPDocument *document); void on_change_selection(); void on_modified_selection( guint flags ); diff --git a/src/ui/dialog/font-substitution.cpp b/src/ui/dialog/font-substitution.cpp index d449bad67..24588946e 100644 --- a/src/ui/dialog/font-substitution.cpp +++ b/src/ui/dialog/font-substitution.cpp @@ -207,7 +207,7 @@ GSList * FontSubstitution::getFontReplacedItems(SPDocument* doc, Glib::ustring * // Check if any document styles are not in the actual layout std::map<SPItem *, Glib::ustring>::const_iterator mapIter; - for (mapIter = mapFontStyles.begin(); mapIter != mapFontStyles.end(); mapIter++) { + for (mapIter = mapFontStyles.begin(); mapIter != mapFontStyles.end(); ++mapIter) { SPItem *item = mapIter->first; Glib::ustring fonts = mapIter->second; @@ -241,7 +241,7 @@ GSList * FontSubstitution::getFontReplacedItems(SPDocument* doc, Glib::ustring * } std::set<Glib::ustring>::const_iterator setIter; - for (setIter = setErrors.begin(); setIter != setErrors.end(); setIter++) { + for (setIter = setErrors.begin(); setIter != setErrors.end(); ++setIter) { Glib::ustring err = (*setIter); out->append(err + "\n"); g_warning("%s", err.c_str()); diff --git a/src/ui/dialog/glyphs.cpp b/src/ui/dialog/glyphs.cpp index 1eed8d804..eec904ee4 100644 --- a/src/ui/dialog/glyphs.cpp +++ b/src/ui/dialog/glyphs.cpp @@ -364,11 +364,7 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : scriptCombo = new Gtk::ComboBoxText(); for (std::map<GUnicodeScript, Glib::ustring>::iterator it = getScriptToName().begin(); it != getScriptToName().end(); ++it) { -#if WITH_GTKMM_2_24 scriptCombo->append(it->second); -#else - scriptCombo->append_text(it->second); -#endif } scriptCombo->set_active_text(getScriptToName()[G_UNICODE_SCRIPT_INVALID_CODE]); @@ -393,11 +389,7 @@ GlyphsPanel::GlyphsPanel(gchar const *prefsPath) : rangeCombo = new Gtk::ComboBoxText(); for ( std::vector<NamedRange>::iterator it = getRanges().begin(); it != getRanges().end(); ++it ) { -#if WITH_GTKMM_2_24 rangeCombo->append(it->second); -#else - rangeCombo->append_text(it->second); -#endif } rangeCombo->set_active_text(getRanges()[1].second); diff --git a/src/ui/dialog/guides.cpp b/src/ui/dialog/guides.cpp index d20f2a220..1f02002ca 100644 --- a/src/ui/dialog/guides.cpp +++ b/src/ui/dialog/guides.cpp @@ -168,30 +168,54 @@ void GuidelinePropertiesDialog::_setup() { Gtk::Box *mainVBox = get_vbox(); +#if WITH_GTKMM_3_0 + _layout_table.set_row_spacing(4); + _layout_table.set_column_spacing(4); +#else _layout_table.set_spacings(4); _layout_table.resize (3, 4); +#endif mainVBox->pack_start(_layout_table, false, false, 0); _label_name.set_label("foo0"); - _layout_table.attach(_label_name, - 0, 3, 0, 1, Gtk::FILL, Gtk::FILL); _label_name.set_alignment(0, 0.5); _label_descr.set_label("foo1"); - _layout_table.attach(_label_descr, - 0, 3, 1, 2, Gtk::FILL, Gtk::FILL); _label_descr.set_alignment(0, 0.5); + +#if WITH_GTKMM_3_0 + _label_name.set_halign(Gtk::ALIGN_FILL); + _label_name.set_valign(Gtk::ALIGN_FILL); + _layout_table.attach(_label_name, 0, 0, 3, 1); + + _label_descr.set_halign(Gtk::ALIGN_FILL); + _label_descr.set_valign(Gtk::ALIGN_FILL); + _layout_table.attach(_label_descr, 0, 1, 3, 1); + + _label_entry.set_halign(Gtk::ALIGN_FILL); + _label_entry.set_valign(Gtk::ALIGN_FILL); + _label_entry.set_hexpand(); + _layout_table.attach(_label_entry, 1, 2, 2, 1); + + _color.set_halign(Gtk::ALIGN_FILL); + _color.set_valign(Gtk::ALIGN_FILL); + _color.set_hexpand(); + _layout_table.attach(_color, 1, 3, 2, 1); +#else + _layout_table.attach(_label_name, + 0, 3, 0, 1, Gtk::FILL, Gtk::FILL); - // indent -// _layout_table.attach(*manage(new Gtk::Label(" ")), -// 0, 1, 2, 3, Gtk::FILL, Gtk::FILL, 10); + _layout_table.attach(_label_descr, + 0, 3, 1, 2, Gtk::FILL, Gtk::FILL); _layout_table.attach(_label_entry, 1, 3, 2, 3, Gtk::EXPAND | Gtk::FILL, Gtk::FILL); _layout_table.attach(_color, 1, 3, 3, 4, Gtk::EXPAND | Gtk::FILL, Gtk::FILL); +#endif + _color.signal_color_set().connect(sigc::mem_fun(*this, &GuidelinePropertiesDialog::_colorChanged)); @@ -211,6 +235,22 @@ void GuidelinePropertiesDialog::_setup() { _spin_button_y.setDigits(3); _spin_button_y.setIncrements(1.0, 10.0); _spin_button_y.setRange(-1e6, 1e6); + +#if WITH_GTKMM_3_0 + _spin_button_x.set_halign(Gtk::ALIGN_FILL); + _spin_button_x.set_valign(Gtk::ALIGN_FILL); + _spin_button_x.set_hexpand(); + _layout_table.attach(_spin_button_x, 1, 4, 1, 1); + + _spin_button_y.set_halign(Gtk::ALIGN_FILL); + _spin_button_y.set_valign(Gtk::ALIGN_FILL); + _spin_button_y.set_hexpand(); + _layout_table.attach(_spin_button_y, 1, 5, 1, 1); + + _unit_menu.set_halign(Gtk::ALIGN_FILL); + _unit_menu.set_valign(Gtk::ALIGN_FILL); + _layout_table.attach(_unit_menu, 2, 4, 1, 1); +#else _layout_table.attach(_spin_button_x, 1, 2, 4, 5, Gtk::EXPAND | Gtk::FILL, Gtk::FILL); _layout_table.attach(_spin_button_y, @@ -218,17 +258,33 @@ void GuidelinePropertiesDialog::_setup() { _layout_table.attach(_unit_menu, 2, 3, 4, 5, Gtk::FILL, Gtk::FILL); +#endif // angle spinbutton _spin_angle.setDigits(3); _spin_angle.setIncrements(1.0, 10.0); _spin_angle.setRange(-3600., 3600.); + +#if WITH_GTKMM_3_0 + _spin_angle.set_halign(Gtk::ALIGN_FILL); + _spin_angle.set_valign(Gtk::ALIGN_FILL); + _spin_angle.set_hexpand(); + _layout_table.attach(_spin_angle, 1, 6, 2, 1); + + // mode radio button + _relative_toggle.set_halign(Gtk::ALIGN_FILL); + _relative_toggle.set_valign(Gtk::ALIGN_FILL); + _relative_toggle.set_hexpand(); + _layout_table.attach(_relative_toggle, 1, 7, 2, 1); +#else _layout_table.attach(_spin_angle, 1, 3, 6, 7, Gtk::EXPAND | Gtk::FILL, Gtk::FILL); // mode radio button _layout_table.attach(_relative_toggle, 1, 3, 7, 8, Gtk::EXPAND | Gtk::FILL, Gtk::FILL); +#endif + _relative_toggle.signal_toggled().connect(sigc::mem_fun(*this, &GuidelinePropertiesDialog::_modeChanged)); _relative_toggle.set_active(_relative_toggle_status); diff --git a/src/ui/dialog/guides.h b/src/ui/dialog/guides.h index d06c3afc8..a15667152 100644 --- a/src/ui/dialog/guides.h +++ b/src/ui/dialog/guides.h @@ -11,8 +11,18 @@ #ifndef INKSCAPE_DIALOG_GUIDELINE_H #define INKSCAPE_DIALOG_GUIDELINE_H +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + #include <gtkmm/dialog.h> + +#if WITH_GTKMM_3_0 +#include <gtkmm/grid.h> +#else #include <gtkmm/table.h> +#endif + #include <gtkmm/label.h> #include <gtkmm/colorbutton.h> #include "ui/widget/button.h" @@ -62,7 +72,13 @@ private: SPDesktop *_desktop; SPGuide *_guide; + +#if WITH_GTKMM_3_0 + Gtk::Grid _layout_table; +#else Gtk::Table _layout_table; +#endif + Gtk::Label _label_name; Gtk::Label _label_descr; Inkscape::UI::Widget::CheckButton _relative_toggle; diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 62f48cce0..cc145c16b 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -47,7 +47,11 @@ #include "display/canvas-grid.h" #include "path-prefix.h" #include "io/resource.h" +#include "io/sys.h" #include "inkscape.h" +#include "shortcuts.h" +#include "document.h" + #ifdef HAVE_ASPELL # include <aspell.h> @@ -137,6 +141,7 @@ InkscapePreferences::InkscapePreferences() initPageRendering(); initPageSpellcheck(); + signalPresent().connect(sigc::mem_fun(*this, &InkscapePreferences::_presentPages)); //calculate the size request for this dialog @@ -200,7 +205,7 @@ void InkscapePreferences::AddDotSizeSpinbutton(DialogPage &p, Glib::ustring cons } -void StyleFromSelectionToTool(Glib::ustring const &prefs_path, StyleSwatch *swatch) +static void StyleFromSelectionToTool(Glib::ustring const &prefs_path, StyleSwatch *swatch) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (desktop == NULL) @@ -480,7 +485,7 @@ void InkscapePreferences::initPageTools() _misc_gradientangle.init("/dialogs/gradienteditor/angle", -359, 359, 1, 90, 0, false, false); _page_gradient.add_line( false, _("Linear gradient _angle:"), _misc_gradientangle, "", - _("Default angle of new linear gradients in degrees (clockwise from horizontal"), false); + _("Default angle of new linear gradients in degrees (clockwise from horizontal)"), false); //Dropper @@ -741,6 +746,8 @@ void InkscapePreferences::initPageUI() _grids_axonom.add_line( false, _("Major grid line every:"), _grids_axonom_empspacing, "", "", false); this->AddPage(_page_grids, _("Grids"), iter_ui, PREFS_PAGE_UI_GRIDS); + + initKeyboardShortcuts(iter_ui); } #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) @@ -811,7 +818,7 @@ void InkscapePreferences::initPageIO() _("Maximum mouse drag (in screen pixels) which is considered a click, not a drag"), false); _mouse_grabsize.init("/options/grabsize/value", 1, 7, 1, 2, 3, 0); - _page_mouse.add_line(false, _("_Handle size"), _mouse_grabsize, "", + _page_mouse.add_line(false, _("_Handle size:"), _mouse_grabsize, "", _("Set the relative size of node handles"), true); _mouse_use_ext_input.init( _("Use pressure-sensitive tablet (requires restart)"), "/options/useextinput/value", true); @@ -979,18 +986,10 @@ void InkscapePreferences::initPageIO() Glib::ustring current = prefs->getString( "/options/displayprofile/uri" ); gint index = 0; -#if WITH_GTKMM_2_24 _cms_display_profile.append(_("<none>")); -#else - _cms_display_profile.append_text(_("<none>")); -#endif index++; for ( std::vector<Glib::ustring>::iterator it = names.begin(); it != names.end(); ++it ) { -#if WITH_GTKMM_2_24 _cms_display_profile.append( *it ); -#else - _cms_display_profile.append_text( *it ); -#endif Glib::ustring path = CMSSystem::getPathForProfile(*it); if ( !path.empty() && path == current ) { _cms_display_profile.set_active(index); @@ -1005,11 +1004,7 @@ void InkscapePreferences::initPageIO() current = prefs->getString("/options/softproof/uri"); index = 0; for ( std::vector<Glib::ustring>::iterator it = names.begin(); it != names.end(); ++it ) { -#if WITH_GTKMM_2_24 _cms_proof_profile.append( *it ); -#else - _cms_proof_profile.append_text( *it ); -#endif Glib::ustring path = CMSSystem::getPathForProfile(*it); if ( !path.empty() && path == current ) { _cms_proof_profile.set_active(index); @@ -1041,10 +1036,14 @@ void InkscapePreferences::initPageIO() // Autosave options _save_autosave_enable.init( _("Enable autosave (requires restart)"), "/options/autosave/enable", false); _page_autosave.add_line(false, "", _save_autosave_enable, "", _("Automatically save the current document(s) at a given interval, thus minimizing loss in case of a crash"), false); + _save_autosave_path.init("/options/autosave/path", true); + if (prefs->getString("/options/autosave/path").empty()) { + // Show the default fallback "tmp dir" if autosave path is not set. + _save_autosave_path.set_text(Glib::get_tmp_dir()); + } + _page_autosave.add_line(false, C_("Filesystem", "Autosave _directory:"), _save_autosave_path, "", _("The directory where autosaves will be written. This should be an absolute path (starts with / on UNIX or a drive letter such as C: on Windows). "), false); _save_autosave_interval.init("/options/autosave/interval", 1.0, 10800.0, 1.0, 10.0, 10.0, true, false); _page_autosave.add_line(false, _("_Interval (in minutes):"), _save_autosave_interval, "", _("Interval (in minutes) at which document will be autosaved"), false); - _save_autosave_path.init("/options/autosave/path", true); - _page_autosave.add_line(false, C_("Filesystem", "_Path:"), _save_autosave_path, "", _("The directory where autosaves will be written"), false); _save_autosave_max.init("/options/autosave/max", 1.0, 100.0, 1.0, 10.0, 10.0, true, false); _page_autosave.add_line(false, _("_Maximum number of autosaves:"), _save_autosave_max, "", _("Maximum number of autosaved files; use this to limit the storage space used"), false); @@ -1163,9 +1162,11 @@ void InkscapePreferences::initPageBehavior() _scroll_auto_thres.init ( "/options/autoscrolldistance/value", -600.0, 600.0, 1.0, 1.0, -10.0, true, false); _page_scrolling.add_line( true, _("_Threshold:"), _scroll_auto_thres, _("pixels"), _("How far (in screen pixels) you need to be from the canvas edge to trigger autoscroll; positive is outside the canvas, negative is within the canvas"), false); +/* _scroll_space.init ( _("Left mouse button pans when Space is pressed"), "/options/spacepans/value", false); _page_scrolling.add_line( false, "", _scroll_space, "", _("When on, pressing and holding Space and dragging with left mouse button pans canvas (as in Adobe Illustrator); when off, Space temporarily switches to Selector tool (default)")); +*/ _wheel_zoom.init ( _("Mouse wheel zooms by default"), "/options/wheelzooms/value", false); _page_scrolling.add_line( false, "", _wheel_zoom, "", _("When on, mouse wheel zooms without Ctrl and scrolls canvas with Ctrl; when off, it zooms with Ctrl and scrolls without Ctrl")); @@ -1401,6 +1402,316 @@ void InkscapePreferences::initPageBitmaps() this->AddPage(_page_bitmaps, _("Bitmaps"), PREFS_PAGE_BITMAPS); } +void InkscapePreferences::initKeyboardShortcuts(Gtk::TreeModel::iterator iter_ui) +{ + std::vector<Glib::ustring> fileNames; + std::vector<Glib::ustring> fileLabels; + + sp_shortcut_get_file_names(&fileLabels, &fileNames); + + _kb_filelist.init( "/options/kbshortcuts/shortcutfile", &fileLabels[0], &fileNames[0], fileLabels.size(), fileNames[0]); + + Glib::ustring tooltip(_("Select a file of predefined shortcuts to use. Any customized shortcuts you create will be added seperately to ")); + tooltip += Glib::ustring(IO::Resource::get_path(IO::Resource::USER, IO::Resource::KEYS, "default.xml")); + + _page_keyshortcuts.add_line( false, _("Shortcut file:"), _kb_filelist, "", tooltip.c_str(), false); + + _kb_search.init("/options/kbshortcuts/value", true); + _page_keyshortcuts.add_line( false, _("Search:"), _kb_search, "", "", true); + + _kb_store = Gtk::TreeStore::create( _kb_columns ); + _kb_store->set_sort_column (_kb_columns.id, Gtk::SORT_ASCENDING ); + + _kb_filter = Gtk::TreeModelFilter::create(_kb_store); + _kb_filter->set_visible_func (sigc::mem_fun(*this, &InkscapePreferences::onKBSearchFilter)); + + _kb_shortcut_renderer.property_editable() = true; + + _kb_tree.set_model(_kb_filter); + _kb_tree.append_column(_("Name"), _kb_columns.name); + _kb_tree.append_column(_("Shortcut"), _kb_shortcut_renderer); + _kb_tree.append_column(_("Description"), _kb_columns.description); + _kb_tree.append_column(_("ID"), _kb_columns.id); + + _kb_tree.set_expander_column(*_kb_tree.get_column(0)); + + _kb_tree.get_column(0)->set_resizable(true); + _kb_tree.get_column(0)->set_clickable(true); + _kb_tree.get_column(0)->set_fixed_width (200); + + _kb_tree.get_column(1)->set_resizable(true); + _kb_tree.get_column(1)->set_clickable(true); + _kb_tree.get_column(1)->set_fixed_width (150); + //_kb_tree.get_column(1)->add_attribute(_kb_shortcut_renderer.property_text(), _kb_columns.shortcut); + _kb_tree.get_column(1)->set_cell_data_func(_kb_shortcut_renderer, sigc::ptr_fun(InkscapePreferences::onKBShortcutRenderer)); + + _kb_tree.get_column(2)->set_resizable(true); + _kb_tree.get_column(2)->set_clickable(true); + + _kb_tree.get_column(3)->set_resizable(true); + _kb_tree.get_column(3)->set_clickable(true); + + _kb_shortcut_renderer.signal_accel_edited().connect( sigc::mem_fun(*this, &InkscapePreferences::onKBTreeEdited) ); + _kb_shortcut_renderer.signal_accel_cleared().connect( sigc::mem_fun(*this, &InkscapePreferences::onKBTreeCleared) ); + + Gtk::ScrolledWindow* scroller = new Gtk::ScrolledWindow(); + scroller->add(_kb_tree); + + int row = 3; + _page_keyshortcuts.attach(*scroller, 0, 2, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::EXPAND | Gtk::FILL); + row++; + + Gtk::HButtonBox *box_buttons = manage (new Gtk::HButtonBox); + box_buttons->set_layout(Gtk::BUTTONBOX_END); + box_buttons->set_spacing(4); + _page_keyshortcuts.attach(*box_buttons, 0, 3, row, row+1, Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK); + + UI::Widget::Button *kb_reset = manage(new UI::Widget::Button(_("Reset"), _("Remove all your customized keyboard shortcuts, and revert to the shortcuts in the shortcut file listed above"))); + box_buttons->pack_start(*kb_reset, true, true, 6); + box_buttons->set_child_secondary(*kb_reset); + + UI::Widget::Button *kb_import = manage(new UI::Widget::Button(_("Import ..."), _("Import custom keyboard shortcuts from a file"))); + box_buttons->pack_end(*kb_import, true, true, 6); + + UI::Widget::Button *kb_export = manage(new UI::Widget::Button(_("Export ..."), _("Export custom keyboard shortcuts to a file"))); + box_buttons->pack_end(*kb_export, true, true, 6); + + kb_reset->signal_clicked().connect( sigc::mem_fun(*this, &InkscapePreferences::onKBReset) ); + kb_import->signal_clicked().connect( sigc::mem_fun(*this, &InkscapePreferences::onKBImport) ); + kb_export->signal_clicked().connect( sigc::mem_fun(*this, &InkscapePreferences::onKBExport) ); + _kb_search.signal_key_release_event().connect( sigc::mem_fun(*this, &InkscapePreferences::onKBSearchKeyEvent) ); + _kb_filelist.signal_changed().connect( sigc::mem_fun(*this, &InkscapePreferences::onKBList) ); + _page_keyshortcuts.signal_realize().connect( sigc::mem_fun(*this, &InkscapePreferences::onKBRealize) ); + + this->AddPage(_page_keyshortcuts, _("Keyboard Shortcuts"), iter_ui, PREFS_PAGE_UI_KEYBOARD_SHORTCUTS); + + _kb_shortcuts_loaded = false; + Gtk::TreeStore::iterator iter_group = _kb_store->append(); + (*iter_group)[_kb_columns.name] = "Loading ..."; + (*iter_group)[_kb_columns.shortcut] = ""; + (*iter_group)[_kb_columns.id] = ""; + (*iter_group)[_kb_columns.description] = ""; + (*iter_group)[_kb_columns.shortcutid] = 0; + (*iter_group)[_kb_columns.user_set] = 0; + +} + +void InkscapePreferences::onKBList() +{ + sp_shortcut_init(); + onKBListKeyboardShortcuts(); +} + +void InkscapePreferences::onKBReset() +{ + sp_shortcuts_delete_all_from_file(); + sp_shortcut_init(); + onKBListKeyboardShortcuts(); +} + +void InkscapePreferences::onKBImport() +{ + if (sp_shortcut_file_import()) { + onKBListKeyboardShortcuts(); + } +} + +void InkscapePreferences::onKBExport() +{ + sp_shortcut_file_export(); +} + +bool InkscapePreferences::onKBSearchKeyEvent(GdkEventKey *event) +{ + _kb_filter->refilter(); + return FALSE; +} + +void InkscapePreferences::onKBTreeCleared(const Glib::ustring& path) +{ + Gtk::TreeModel::iterator iter = _kb_filter->get_iter(path); + Glib::ustring id = (*iter)[_kb_columns.id]; + unsigned int const current_shortcut_id = (*iter)[_kb_columns.shortcutid]; + + // Remove current shortcut from file + sp_shortcut_delete_from_file(id.c_str(), current_shortcut_id); + + sp_shortcut_init(); + onKBListKeyboardShortcuts(); + +} + +void InkscapePreferences::onKBTreeEdited (const Glib::ustring& path, guint accel_key, Gdk::ModifierType accel_mods, guint hardware_keycode) +{ + Gtk::TreeModel::iterator iter = _kb_filter->get_iter(path); + + Glib::ustring id = (*iter)[_kb_columns.id]; + Glib::ustring current_shortcut = (*iter)[_kb_columns.shortcut]; + unsigned int const current_shortcut_id = (*iter)[_kb_columns.shortcutid]; + + Inkscape::Verb *const verb = Inkscape::Verb::getbyid(id.c_str()); + if (!verb) { + return; + } + + unsigned int const new_shortcut_id = sp_gdkmodifier_to_shortcut(accel_key, accel_mods, hardware_keycode); + if (new_shortcut_id) { + + // Delete current shortcut if it existed + sp_shortcut_delete_from_file(id.c_str(), current_shortcut_id); + // Delete any references to the new shortcut + sp_shortcut_delete_from_file(id.c_str(), new_shortcut_id); + // Add the new shortcut + sp_shortcut_add_to_file(id.c_str(), new_shortcut_id); + + sp_shortcut_init(); + onKBListKeyboardShortcuts(); + } +} + +bool InkscapePreferences::onKBSearchFilter(const Gtk::TreeModel::const_iterator& iter) +{ + Glib::ustring search = _kb_search.get_text().lowercase(); + if (search.empty()) { + return TRUE; + } + + Glib::ustring name = (*iter)[_kb_columns.name]; + Glib::ustring desc = (*iter)[_kb_columns.description]; + Glib::ustring shortcut = (*iter)[_kb_columns.shortcut]; + Glib::ustring id = (*iter)[_kb_columns.id]; + + if (id.empty()) { + return TRUE; // Keep all group nodes visible + } + + return (name.lowercase().find(search) != name.npos + || shortcut.lowercase().find(search) != name.npos + || desc.lowercase().find(search) != name.npos + || id.lowercase().find(search) != name.npos); +} + +void InkscapePreferences::onKBRealize() +{ + if (!_kb_shortcuts_loaded /*&& _current_page == &_page_keyshortcuts*/) { + _kb_shortcuts_loaded = true; + onKBListKeyboardShortcuts(); + } +} + +InkscapePreferences::ModelColumns &InkscapePreferences::onKBGetCols() +{ + static InkscapePreferences::ModelColumns cols; + return cols; +} + +void InkscapePreferences::onKBShortcutRenderer(Gtk::CellRenderer *renderer, Gtk::TreeIter const &iter) { + + Glib::ustring shortcut = (*iter)[onKBGetCols().shortcut]; + unsigned int user_set = (*iter)[onKBGetCols().user_set]; + Gtk::CellRendererAccel *accel = dynamic_cast<Gtk::CellRendererAccel *>(renderer); + if (user_set) { + accel->property_markup() = Glib::ustring("<span foreground=\"blue\"> " + shortcut + " </span>").c_str(); + } else { + accel->property_markup() = Glib::ustring("<span> " + shortcut + " </span>").c_str(); + } +} + +void InkscapePreferences::onKBListKeyboardShortcuts() +{ + // Save the current selection + Gtk::TreeStore::iterator iter = _kb_tree.get_selection()->get_selected(); + Glib::ustring selected_id = ""; + if (iter) { + selected_id = (*iter)[_kb_columns.id]; + } + + _kb_store->clear(); + + std::vector<Verb *>verbs = Inkscape::Verb::getList(); + + for (unsigned int i = 0; i < verbs.size(); i++) { + + Inkscape::Verb* verb = verbs[i]; + if (!verb) { + continue; + } + if (!verb->get_name()){ + continue; + } + + Gtk::TreeStore::Path path; + if (_kb_store->iter_is_valid(_kb_store->get_iter("0"))) { + path = _kb_store->get_path(_kb_store->get_iter("0")); + } + + // Find this group in the tree + Glib::ustring group = verb->get_group() ? verb->get_group() : "Misc"; + Gtk::TreeStore::iterator iter_group; + bool found = false; + while (path) { + iter_group = _kb_store->get_iter(path); + if (!_kb_store->iter_is_valid(iter_group)) { + break; + } + Glib::ustring name = (*iter_group)[_kb_columns.name]; + if ((*iter_group)[_kb_columns.name] == group) { + found = true; + break; + } + path.next(); + } + + if (!found) { + // Add the group if not there + iter_group = _kb_store->append(); + (*iter_group)[_kb_columns.name] = group; + (*iter_group)[_kb_columns.shortcut] = ""; + (*iter_group)[_kb_columns.id] = ""; + (*iter_group)[_kb_columns.description] = ""; + (*iter_group)[_kb_columns.shortcutid] = 0; + (*iter_group)[_kb_columns.user_set] = 0; + } + + // Remove the key accelerators from the verb name + Glib::ustring name = verb->get_name(); + std::string::size_type k = 0; + while((k=name.find('_',k))!=name.npos) { + name.erase(k, 1); + } + + // Get the shortcut label + unsigned int shortcut_id = sp_shortcut_get_primary(verb); + Glib::ustring shortcut_label = ""; + if (shortcut_id != GDK_KEY_VoidSymbol) { + gchar* str = sp_shortcut_get_label(shortcut_id); + if (str) { + shortcut_label = str; + g_free(str); + str = 0; + } + } + // Add the verb to the group + Gtk::TreeStore::iterator row = _kb_store->append(iter_group->children()); + (*row)[_kb_columns.name] = name; + (*row)[_kb_columns.shortcut] = shortcut_label; + (*row)[_kb_columns.description] = verb->get_short_tip() ? verb->get_short_tip() : ""; + (*row)[_kb_columns.shortcutid] = shortcut_id; + (*row)[_kb_columns.id] = verb->get_id(); + (*row)[_kb_columns.user_set] = sp_shortcut_is_user_set(verb); + + if (selected_id == verb->get_id()) { + Gtk::TreeStore::Path sel_path = _kb_filter->convert_child_path_to_path(_kb_store->get_path(row)); + _kb_tree.expand_to_path(sel_path); + _kb_tree.get_selection()->select(sel_path); + } + } + + if (selected_id.empty()) { + _kb_tree.expand_to_path(_kb_store->get_path(_kb_store->get_iter("0:1"))); + } + +} void InkscapePreferences::initPageSpellcheck() { @@ -1605,7 +1916,7 @@ bool InkscapePreferences::PresentPage(const Gtk::TreeModel::iterator& iter) _page_list.expand_row(_path_tools, false); if (desired_page >= PREFS_PAGE_TOOLS_SHAPES && desired_page <= PREFS_PAGE_TOOLS_SHAPES_SPIRAL) _page_list.expand_row(_path_shapes, false); - if (desired_page >= PREFS_PAGE_UI && desired_page <= PREFS_PAGE_UI_GRIDS) + if (desired_page >= PREFS_PAGE_UI && desired_page <= PREFS_PAGE_UI_KEYBOARD_SHORTCUTS) _page_list.expand_row(_path_ui, false); if (desired_page >= PREFS_PAGE_BEHAVIOR && desired_page <= PREFS_PAGE_BEHAVIOR_MASKS) _page_list.expand_row(_path_behavior, false); diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h index d60035515..690016556 100644 --- a/src/ui/dialog/inkscape-preferences.h +++ b/src/ui/dialog/inkscape-preferences.h @@ -18,15 +18,19 @@ #include <iostream> #include <vector> #include "ui/widget/preferences-widget.h" +#include "ui/widget/button.h" +#include <stddef.h> #include <gtkmm/colorbutton.h> #include <gtkmm/comboboxtext.h> #include <gtkmm/treestore.h> #include <gtkmm/treeview.h> #include <gtkmm/frame.h> #include <gtkmm/notebook.h> -#include <stddef.h> #include <gtkmm/textview.h> #include <gtkmm/scrolledwindow.h> +#include <gtkmm/liststore.h> +#include <gtkmm/treemodel.h> +#include <gtkmm/treemodelfilter.h> #include "ui/widget/panel.h" @@ -60,6 +64,7 @@ enum { PREFS_PAGE_UI, PREFS_PAGE_UI_WINDOWS, PREFS_PAGE_UI_GRIDS, + PREFS_PAGE_UI_KEYBOARD_SHORTCUTS, PREFS_PAGE_BEHAVIOR, PREFS_PAGE_BEHAVIOR_SELECTING, PREFS_PAGE_BEHAVIOR_TRANSFORMS, @@ -79,6 +84,7 @@ enum { PREFS_PAGE_BITMAPS, PREFS_PAGE_RENDERING, PREFS_PAGE_SPELLCHECK + }; namespace Inkscape { @@ -166,6 +172,8 @@ protected: UI::Widget::DialogPage _page_bitmaps; UI::Widget::DialogPage _page_spellcheck; + UI::Widget::DialogPage _page_keyshortcuts; + UI::Widget::PrefSpinButton _mouse_sens; UI::Widget::PrefSpinButton _mouse_thres; UI::Widget::PrefSlider _mouse_grabsize; @@ -337,12 +345,16 @@ protected: UI::Widget::PrefCheckButton _spell_ignorenumbers; UI::Widget::PrefCheckButton _spell_ignoreallcaps; + UI::Widget::PrefCombo _misc_overs_bitmap; UI::Widget::PrefEntryFileButtonHBox _misc_bitmap_editor; UI::Widget::PrefCheckButton _misc_bitmap_autoreload; UI::Widget::PrefSpinButton _bitmap_copy_res; UI::Widget::PrefCombo _bitmap_import; + UI::Widget::PrefEntry _kb_search; + UI::Widget::PrefCombo _kb_filelist; + UI::Widget::PrefCheckButton _save_use_current_dir; UI::Widget::PrefCheckButton _save_autosave_enable; UI::Widget::PrefSpinButton _save_autosave_interval; @@ -411,6 +423,37 @@ protected: UI::Widget::PrefEntry _importexport_ocal_username; UI::Widget::PrefEntry _importexport_ocal_password; + /* + * Keyboard shortcut members + */ + class ModelColumns: public Gtk::TreeModel::ColumnRecord { + public: + ModelColumns() { + add(name); + add(id); + add(shortcut); + add(description); + add(shortcutid); + add(user_set); + } + virtual ~ModelColumns() { + } + + Gtk::TreeModelColumn<Glib::ustring> name; + Gtk::TreeModelColumn<Glib::ustring> id; + Gtk::TreeModelColumn<Glib::ustring> shortcut; + Gtk::TreeModelColumn<Glib::ustring> description; + Gtk::TreeModelColumn<unsigned int> shortcutid; + Gtk::TreeModelColumn<unsigned int> user_set; + }; + ModelColumns _kb_columns; + static ModelColumns &onKBGetCols(); + Glib::RefPtr<Gtk::TreeStore> _kb_store; + Gtk::TreeView _kb_tree; + Gtk::CellRendererAccel _kb_shortcut_renderer; + Glib::RefPtr<Gtk::TreeModelFilter> _kb_filter; + gboolean _kb_shortcuts_loaded; + int _max_dialog_width; int _max_dialog_height; int _sb_width; @@ -441,9 +484,26 @@ protected: void initPageBitmaps(); void initPageSystem(); void initPageI18n(); // Do we still need it? + void initKeyboardShortcuts(Gtk::TreeModel::iterator iter_ui); void _presentPages(); + /* + * Functions for the Keyboard shortcut editor panel + */ + void onKBReset(); + void onKBImport(); + void onKBExport(); + void onKBList(); + void onKBRealize(); + void onKBListKeyboardShortcuts(); + void onKBTreeEdited (const Glib::ustring& path, guint accel_key, Gdk::ModifierType accel_mods, guint hardware_keycode); + void onKBTreeCleared(const Glib::ustring& path_string); + bool onKBSearchKeyEvent(GdkEventKey *event); + bool onKBSearchFilter(const Gtk::TreeModel::const_iterator& iter); + static void onKBShortcutRenderer(Gtk::CellRenderer *rndr, Gtk::TreeIter const &iter); + + private: InkscapePreferences(); InkscapePreferences(InkscapePreferences const &d); diff --git a/src/ui/dialog/input.cpp b/src/ui/dialog/input.cpp index b3c1bddfd..4c567a6e3 100644 --- a/src/ui/dialog/input.cpp +++ b/src/ui/dialog/input.cpp @@ -357,6 +357,15 @@ static std::map<Gdk::InputMode, Glib::ustring> &getModeToString() return mapping; } +static int getModeId(Gdk::InputMode im) +{ + if (im == Gdk::MODE_DISABLED) return 0; + if (im == Gdk::MODE_SCREEN) return 1; + if (im == Gdk::MODE_WINDOW) return 2; + + return 0; +} + static std::map<Glib::ustring, Gdk::InputMode> &getStringToMode() { static std::map<Glib::ustring, Gdk::InputMode> mapping; @@ -400,15 +409,59 @@ private: static void setCellStateToggle(Gtk::CellRenderer *rndr, Gtk::TreeIter const &iter); void saveSettings(); + void onTreeSelect(); void useExtToggled(); - Glib::RefPtr<Gtk::TreeStore> store; - Gtk::TreeIter tabletIter; - Gtk::TreeView tree; - Gtk::ScrolledWindow treeScroller; + void onModeChange(); + void setKeys(gint count); + void setAxis(gint count); + + Glib::RefPtr<Gtk::TreeStore> confDeviceStore; + Gtk::TreeIter confDeviceIter; + Gtk::TreeView confDeviceTree; + Gtk::ScrolledWindow confDeviceScroller; Blink watcher; Gtk::CheckButton useExt; Gtk::Button save; + + Gtk::HPaned pane; + Gtk::VBox detailsBox; + Gtk::HBox titleFrame; + Gtk::Label titleLabel; + Inkscape::UI::Widget::Frame axisFrame; + Inkscape::UI::Widget::Frame keysFrame; + Gtk::VBox axisVBox; + Gtk::ComboBoxText modeCombo; + Gtk::Label modeLabel; + Gtk::HBox modeBox; + + class KeysColumns : public Gtk::TreeModel::ColumnRecord + { + public: + KeysColumns() + { + add(name); + add(value); + } + virtual ~KeysColumns() {} + + Gtk::TreeModelColumn<Glib::ustring> name; + Gtk::TreeModelColumn<Glib::ustring> value; + }; + + KeysColumns keysColumns; + KeysColumns axisColumns; + + Glib::RefPtr<Gtk::ListStore> axisStore; + Gtk::TreeView axisTree; + Gtk::ScrolledWindow axisScroll; + + Glib::RefPtr<Gtk::ListStore> keysStore; + Gtk::TreeView keysTree; + Gtk::ScrolledWindow keysScroll; + Gtk::CellRendererAccel _kb_shortcut_renderer; + + }; static DeviceModelColumns &getCols(); @@ -425,11 +478,11 @@ private: GdkInputSource lastSourceSeen; Glib::ustring lastDevnameSeen; - Glib::RefPtr<Gtk::TreeStore> store; - Gtk::TreeIter tabletIter; - Gtk::TreeView tree; - Inkscape::UI::Widget::Frame detailFrame; + Glib::RefPtr<Gtk::TreeStore> deviceStore; + Gtk::TreeIter deviceIter; + Gtk::TreeView deviceTree; Inkscape::UI::Widget::Frame testFrame; + Inkscape::UI::Widget::Frame axisFrame; Gtk::ScrolledWindow treeScroller; Gtk::ScrolledWindow detailScroller; Gtk::HPaned splitter; @@ -439,12 +492,13 @@ private: Gtk::Label devAxesCount; Gtk::ComboBoxText axesCombo; Gtk::ProgressBar axesValues[6]; + Gtk::Table axisTable; + Gtk::ComboBoxText buttonCombo; Gtk::ComboBoxText linkCombo; sigc::connection linkConnection; Gtk::Label keyVal; Gtk::Entry keyEntry; - Gtk::Table devDetails; Gtk::Notebook topHolder; Gtk::Image testThumb; Gtk::Image testButtons[24]; @@ -454,6 +508,7 @@ private: ConfPanel cfgPanel; + static void setupTree( Glib::RefPtr<Gtk::TreeStore> store, Gtk::TreeIter &tablet ); void setupValueAndCombo( gint reported, gint actual, Gtk::Label& label, Gtk::ComboBoxText& combo ); void updateTestButtons( Glib::ustring const& key, gint hotButton ); @@ -526,17 +581,17 @@ InputDialogImpl::InputDialogImpl() : lastSourceSeen((GdkInputSource)-1), lastDevnameSeen(""), - store(Gtk::TreeStore::create(getCols())), - tabletIter(), - tree(store), - detailFrame(), + deviceStore(Gtk::TreeStore::create(getCols())), + deviceIter(), + deviceTree(deviceStore), testFrame(_("Test Area")), + axisFrame(_("Axis")), treeScroller(), detailScroller(), splitter(), split2(), + axisTable(11, 2), linkCombo(), - devDetails(12, 2), topHolder(), imageTable(8, 7), testDetector(), @@ -547,10 +602,12 @@ InputDialogImpl::InputDialogImpl() : treeScroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); treeScroller.set_shadow_type(Gtk::SHADOW_IN); - treeScroller.add(tree); + treeScroller.add(deviceTree); treeScroller.set_size_request(50, 0); - split2.pack1(testFrame, false, false); - split2.pack2(detailFrame, true, true); + + split2.pack1(axisFrame, false, false); + split2.pack2(testFrame, true, true); + splitter.pack1(treeScroller); splitter.pack2(split2); @@ -585,54 +642,60 @@ InputDialogImpl::InputDialogImpl() : } - topHolder.append_page(cfgPanel, _("Configuration")); - topHolder.append_page(splitter, _("Hardware")); - topHolder.show_all(); - topHolder.set_current_page(0); + // This is a hidden preference to enable the "hardware" details in a separate tab + // By default this is not available to users + if (Preferences::get()->getBool("/dialogs/inputdevices/test")) { + topHolder.append_page(cfgPanel, _("Configuration")); + topHolder.append_page(splitter, _("Hardware")); + topHolder.show_all(); + topHolder.set_current_page(0); + contents->pack_start(topHolder); + } else { + contents->pack_start(cfgPanel); + } - contents->pack_start(topHolder); int rowNum = 0; /* Gtk::Label* lbl = Gtk::manage(new Gtk::Label(_("Name:"))); - devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1, + axisTable.attach(*lbl, 0, 1, rowNum, rowNum+ 1, ::Gtk::FILL, ::Gtk::SHRINK); - devDetails.attach(devName, 1, 2, rowNum, rowNum + 1, + axisTable.attach(devName, 1, 2, rowNum, rowNum + 1, ::Gtk::SHRINK, ::Gtk::SHRINK); rowNum++;*/ + axisFrame.add(axisTable); + Gtk::Label *lbl = Gtk::manage(new Gtk::Label(_("Link:"))); - devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1, + axisTable.attach(*lbl, 0, 1, rowNum, rowNum+ 1, ::Gtk::FILL, ::Gtk::SHRINK); -#if WITH_GTKMM_2_24 linkCombo.append(_("None")); -#else - linkCombo.append_text(_("None")); -#endif linkCombo.set_active_text(_("None")); linkCombo.set_sensitive(false); linkConnection = linkCombo.signal_changed().connect(sigc::mem_fun(*this, &InputDialogImpl::linkComboChanged)); - devDetails.attach(linkCombo, 1, 2, rowNum, rowNum + 1, + axisTable.attach(linkCombo, 1, 2, rowNum, rowNum + 1, ::Gtk::FILL, ::Gtk::SHRINK); rowNum++; + lbl = Gtk::manage(new Gtk::Label(_("Axes count:"))); - devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1, + axisTable.attach(*lbl, 0, 1, rowNum, rowNum+ 1, ::Gtk::FILL, ::Gtk::SHRINK); - devDetails.attach(devAxesCount, 1, 2, rowNum, rowNum + 1, + axisTable.attach(devAxesCount, 1, 2, rowNum, rowNum + 1, ::Gtk::SHRINK, ::Gtk::SHRINK); rowNum++; + /* lbl = Gtk::manage(new Gtk::Label(_("Actual axes count:"))); devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1, @@ -647,22 +710,24 @@ InputDialogImpl::InputDialogImpl() : for ( guint barNum = 0; barNum < static_cast<guint>(G_N_ELEMENTS(axesValues)); barNum++ ) { lbl = Gtk::manage(new Gtk::Label(_("axis:"))); - devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1, - ::Gtk::FILL, + axisTable.attach(*lbl, 0, 1, rowNum, rowNum+ 1, + ::Gtk::EXPAND, ::Gtk::SHRINK); - devDetails.attach(axesValues[barNum], 1, 2, rowNum, rowNum + 1, + axisTable.attach(axesValues[barNum], 1, 2, rowNum, rowNum + 1, ::Gtk::EXPAND, ::Gtk::SHRINK); axesValues[barNum].set_sensitive(false); rowNum++; + + } lbl = Gtk::manage(new Gtk::Label(_("Button count:"))); - devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1, + axisTable.attach(*lbl, 0, 1, rowNum, rowNum+ 1, ::Gtk::FILL, ::Gtk::SHRINK); - devDetails.attach(devKeyCount, 1, 2, rowNum, rowNum + 1, + axisTable.attach(devKeyCount, 1, 2, rowNum, rowNum + 1, ::Gtk::SHRINK, ::Gtk::SHRINK); @@ -680,7 +745,7 @@ InputDialogImpl::InputDialogImpl() : rowNum++; */ - devDetails.attach(keyVal, 0, 2, rowNum, rowNum + 1, + axisTable.attach(keyVal, 0, 2, rowNum, rowNum + 1, ::Gtk::FILL, ::Gtk::SHRINK); rowNum++; @@ -700,19 +765,18 @@ InputDialogImpl::InputDialogImpl() : #endif testDetector.add_events(Gdk::POINTER_MOTION_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK |Gdk::PROXIMITY_IN_MASK|Gdk::PROXIMITY_OUT_MASK|Gdk::SCROLL_MASK); - devDetails.attach(keyEntry, 0, 2, rowNum, rowNum + 1, + axisTable.attach(keyEntry, 0, 2, rowNum, rowNum + 1, ::Gtk::FILL, ::Gtk::SHRINK); rowNum++; - devDetails.set_sensitive(false); - detailScroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + axisTable.set_sensitive(false); + +/* detailScroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); detailScroller.set_shadow_type(Gtk::SHADOW_NONE); detailScroller.set_border_width (0); - detailScroller.add(devDetails); - detailFrame.add(detailScroller); - detailFrame.set_size_request(0, 60); + detailScroller.add(devDetails);*/ //- 16x16/devices // gnome-dev-mouse-optical @@ -721,25 +785,24 @@ InputDialogImpl::InputDialogImpl() : // mouse - //Add the TreeView's view columns: - tree.append_column("I", getCols().thumbnail); - tree.append_column("Bar", getCols().description); + deviceTree.append_column("I", getCols().thumbnail); + deviceTree.append_column("Bar", getCols().description); - tree.set_enable_tree_lines(); - tree.set_headers_visible(false); - tree.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &InputDialogImpl::resyncToSelection)); + deviceTree.set_enable_tree_lines(); + deviceTree.set_headers_visible(false); + deviceTree.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &InputDialogImpl::resyncToSelection)); - setupTree( store, tabletIter ); + setupTree( deviceStore, deviceIter ); Inkscape::DeviceManager::getManager().signalDeviceChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::handleDeviceChange)); Inkscape::DeviceManager::getManager().signalAxesChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceAxes)); Inkscape::DeviceManager::getManager().signalButtonsChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceButtons)); - Glib::RefPtr<Gtk::TreeView> treePtr(&tree); - Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::bind(sigc::ptr_fun(&InputDialogImpl::updateDeviceLinks), tabletIter, treePtr)); + Glib::RefPtr<Gtk::TreeView> treePtr(&deviceTree); + Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::bind(sigc::ptr_fun(&InputDialogImpl::updateDeviceLinks), deviceIter, treePtr)); - tree.expand_all(); + deviceTree.expand_all(); show_all_children(); } @@ -781,12 +844,30 @@ static Glib::ustring getCommon( std::list<Glib::ustring> const &names ) return result; } + +void InputDialogImpl::ConfPanel::onModeChange() +{ + Glib::ustring newText = modeCombo.get_active_text(); + + Glib::RefPtr<Gtk::TreeSelection> sel = confDeviceTree.get_selection(); + Gtk::TreeModel::iterator iter = sel->get_selected(); + if (iter) { + Glib::RefPtr<InputDevice const> dev = (*iter)[getCols().device]; + if (dev && (getStringToMode().find(newText) != getStringToMode().end())) { + Gdk::InputMode mode = getStringToMode()[newText]; + Inkscape::DeviceManager::getManager().setMode( dev->getId(), mode ); + } + } + +} + + void InputDialogImpl::setupTree( Glib::RefPtr<Gtk::TreeStore> store, Gtk::TreeIter &tablet ) { std::list<Glib::RefPtr<InputDevice const> > devList = Inkscape::DeviceManager::getManager().getDevices(); if ( !devList.empty() ) { - Gtk::TreeModel::Row row = *(store->append()); - row[getCols().description] = _("Hardware"); + //Gtk::TreeModel::Row row = *(store->append()); + //row[getCols().description] = _("Hardware"); // Let's make some tablets!!! std::list<TabletTmp> tablets; @@ -811,7 +892,7 @@ void InputDialogImpl::setupTree( Glib::RefPtr<Gtk::TreeStore> store, Gtk::TreeIt // Phase 2 - build a UI for the present devices for ( std::list<TabletTmp>::iterator it = tablets.begin(); it != tablets.end(); ++it ) { - tablet = store->append(row.children()); + tablet = store->prepend(/*row.children()*/); Gtk::TreeModel::Row childrow = *tablet; if ( it->name.empty() ) { // Check to see if we can derive one @@ -874,13 +955,14 @@ void InputDialogImpl::setupTree( Glib::RefPtr<Gtk::TreeStore> store, Gtk::TreeIt for ( std::list<Glib::RefPtr<InputDevice const> >::iterator it = devList.begin(); it != devList.end(); ++it ) { Glib::RefPtr<InputDevice const> dev = *it; if ( dev && (consumed.find( dev->getId() ) == consumed.end()) ) { - Gtk::TreeModel::Row deviceRow = *(store->append(row.children())); + Gtk::TreeModel::Row deviceRow = *(store->prepend(/*row.children()*/)); deviceRow[getCols().description] = dev->getName(); deviceRow[getCols().device] = dev; deviceRow[getCols().mode] = dev->getMode(); deviceRow[getCols().thumbnail] = getPix(PIX_CORE); } } + } else { g_warning("No devices found"); } @@ -889,84 +971,158 @@ void InputDialogImpl::setupTree( Glib::RefPtr<Gtk::TreeStore> store, Gtk::TreeIt InputDialogImpl::ConfPanel::ConfPanel() : Gtk::VBox(), - store(Gtk::TreeStore::create(getCols())), - tabletIter(), - tree(store), - treeScroller(), + confDeviceStore(Gtk::TreeStore::create(getCols())), + confDeviceIter(), + confDeviceTree(confDeviceStore), + confDeviceScroller(), watcher(*this), useExt(_("_Use pressure-sensitive tablet (requires restart)"), true), - save(_("_Save"), true) + save(_("_Save"), true), + detailsBox(false, 4), + titleFrame(false, 4), + titleLabel(""), + axisFrame(_("Axes")), + keysFrame(_("Keys")), + modeLabel(_("Mode")), + modeBox(false, 4) + { - pack_start(treeScroller); - treeScroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); - treeScroller.add(tree); - class Foo : public Gtk::TreeModel::ColumnRecord { + confDeviceScroller.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + confDeviceScroller.set_shadow_type(Gtk::SHADOW_IN); + confDeviceScroller.add(confDeviceTree); + confDeviceScroller.set_size_request(120, 0); + + /* class Foo : public Gtk::TreeModel::ColumnRecord { public : Gtk::TreeModelColumn<Glib::ustring> one; Foo() {add(one);} }; static Foo foo; - Glib::RefPtr<Gtk::ListStore> poppers = Gtk::ListStore::create(foo); - poppers->reference(); - - Gtk::TreeModel::Row row = *(poppers->append()); - row[foo.one] = getModeToString()[Gdk::MODE_DISABLED]; - row = *(poppers->append()); - row[foo.one] = getModeToString()[Gdk::MODE_SCREEN]; - row = *(poppers->append()); - row[foo.one] = getModeToString()[Gdk::MODE_WINDOW]; //Add the TreeView's view columns: { Gtk::CellRendererToggle *rendr = new Gtk::CellRendererToggle(); Gtk::TreeViewColumn *col = new Gtk::TreeViewColumn("xx", *rendr); if (col) { - tree.append_column(*col); + confDeviceTree.append_column(*col); col->set_cell_data_func(*rendr, sigc::ptr_fun(setCellStateToggle)); - rendr->signal_toggled().connect(sigc::bind(sigc::ptr_fun(commitCellStateChange), store)); + rendr->signal_toggled().connect(sigc::bind(sigc::ptr_fun(commitCellStateChange), confDeviceStore)); } - } + }*/ - int expPos = tree.append_column("", getCols().expander); + //int expPos = confDeviceTree.append_column("", getCols().expander); - tree.append_column("I", getCols().thumbnail); - tree.append_column("Bar", getCols().description); + confDeviceTree.append_column("I", getCols().thumbnail); + confDeviceTree.append_column("Bar", getCols().description); - { - Gtk::CellRendererCombo *rendr = new Gtk::CellRendererCombo(); - rendr->property_model().set_value(poppers); - rendr->property_text_column().set_value(0); - rendr->property_has_entry() = false; + //confDeviceTree.get_column(0)->set_fixed_width(100); + //confDeviceTree.get_column(1)->set_expand(); + +/* { Gtk::TreeViewColumn *col = new Gtk::TreeViewColumn("X", *rendr); if (col) { - tree.append_column(*col); + confDeviceTree.append_column(*col); col->set_cell_data_func(*rendr, sigc::ptr_fun(setModeCellString)); - rendr->signal_edited().connect(sigc::bind(sigc::ptr_fun(commitCellModeChange), store)); + rendr->signal_edited().connect(sigc::bind(sigc::ptr_fun(commitCellModeChange), confDeviceStore)); rendr->property_editable() = true; } - } + }*/ + + //confDeviceTree.set_enable_tree_lines(); + confDeviceTree.property_enable_tree_lines() = false; + confDeviceTree.property_enable_grid_lines() = false; + confDeviceTree.set_headers_visible(false); + //confDeviceTree.set_expander_column( *confDeviceTree.get_column(expPos - 1) ); - tree.set_enable_tree_lines(); - tree.set_headers_visible(false); - tree.set_expander_column( *tree.get_column(expPos - 1) ); + confDeviceTree.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &InputDialogImpl::ConfPanel::onTreeSelect)); - setupTree( store, tabletIter ); + setupTree( confDeviceStore, confDeviceIter ); - Glib::RefPtr<Gtk::TreeView> treePtr(&tree); - Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::bind(sigc::ptr_fun(&InputDialogImpl::updateDeviceLinks), tabletIter, treePtr)); + Glib::RefPtr<Gtk::TreeView> treePtr(&confDeviceTree); + Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::bind(sigc::ptr_fun(&InputDialogImpl::updateDeviceLinks), confDeviceIter, treePtr)); - tree.expand_all(); + confDeviceTree.expand_all(); useExt.set_active(Preferences::get()->getBool("/options/useextinput/value")); useExt.signal_toggled().connect(sigc::mem_fun(*this, &InputDialogImpl::ConfPanel::useExtToggled)); - pack_start(useExt, Gtk::PACK_SHRINK); + Gtk::HButtonBox *buttonBox = manage (new Gtk::HButtonBox); + buttonBox->set_layout (Gtk::BUTTONBOX_END); + //Gtk::Alignment *align = new Gtk::Alignment(Gtk::ALIGN_END, Gtk::ALIGN_START, 0, 0); + buttonBox->add(save); save.signal_clicked().connect(sigc::mem_fun(*this, &InputDialogImpl::ConfPanel::saveSettings)); - Gtk::Alignment *align = new Gtk::Alignment(Gtk::ALIGN_END, Gtk::ALIGN_START, 0, 0); - align->add(save); - pack_start(*Gtk::manage(align), Gtk::PACK_SHRINK); + + titleFrame.pack_start(titleLabel, true, true); + //titleFrame.set_shadow_type(Gtk::SHADOW_IN); + + modeCombo.append(getModeToString()[Gdk::MODE_DISABLED]); + modeCombo.append(getModeToString()[Gdk::MODE_SCREEN]); + modeCombo.append(getModeToString()[Gdk::MODE_WINDOW]); + modeCombo.set_tooltip_text(_("A device can be 'Disabled', its co-ordinates mapped to the whole 'Screen', or to a single (usually focused) 'Window'")); + modeCombo.signal_changed().connect(sigc::mem_fun(*this, &InputDialogImpl::ConfPanel::onModeChange)); + + modeBox.pack_start(modeLabel, false, false); + modeBox.pack_start(modeCombo, true, true); + + axisVBox.add(axisScroll); + axisFrame.add(axisVBox); + + keysFrame.add(keysScroll); + + /** + * Scrolled Window + */ + keysScroll.add(keysTree); + keysScroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + keysScroll.set_shadow_type(Gtk::SHADOW_IN); + keysScroll.set_size_request(120, 80); + + keysStore = Gtk::ListStore::create(keysColumns); + + _kb_shortcut_renderer.property_editable() = true; + + keysTree.set_model(keysStore); + keysTree.set_headers_visible(false); + keysTree.append_column("Name", keysColumns.name); + keysTree.append_column("Value", keysColumns.value); + + //keysTree.append_column("Value", _kb_shortcut_renderer); + //keysTree.get_column(1)->add_attribute(_kb_shortcut_renderer.property_text(), keysColumns.value); + //_kb_shortcut_renderer.signal_accel_edited().connect( sigc::mem_fun(*this, &InputDialogImpl::onKBTreeEdited) ); + //_kb_shortcut_renderer.signal_accel_cleared().connect( sigc::mem_fun(*this, &InputDialogImpl::onKBTreeCleared) ); + + axisStore = Gtk::ListStore::create(axisColumns); + + axisTree.set_model(axisStore); + axisTree.set_headers_visible(false); + axisTree.append_column("Name", axisColumns.name); + axisTree.append_column("Value", axisColumns.value); + + /** + * Scrolled Window + */ + axisScroll.add(axisTree); + axisScroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + axisScroll.set_shadow_type(Gtk::SHADOW_IN); + axisScroll.set_size_request(0, 150); + + pane.pack1(confDeviceScroller); + pane.pack2(detailsBox); + + detailsBox.pack_start(titleFrame, false, false, 6); + detailsBox.pack_start(modeBox, false, false, 6); + detailsBox.pack_start(axisFrame, false, false); + detailsBox.pack_start(keysFrame, false, false); + + pack_start(pane, true, true); + pack_start(useExt, Gtk::PACK_SHRINK); + pack_start(*buttonBox, false, false); + + // Select the first device + confDeviceTree.get_selection()->select(confDeviceStore->get_iter("0")); + } InputDialogImpl::ConfPanel::~ConfPanel() @@ -999,6 +1155,8 @@ void InputDialogImpl::ConfPanel::commitCellModeChange(Glib::ustring const &path, Inkscape::DeviceManager::getManager().setMode( dev->getId(), mode ); } } + + } void InputDialogImpl::ConfPanel::setCellStateToggle(Gtk::CellRenderer *rndr, Gtk::TreeIter const &iter) @@ -1033,6 +1191,25 @@ void InputDialogImpl::ConfPanel::commitCellStateChange(Glib::ustring const &path } } +void InputDialogImpl::ConfPanel::onTreeSelect() +{ + Glib::RefPtr<Gtk::TreeSelection> treeSel = confDeviceTree.get_selection(); + Gtk::TreeModel::iterator iter = treeSel->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + Glib::ustring val = row[getCols().description]; + Glib::RefPtr<InputDevice const> dev = row[getCols().device]; + Gdk::InputMode mode = (*iter)[getCols().mode]; + modeCombo.set_active(getModeId(mode)); + + titleLabel.set_markup("<b>" + row[getCols().description] + "</b>"); + + if (dev) { + setKeys(dev->getNumKeys()); + setAxis(dev->getNumAxes()); + } + } +} void InputDialogImpl::ConfPanel::saveSettings() { Inkscape::DeviceManager::getManager().saveConfig(); @@ -1074,8 +1251,8 @@ void InputDialogImpl::handleDeviceChange(Glib::RefPtr<InputDevice const> device) { // g_message("OUCH!!!! for %p hits %s", &device, device->getId().c_str()); std::vector<Glib::RefPtr<Gtk::TreeStore> > stores; - stores.push_back(store); - stores.push_back(cfgPanel.store); + stores.push_back(deviceStore); + stores.push_back(cfgPanel.confDeviceStore); for (std::vector<Glib::RefPtr<Gtk::TreeStore> >::iterator it = stores.begin(); it != stores.end(); ++it) { Gtk::TreeModel::iterator deviceIter; @@ -1158,11 +1335,11 @@ bool InputDialogImpl::findDeviceByLink(const Gtk::TreeModel::iterator& iter, void InputDialogImpl::updateDeviceLinks(Glib::RefPtr<InputDevice const> device, Gtk::TreeIter tabletIter, Glib::RefPtr<Gtk::TreeView> tree) { - Glib::RefPtr<Gtk::TreeStore> store = Glib::RefPtr<Gtk::TreeStore>::cast_dynamic(tree->get_model()); + Glib::RefPtr<Gtk::TreeStore> deviceStore = Glib::RefPtr<Gtk::TreeStore>::cast_dynamic(tree->get_model()); // g_message("Links!!!! for %p hits [%s] with link of [%s]", &device, device->getId().c_str(), device->getLink().c_str()); Gtk::TreeModel::iterator deviceIter; - store->foreach_iter( sigc::bind<Glib::ustring, Gtk::TreeModel::iterator*>( + deviceStore->foreach_iter( sigc::bind<Glib::ustring, Gtk::TreeModel::iterator*>( sigc::ptr_fun(&InputDialogImpl::findDevice), device->getId(), &deviceIter) ); @@ -1180,16 +1357,16 @@ void InputDialogImpl::updateDeviceLinks(Glib::RefPtr<InputDevice const> device, Glib::ustring descr = (*deviceIter)[getCols().description]; Glib::RefPtr<Gdk::Pixbuf> thumb = (*deviceIter)[getCols().thumbnail]; - Gtk::TreeModel::Row deviceRow = *store->append(tabletIter->children()); + Gtk::TreeModel::Row deviceRow = *deviceStore->append(tabletIter->children()); deviceRow[getCols().description] = descr; deviceRow[getCols().thumbnail] = thumb; deviceRow[getCols().device] = dev; deviceRow[getCols().mode] = dev->getMode(); Gtk::TreeModel::iterator oldParent = deviceIter->parent(); - store->erase(deviceIter); + deviceStore->erase(deviceIter); if ( oldParent->children().empty() ) { - store->erase(oldParent); + deviceStore->erase(oldParent); } } } else { @@ -1197,7 +1374,7 @@ void InputDialogImpl::updateDeviceLinks(Glib::RefPtr<InputDevice const> device, if ( deviceIter->parent() == tabletIter ) { // Simple case. Not already linked - Gtk::TreeIter newGroup = store->append(tabletIter->children()); + Gtk::TreeIter newGroup = deviceStore->append(tabletIter->children()); (*newGroup)[getCols().description] = _("Pen"); (*newGroup)[getCols().thumbnail] = getPix(PIX_PEN); @@ -1205,7 +1382,7 @@ void InputDialogImpl::updateDeviceLinks(Glib::RefPtr<InputDevice const> device, Glib::ustring descr = (*deviceIter)[getCols().description]; Glib::RefPtr<Gdk::Pixbuf> thumb = (*deviceIter)[getCols().thumbnail]; - Gtk::TreeModel::Row deviceRow = *store->append(newGroup->children()); + Gtk::TreeModel::Row deviceRow = *deviceStore->append(newGroup->children()); deviceRow[getCols().description] = descr; deviceRow[getCols().thumbnail] = thumb; deviceRow[getCols().device] = dev; @@ -1213,7 +1390,7 @@ void InputDialogImpl::updateDeviceLinks(Glib::RefPtr<InputDevice const> device, Gtk::TreeModel::iterator linkIter; - store->foreach_iter( sigc::bind<Glib::ustring, Gtk::TreeModel::iterator*>( + deviceStore->foreach_iter( sigc::bind<Glib::ustring, Gtk::TreeModel::iterator*>( sigc::ptr_fun(&InputDialogImpl::findDeviceByLink), device->getId(), &linkIter) ); @@ -1222,22 +1399,22 @@ void InputDialogImpl::updateDeviceLinks(Glib::RefPtr<InputDevice const> device, descr = (*linkIter)[getCols().description]; thumb = (*linkIter)[getCols().thumbnail]; - deviceRow = *store->append(newGroup->children()); + deviceRow = *deviceStore->append(newGroup->children()); deviceRow[getCols().description] = descr; deviceRow[getCols().thumbnail] = thumb; deviceRow[getCols().device] = dev; deviceRow[getCols().mode] = dev->getMode(); Gtk::TreeModel::iterator oldParent = linkIter->parent(); - store->erase(linkIter); + deviceStore->erase(linkIter); if ( oldParent->children().empty() ) { - store->erase(oldParent); + deviceStore->erase(oldParent); } } Gtk::TreeModel::iterator oldParent = deviceIter->parent(); - store->erase(deviceIter); + deviceStore->erase(deviceIter); if ( oldParent->children().empty() ) { - store->erase(oldParent); + deviceStore->erase(oldParent); } tree->expand_row(Gtk::TreePath(newGroup), true); } @@ -1246,7 +1423,7 @@ void InputDialogImpl::updateDeviceLinks(Glib::RefPtr<InputDevice const> device, } void InputDialogImpl::linkComboChanged() { - Glib::RefPtr<Gtk::TreeSelection> treeSel = tree.get_selection(); + Glib::RefPtr<Gtk::TreeSelection> treeSel = deviceTree.get_selection(); Gtk::TreeModel::iterator iter = treeSel->get_selected(); if (iter) { Gtk::TreeModel::Row row = *iter; @@ -1272,34 +1449,26 @@ void InputDialogImpl::linkComboChanged() { void InputDialogImpl::resyncToSelection() { bool clear = true; - Glib::RefPtr<Gtk::TreeSelection> treeSel = tree.get_selection(); + Glib::RefPtr<Gtk::TreeSelection> treeSel = deviceTree.get_selection(); Gtk::TreeModel::iterator iter = treeSel->get_selected(); if (iter) { Gtk::TreeModel::Row row = *iter; Glib::ustring val = row[getCols().description]; Glib::RefPtr<InputDevice const> dev = row[getCols().device]; + if ( dev ) { - devDetails.set_sensitive(true); + axisTable.set_sensitive(true); linkConnection.block(); -#if WITH_GTKMM_2_24 linkCombo.remove_all(); linkCombo.append(_("None")); -#else - linkCombo.clear_items(); - linkCombo.append_text(_("None")); -#endif linkCombo.set_active(0); if ( dev->getSource() != Gdk::SOURCE_MOUSE ) { Glib::ustring linked = dev->getLink(); std::list<Glib::RefPtr<InputDevice const> > devList = Inkscape::DeviceManager::getManager().getDevices(); for ( std::list<Glib::RefPtr<InputDevice const> >::const_iterator it = devList.begin(); it != devList.end(); ++it ) { if ( ((*it)->getSource() != Gdk::SOURCE_MOUSE) && ((*it) != dev) ) { -#if WITH_GTKMM_2_24 linkCombo.append((*it)->getName().c_str()); -#else - linkCombo.append_text((*it)->getName().c_str()); -#endif if ( (linked.length() > 0) && (linked == (*it)->getId()) ) { linkCombo.set_active_text((*it)->getName().c_str()); } @@ -1313,39 +1482,70 @@ void InputDialogImpl::resyncToSelection() { clear = false; devName.set_label(row[getCols().description]); - detailFrame.set_label(row[getCols().description]); + axisFrame.set_label(row[getCols().description]); setupValueAndCombo( dev->getNumAxes(), dev->getNumAxes(), devAxesCount, axesCombo); setupValueAndCombo( dev->getNumKeys(), dev->getNumKeys(), devKeyCount, buttonCombo); + + } } - devDetails.set_sensitive(!clear); + axisTable.set_sensitive(!clear); if (clear) { - detailFrame.set_label(""); + axisFrame.set_label(""); devName.set_label(""); devAxesCount.set_label(""); devKeyCount.set_label(""); } } +void InputDialogImpl::ConfPanel::setAxis(gint count) +{ + /* + * TODO - Make each axis editable + */ + axisStore->clear(); + + static Glib::ustring axesLabels[6] = {_("X"), _("Y"), _("Pressure"), _("X tilt"), _("Y tilt"), _("Wheel")}; + + for ( gint barNum = 0; barNum < static_cast<gint>(G_N_ELEMENTS(axesLabels)); barNum++ ) { + + Gtk::TreeModel::Row row = *(axisStore->append()); + row[axisColumns.name] = axesLabels[barNum]; + if (barNum < count) { + row[axisColumns.value] = Glib::ustring::format(barNum+1); + } else { + row[axisColumns.value] = _("None"); + } + } + +} +void InputDialogImpl::ConfPanel::setKeys(gint count) +{ + /* + * TODO - Make each key assignable + */ + + keysStore->clear(); + + for (gint i = 0; i < count; i++) { + Gtk::TreeModel::Row row = *(keysStore->append()); + row[keysColumns.name] = Glib::ustring::format(i+1); + row[keysColumns.value] = _("Disabled"); + } + + +} void InputDialogImpl::setupValueAndCombo( gint reported, gint actual, Gtk::Label& label, Gtk::ComboBoxText& combo ) { gchar *tmp = g_strdup_printf("%d", reported); label.set_label(tmp); g_free(tmp); -#if WITH_GTKMM_2_24 combo.remove_all(); -#else - combo.clear_items(); -#endif for ( gint i = 1; i <= reported; ++i ) { tmp = g_strdup_printf("%d", i); -#if WITH_GTKMM_2_24 combo.append(tmp); -#else - combo.append_text(tmp); -#endif g_free(tmp); } @@ -1371,9 +1571,9 @@ void InputDialogImpl::updateTestButtons( Glib::ustring const& key, gint hotButto void InputDialogImpl::updateTestAxes( Glib::ustring const& key, GdkDevice* dev ) { - static gdouble epsilon = 0.0001; + //static gdouble epsilon = 0.0001; { - Glib::RefPtr<Gtk::TreeSelection> treeSel = tree.get_selection(); + Glib::RefPtr<Gtk::TreeSelection> treeSel = deviceTree.get_selection(); Gtk::TreeModel::iterator iter = treeSel->get_selected(); if (iter) { Gtk::TreeModel::Row row = *iter; @@ -1385,7 +1585,6 @@ void InputDialogImpl::updateTestAxes( Glib::ustring const& key, GdkDevice* dev ) } } - for ( gint i = 0; i < static_cast<gint>(G_N_ELEMENTS(testAxes)); i++ ) { if ( axesMap[key].find(i) != axesMap[key].end() ) { switch ( axesMap[key][i].first ) { @@ -1400,7 +1599,6 @@ void InputDialogImpl::updateTestAxes( Glib::ustring const& key, GdkDevice* dev ) testAxes[i].set(getPix(PIX_AXIS_OFF)); axesValues[i].set_sensitive(true); if ( dev && (i < static_cast<gint>(G_N_ELEMENTS(axesValues)) ) ) { - // FIXME: Device axis ranges are inaccessible in GTK+ 3 and // are deprecated in GTK+ 2. Progress-bar ranges are disabled // until we find an alternative solution diff --git a/src/ui/dialog/layer-properties.cpp b/src/ui/dialog/layer-properties.cpp index 465192aee..6a1bc829e 100644 --- a/src/ui/dialog/layer-properties.cpp +++ b/src/ui/dialog/layer-properties.cpp @@ -28,7 +28,10 @@ #include "sp-item.h" #include "verbs.h" #include "selection.h" - +#include "selection-chemistry.h" +#include "ui/icon-names.h" +#include "ui/widget/imagetoggler.h" +#include "event-context.h" namespace Inkscape { namespace UI { @@ -39,19 +42,36 @@ LayerPropertiesDialog::LayerPropertiesDialog() { Gtk::Box *mainVBox = get_vbox(); +#if WITH_GTKMM_3_0 + _layout_table.set_row_spacing(4); + _layout_table.set_column_spacing(4); +#else _layout_table.set_spacings(4); _layout_table.resize (1, 2); +#endif // Layer name widgets _layer_name_entry.set_activates_default(true); _layer_name_label.set_label(_("Layer name:")); _layer_name_label.set_alignment(1.0, 0.5); +#if WITH_GTKMM_3_0 + _layer_name_label.set_halign(Gtk::ALIGN_FILL); + _layer_name_label.set_valign(Gtk::ALIGN_FILL); + _layout_table.attach(_layer_name_label, 0, 0, 1, 1); + + _layer_name_entry.set_halign(Gtk::ALIGN_FILL); + _layer_name_entry.set_valign(Gtk::ALIGN_FILL); + _layer_name_entry.set_hexpand(); + _layout_table.attach(_layer_name_entry, 1, 0, 1, 1); +#else _layout_table.attach(_layer_name_label, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL); _layout_table.attach(_layer_name_entry, 1, 2, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::FILL); - mainVBox->pack_start(_layout_table, false, false, 4); +#endif + + mainVBox->pack_start(_layout_table, true, true, 4); // Buttons _close_button.set_use_stock(true); @@ -82,6 +102,7 @@ LayerPropertiesDialog::LayerPropertiesDialog() } LayerPropertiesDialog::~LayerPropertiesDialog() { + _setDesktop(NULL); _setLayer(NULL); } @@ -145,7 +166,9 @@ LayerPropertiesDialog::_setup_position_controls() { _layer_position_combo.set_cell_data_func(_label_renderer, sigc::mem_fun(*this, &LayerPropertiesDialog::_prepareLabelRenderer)); +#if !WITH_GTKMM_3_0 _layout_table.resize (2, 2); +#endif Gtk::ListStore::iterator row; row = _dropdown_list->append(); @@ -159,15 +182,162 @@ LayerPropertiesDialog::_setup_position_controls() { row->set_value(_dropdown_columns.position, LPOS_CHILD); row->set_value(_dropdown_columns.name, Glib::ustring(_("As sublayer of current"))); - _layout_table.attach(_layer_position_combo, - 1, 2, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::FILL); _layer_position_label.set_label(_("Position:")); _layer_position_label.set_alignment(1.0, 0.5); + +#if WITH_GTKMM_3_0 + _layer_position_combo.set_halign(Gtk::ALIGN_FILL); + _layer_position_combo.set_valign(Gtk::ALIGN_FILL); + _layer_position_combo.set_hexpand(); + _layout_table.attach(_layer_position_combo, 1, 1, 1, 1); + + _layer_position_label.set_halign(Gtk::ALIGN_FILL); + _layer_position_label.set_valign(Gtk::ALIGN_FILL); + _layout_table.attach(_layer_position_label, 0, 1, 1, 1); +#else + _layout_table.attach(_layer_position_combo, + 1, 2, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::FILL); _layout_table.attach(_layer_position_label, 0, 1, 1, 2, Gtk::FILL, Gtk::FILL); +#endif + + show_all_children(); +} + +void +LayerPropertiesDialog::_setup_layers_controls() { + + ModelColumns *zoop = new ModelColumns(); + _model = zoop; + _store = Gtk::TreeStore::create( *zoop ); + _tree.set_model( _store ); + _tree.set_headers_visible(false); + + Inkscape::UI::Widget::ImageToggler *eyeRenderer = manage( new Inkscape::UI::Widget::ImageToggler( + INKSCAPE_ICON("object-visible"), INKSCAPE_ICON("object-hidden")) ); + int visibleColNum = _tree.append_column("vis", *eyeRenderer) - 1; + Gtk::TreeViewColumn* col = _tree.get_column(visibleColNum); + if ( col ) { + col->add_attribute( eyeRenderer->property_active(), _model->_colVisible ); + } + + Inkscape::UI::Widget::ImageToggler * renderer = manage( new Inkscape::UI::Widget::ImageToggler( + INKSCAPE_ICON("object-locked"), INKSCAPE_ICON("object-unlocked")) ); + int lockedColNum = _tree.append_column("lock", *renderer) - 1; + col = _tree.get_column(lockedColNum); + if ( col ) { + col->add_attribute( renderer->property_active(), _model->_colLocked ); + } + + Gtk::CellRendererText *_text_renderer = manage(new Gtk::CellRendererText()); + int nameColNum = _tree.append_column("Name", *_text_renderer) - 1; + Gtk::TreeView::Column *_name_column = _tree.get_column(nameColNum); + _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel); + + _tree.set_expander_column( *_tree.get_column(nameColNum) ); + _tree.signal_key_press_event().connect( sigc::mem_fun(*this, &LayerPropertiesDialog::_handleKeyEvent), false ); + _tree.signal_button_press_event().connect_notify( sigc::mem_fun(*this, &LayerPropertiesDialog::_handleButtonEvent) ); + + _scroller.add( _tree ); + _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + _scroller.set_shadow_type(Gtk::SHADOW_IN); + _scroller.set_size_request(220, 180); + + SPDocument* document = _desktop->doc(); + SPRoot* root = document->getRoot(); + if ( root ) { + SPObject* target = _desktop->currentLayer(); + _store->clear(); + _addLayer( document, SP_OBJECT(root), 0, target, 0 ); + } + + _layout_table.remove(_layer_name_entry); + _layout_table.remove(_layer_name_label); + +#if WITH_GTKMM_3_0 + _scroller.set_halign(Gtk::ALIGN_FILL); + _scroller.set_valign(Gtk::ALIGN_FILL); + _scroller.set_hexpand(); + _scroller.set_vexpand(); + _layout_table.attach(_scroller, 0, 1, 2, 1); +#else + _layout_table.attach(_scroller, + 0, 2, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::FILL | Gtk::EXPAND); +#endif + show_all_children(); } +void LayerPropertiesDialog::_addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level ) +{ + int _maxNestDepth = 20; + if ( _desktop && _desktop->layer_manager && layer && (level < _maxNestDepth) ) { + unsigned int counter = _desktop->layer_manager->childCount(layer); + for ( unsigned int i = 0; i < counter; i++ ) { + SPObject *child = _desktop->layer_manager->nthChildOf(layer, i); + if ( child ) { +#if DUMP_LAYERS + g_message(" %3d layer:%p {%s} [%s]", level, child, child->id, child->label() ); +#endif // DUMP_LAYERS + + Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend(); + Gtk::TreeModel::Row row = *iter; + row[_model->_colObject] = child; + row[_model->_colLabel] = child->label() ? child->label() : child->getId(); + row[_model->_colVisible] = SP_IS_ITEM(child) ? !SP_ITEM(child)->isHidden() : false; + row[_model->_colLocked] = SP_IS_ITEM(child) ? SP_ITEM(child)->isLocked() : false; + + if ( target && child == target ) { + _tree.expand_to_path( _store->get_path(iter) ); + + Glib::RefPtr<Gtk::TreeSelection> select = _tree.get_selection(); + select->select(iter); + + //_checkTreeSelection(); + } + + _addLayer( doc, child, &row, target, level + 1 ); + } + } + } +} + +SPObject* LayerPropertiesDialog::_selectedLayer() +{ + SPObject* obj = 0; + + Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); + if ( iter ) { + Gtk::TreeModel::Row row = *iter; + obj = row[_model->_colObject]; + } + + return obj; +} + +bool LayerPropertiesDialog::_handleKeyEvent(GdkEventKey *event) +{ + + switch (get_group0_keyval(event)) { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: { + _strategy->perform(*this); + _close(); + return true; + } + break; + } + return false; +} + +void LayerPropertiesDialog::_handleButtonEvent(GdkEventButton* event) +{ + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { + _strategy->perform(*this); + _close(); + } +} + /** Formats the label for a given layer row */ void LayerPropertiesDialog::_prepareLabelRenderer( @@ -202,8 +372,11 @@ void LayerPropertiesDialog::Rename::perform(LayerPropertiesDialog &dialog) { void LayerPropertiesDialog::Create::setup(LayerPropertiesDialog &dialog) { dialog.set_title(_("Add Layer")); - //TODO: find an unused layer number, forming name from _("Layer ") + "%d" - dialog._layer_name_entry.set_text(_("Layer")); + + // Set the initial name to the "next available" layer name + LayerManager *mgr = dialog._desktop->layer_manager; + Glib::ustring newName = mgr->getNextLayerName(NULL, dialog._desktop->currentLayer()->label()); + dialog._layer_name_entry.set_text(newName.c_str()); dialog._apply_button.set_label(_("_Add")); dialog._setup_position_controls(); } @@ -231,6 +404,20 @@ void LayerPropertiesDialog::Create::perform(LayerPropertiesDialog &dialog) { desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("New layer created.")); } +void LayerPropertiesDialog::Move::setup(LayerPropertiesDialog &dialog) { + dialog.set_title(_("Move to Layer")); + //TODO: find an unused layer number, forming name from _("Layer ") + "%d" + dialog._layer_name_entry.set_text(_("Layer")); + dialog._apply_button.set_label(_("_Move")); + dialog._setup_layers_controls(); +} + +void LayerPropertiesDialog::Move::perform(LayerPropertiesDialog &dialog) { + + SPObject *moveto = dialog._selectedLayer(); + sp_selection_to_layer(dialog._desktop, moveto, false); +} + void LayerPropertiesDialog::_setDesktop(SPDesktop *desktop) { if (desktop) { Inkscape::GC::anchor (desktop); diff --git a/src/ui/dialog/layer-properties.h b/src/ui/dialog/layer-properties.h index c7d7de130..9de303f89 100644 --- a/src/ui/dialog/layer-properties.h +++ b/src/ui/dialog/layer-properties.h @@ -12,14 +12,28 @@ #ifndef INKSCAPE_DIALOG_LAYER_PROPERTIES_H #define INKSCAPE_DIALOG_LAYER_PROPERTIES_H +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + #include <gtkmm/dialog.h> #include <gtkmm/entry.h> #include <gtkmm/label.h> + +#if WITH_GTKMM_3_0 +#include <gtkmm/grid.h> +#else #include <gtkmm/table.h> +#endif + #include <gtkmm/combobox.h> #include <gtkmm/liststore.h> +#include <gtkmm/treeview.h> +#include <gtkmm/treestore.h> +#include <gtkmm/scrolledwindow.h> #include "layer-fns.h" +#include "ui/widget/layer-selector.h" class SPDesktop; @@ -40,6 +54,9 @@ class LayerPropertiesDialog : public Gtk::Dialog { static void showCreate(SPDesktop *desktop, SPObject *layer) { _showDialog(Create::instance(), desktop, layer); } + static void showMove(SPDesktop *desktop, SPObject *layer) { + _showDialog(Move::instance(), desktop, layer); + } protected: struct Strategy { @@ -57,9 +74,15 @@ protected: void setup(LayerPropertiesDialog &dialog); void perform(LayerPropertiesDialog &dialog); }; + struct Move : public Strategy { + static Move &instance() { static Move instance; return instance; } + void setup(LayerPropertiesDialog &dialog); + void perform(LayerPropertiesDialog &dialog); + }; friend class Rename; friend class Create; + friend class Move; Strategy *_strategy; SPDesktop *_desktop; @@ -79,9 +102,40 @@ protected: Gtk::Entry _layer_name_entry; Gtk::Label _layer_position_label; Gtk::ComboBox _layer_position_combo; + +#if WITH_GTKMM_3_0 + Gtk::Grid _layout_table; +#else Gtk::Table _layout_table; +#endif + bool _position_visible; + class ModelColumns : public Gtk::TreeModel::ColumnRecord + { + public: + + ModelColumns() + { + add(_colObject); + add(_colVisible); + add(_colLocked); + add(_colLabel); + } + virtual ~ModelColumns() {} + + Gtk::TreeModelColumn<SPObject*> _colObject; + Gtk::TreeModelColumn<Glib::ustring> _colLabel; + Gtk::TreeModelColumn<bool> _colVisible; + Gtk::TreeModelColumn<bool> _colLocked; + }; + + Gtk::TreeView _tree; + ModelColumns* _model; + Glib::RefPtr<Gtk::TreeStore> _store; + Gtk::ScrolledWindow _scroller; + + PositionDropdownColumns _dropdown_columns; Gtk::CellRendererText _label_renderer; Glib::RefPtr<Gtk::ListStore> _dropdown_list; @@ -104,8 +158,14 @@ protected: void _close(); void _setup_position_controls(); + void _setup_layers_controls(); void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row); + void _addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level ); + SPObject* _selectedLayer(); + bool _handleKeyEvent(GdkEventKey *event); + void _handleButtonEvent(GdkEventButton* event); + private: LayerPropertiesDialog(LayerPropertiesDialog const &); // no copy LayerPropertiesDialog &operator=(LayerPropertiesDialog const &); // no assign diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp index 70cf7075c..4f7b8f27c 100644 --- a/src/ui/dialog/layers.cpp +++ b/src/ui/dialog/layers.cpp @@ -69,6 +69,9 @@ enum { BUTTON_SOLO, BUTTON_SHOW_ALL, BUTTON_HIDE_ALL, + BUTTON_LOCK_OTHERS, + BUTTON_LOCK_ALL, + BUTTON_UNLOCK_ALL, DRAGNDROP }; @@ -263,6 +266,21 @@ bool LayersPanel::_executeAction() _fireAction( SP_VERB_LAYER_HIDE_ALL ); } break; + case BUTTON_LOCK_OTHERS: + { + _fireAction( SP_VERB_LAYER_LOCK_OTHERS ); + } + break; + case BUTTON_LOCK_ALL: + { + _fireAction( SP_VERB_LAYER_LOCK_ALL ); + } + break; + case BUTTON_UNLOCK_ALL: + { + _fireAction( SP_VERB_LAYER_UNLOCK_ALL ); + } + break; case DRAGNDROP: { _doTreeMove( ); @@ -540,30 +558,76 @@ bool LayersPanel::_handleKeyEvent(GdkEventKey *event) } return false; } -void LayersPanel::_handleButtonEvent(GdkEventButton* event) + +bool LayersPanel::_handleButtonEvent(GdkEventButton* event) { static unsigned doubleclick = 0; - // TODO - fix to a better is-popup function if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) { + // TODO - fix to a better is-popup function + Gtk::TreeModel::Path path; + int x = static_cast<int>(event->x); + int y = static_cast<int>(event->y); + if ( _tree.get_path_at_pos( x, y, path ) ) { + _checkTreeSelection(); + _popupMenu.popup(event->button, event->time); + } + } - { - Gtk::TreeModel::Path path; - Gtk::TreeViewColumn* col = 0; - int x = static_cast<int>(event->x); - int y = static_cast<int>(event->y); - int x2 = 0; - int y2 = 0; - if ( _tree.get_path_at_pos( x, y, - path, col, - x2, y2 ) ) { - _checkTreeSelection(); - _popupMenu.popup(event->button, event->time); + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 1) + && (event->state & GDK_MOD1_MASK)) { + // Alt left click on the visible/lock columns - eat this event to keep row selection + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast<int>(event->x); + int y = static_cast<int>(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if (col == _tree.get_column(COL_VISIBLE-1) || + col == _tree.get_column(COL_LOCKED-1)) { + return true; } } + } + // TODO - ImageToggler doesn't seem to handle Shift/Alt clicks - so we deal with them here. + if ( (event->type == GDK_BUTTON_RELEASE) && (event->button == 1) + && (event->state & (GDK_SHIFT_MASK | GDK_MOD1_MASK))) { + + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast<int>(event->x); + int y = static_cast<int>(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if (event->state & GDK_SHIFT_MASK) { + // Shift left click on the visible/lock columns toggles "solo" mode + if (col == _tree.get_column(COL_VISIBLE - 1)) { + _takeAction(BUTTON_SOLO); + } else if (col == _tree.get_column(COL_LOCKED - 1)) { + _takeAction(BUTTON_LOCK_OTHERS); + } + } else if (event->state & GDK_MOD1_MASK) { + // Alt+left click on the visible/lock columns toggles "solo" mode and preserves selection + Gtk::TreeModel::iterator iter = _store->get_iter(path); + if (_store->iter_is_valid(iter)) { + Gtk::TreeModel::Row row = *iter; + SPObject *obj = row[_model->_colObject]; + if (col == _tree.get_column(COL_VISIBLE - 1)) { + _desktop->toggleLayerSolo( obj ); + DocumentUndo::maybeDone(_desktop->doc(), "layer:solo", SP_VERB_LAYER_SOLO, _("Toggle layer solo")); + } else if (col == _tree.get_column(COL_LOCKED - 1)) { + _desktop->toggleLockOtherLayers( obj ); + DocumentUndo::maybeDone(_desktop->doc(), "layer:lockothers", SP_VERB_LAYER_LOCK_OTHERS, _("Lock other layers")); + } + } + } + } } + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { doubleclick = 1; } @@ -584,6 +648,7 @@ void LayersPanel::_handleButtonEvent(GdkEventButton* event) } } + return false; } /* @@ -678,7 +743,7 @@ void LayersPanel::_renameLayer(Gtk::TreeModel::Row row, const Glib::ustring& nam if ( !name.empty() && (!oldLabel || name != oldLabel) ) { _desktop->layer_manager->renameLayer( obj, name.c_str(), FALSE ); DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, - _("Renamed layer")); + _("Rename layer")); } } @@ -780,8 +845,8 @@ LayersPanel::LayersPanel() : _text_renderer->signal_edited().connect( sigc::mem_fun(*this, &LayersPanel::_handleEdited) ); _text_renderer->signal_editing_canceled().connect( sigc::mem_fun(*this, &LayersPanel::_handleEditingCancelled) ); - _tree.signal_button_press_event().connect_notify( sigc::mem_fun(*this, &LayersPanel::_handleButtonEvent) ); - _tree.signal_button_release_event().connect_notify( sigc::mem_fun(*this, &LayersPanel::_handleButtonEvent) ); + _tree.signal_button_press_event().connect( sigc::mem_fun(*this, &LayersPanel::_handleButtonEvent), false ); + _tree.signal_button_release_event().connect( sigc::mem_fun(*this, &LayersPanel::_handleButtonEvent), false ); _tree.signal_key_press_event().connect( sigc::mem_fun(*this, &LayersPanel::_handleKeyEvent), false ); _scroller.add( _tree ); @@ -810,43 +875,34 @@ LayersPanel::LayersPanel() : SPDesktop* targetDesktop = getDesktop(); -#if !WITH_GTKMM_3_0 - // TODO: This has been removed from Gtkmm 3.0. Check that everything still - // looks OK! - _buttonsRow.set_child_min_width( 16 ); -#endif - - _buttonsRow.set_layout (Gtk::BUTTONBOX_END); - Gtk::Button* btn = manage( new Gtk::Button() ); _styleButton( *btn, targetDesktop, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, C_("Layers", "New") ); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_NEW) ); - _buttonsRow.add( *btn ); - _buttonsRow.set_child_secondary( *btn , true); + _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); btn = manage( new Gtk::Button() ); - _styleButton( *btn, targetDesktop, SP_VERB_LAYER_TO_TOP, GTK_STOCK_GOTO_TOP, C_("Layers", "Top") ); - btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_TOP) ); - _watchingNonTop.push_back( btn ); - _buttonsRow.add( *btn ); - - btn = manage( new Gtk::Button() ); - _styleButton( *btn, targetDesktop, SP_VERB_LAYER_RAISE, GTK_STOCK_GO_UP, C_("Layers", "Up") ); - btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_UP) ); - _watchingNonTop.push_back( btn ); - _buttonsRow.add( *btn ); - + _styleButton( *btn, targetDesktop, SP_VERB_LAYER_TO_BOTTOM, GTK_STOCK_GOTO_BOTTOM, C_("Layers", "Bot") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_BOTTOM) ); + _watchingNonBottom.push_back( btn ); + _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + btn = manage( new Gtk::Button() ); _styleButton( *btn, targetDesktop, SP_VERB_LAYER_LOWER, GTK_STOCK_GO_DOWN, C_("Layers", "Dn") ); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DOWN) ); _watchingNonBottom.push_back( btn ); - _buttonsRow.add( *btn ); - + _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + btn = manage( new Gtk::Button() ); - _styleButton( *btn, targetDesktop, SP_VERB_LAYER_TO_BOTTOM, GTK_STOCK_GOTO_BOTTOM, C_("Layers", "Bot") ); - btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_BOTTOM) ); - _watchingNonBottom.push_back( btn ); - _buttonsRow.add( *btn ); + _styleButton( *btn, targetDesktop, SP_VERB_LAYER_RAISE, GTK_STOCK_GO_UP, C_("Layers", "Up") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_UP) ); + _watchingNonTop.push_back( btn ); + _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + + btn = manage( new Gtk::Button() ); + _styleButton( *btn, targetDesktop, SP_VERB_LAYER_TO_TOP, GTK_STOCK_GOTO_TOP, C_("Layers", "Top") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_TOP) ); + _watchingNonTop.push_back( btn ); + _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); // btn = manage( new Gtk::Button("Dup") ); // btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DUPLICATE) ); @@ -856,9 +912,10 @@ LayersPanel::LayersPanel() : _styleButton( *btn, targetDesktop, SP_VERB_LAYER_DELETE, GTK_STOCK_REMOVE, _("X") ); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DELETE) ); _watching.push_back( btn ); - _buttonsRow.add( *btn ); - _buttonsRow.set_child_secondary( *btn , true); - + _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + + _buttonsRow.pack_start(_buttonsSecondary, Gtk::PACK_EXPAND_WIDGET); + _buttonsRow.pack_end(_buttonsPrimary, Gtk::PACK_EXPAND_WIDGET); @@ -876,6 +933,12 @@ LayersPanel::LayersPanel() : _popupMenu.append(*manage(new Gtk::SeparatorMenuItem())); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOCK_OTHERS, 0, "Lock Others", (int)BUTTON_LOCK_OTHERS ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOCK_ALL, 0, "Lock All", (int)BUTTON_LOCK_ALL ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_UNLOCK_ALL, 0, "Unlock All", (int)BUTTON_UNLOCK_ALL ) ); + + _popupMenu.append(*manage(new Gtk::SeparatorMenuItem())); + _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RAISE, GTK_STOCK_GO_UP, "Up", (int)BUTTON_UP ) ); _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOWER, GTK_STOCK_GO_DOWN, "Down", (int)BUTTON_DOWN ) ); diff --git a/src/ui/dialog/layers.h b/src/ui/dialog/layers.h index 12e5f7986..e9fd9ebc6 100644 --- a/src/ui/dialog/layers.h +++ b/src/ui/dialog/layers.h @@ -13,7 +13,6 @@ #define SEEN_LAYERS_PANEL_H #include <gtkmm/box.h> -#include <gtkmm/buttonbox.h> #include <gtkmm/treeview.h> #include <gtkmm/treestore.h> #include <gtkmm/scrolledwindow.h> @@ -65,7 +64,7 @@ private: void _preToggle( GdkEvent const *event ); void _toggled( Glib::ustring const& str, int targetCol ); - void _handleButtonEvent(GdkEventButton *event); + bool _handleButtonEvent(GdkEventButton *event); bool _handleKeyEvent(GdkEventKey *event); bool _handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time); void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); @@ -122,9 +121,13 @@ private: Gtk::CellRendererText *_text_renderer; Gtk::TreeView::Column *_name_column; #if WITH_GTKMM_3_0 - Gtk::ButtonBox _buttonsRow; + Gtk::Box _buttonsRow; + Gtk::Box _buttonsPrimary; + Gtk::Box _buttonsSecondary; #else - Gtk::HButtonBox _buttonsRow; + Gtk::HBox _buttonsRow; + Gtk::HBox _buttonsPrimary; + Gtk::HBox _buttonsSecondary; #endif Gtk::ScrolledWindow _scroller; Gtk::Menu _popupMenu; diff --git a/src/ui/dialog/livepatheffect-add.cpp b/src/ui/dialog/livepatheffect-add.cpp index c22aace37..e899dbcfc 100644 --- a/src/ui/dialog/livepatheffect-add.cpp +++ b/src/ui/dialog/livepatheffect-add.cpp @@ -48,6 +48,7 @@ LivePathEffectAdd::LivePathEffectAdd() : effectlist_treeview.set_model(effectlist_store); effectlist_treeview.set_headers_visible(false); effectlist_treeview.append_column("Name", _columns.name); + //effectlist_treeview.set_activates_default(true); /** * Initialize Effect list @@ -68,7 +69,7 @@ LivePathEffectAdd::LivePathEffectAdd() : * Buttons */ close_button.set_use_stock(true); - close_button.set_can_default(); + //close_button.set_can_default(); add_button.set_use_underline(true); add_button.set_can_default(); diff --git a/src/ui/dialog/object-attributes.cpp b/src/ui/dialog/object-attributes.cpp index f67c4db21..1ae9730d5 100644 --- a/src/ui/dialog/object-attributes.cpp +++ b/src/ui/dialog/object-attributes.cpp @@ -123,7 +123,7 @@ void ObjectAttributes::widget_setup (void) } blocked = true; - SPObject *obj = (SPObject*)item; //to get the selected item + 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); const SPAttrDesc *desc; diff --git a/src/ui/dialog/object-properties.cpp b/src/ui/dialog/object-properties.cpp index 0aeb3816f..12ee2f762 100644 --- a/src/ui/dialog/object-properties.cpp +++ b/src/ui/dialog/object-properties.cpp @@ -54,7 +54,7 @@ ObjectProperties::ObjectProperties (void) : LabelID(_("_ID:"), 1), LabelLabel(_("_Label:"), 1), LabelTitle(_("_Title:"),1), - LabelDescription(_("_Description"),1), + LabelDescription(_("_Description:"),1), FrameDescription("", FALSE), HBoxCheck(FALSE, 0), CheckTable(1, 2, TRUE), @@ -69,16 +69,15 @@ ObjectProperties::ObjectProperties (void) : subselChangedConn() { //initialize labels for the table at the bottom of the dialog - int_labels.push_back("onclick"); - int_labels.push_back("onmouseover"); - int_labels.push_back("onmouseout"); - int_labels.push_back("onmousedown"); - int_labels.push_back("onmouseup"); - int_labels.push_back("onmousemove"); - int_labels.push_back("onfocusin"); - int_labels.push_back("onfocusout"); - int_labels.push_back("onfocusout"); - int_labels.push_back("onload"); + int_labels.push_back("onclick:"); + int_labels.push_back("onmouseover:"); + int_labels.push_back("onmouseout:"); + int_labels.push_back("onmousedown:"); + int_labels.push_back("onmouseup:"); + int_labels.push_back("onmousemove:"); + int_labels.push_back("onfocusin:"); + int_labels.push_back("onfocusout:"); + int_labels.push_back("onload:"); desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &ObjectProperties::setTargetDesktop) ); deskTrack.connect(GTK_WIDGET(gobj())); @@ -101,10 +100,11 @@ void ObjectProperties::MakeWidget(void) TopTable.set_border_width(4); TopTable.set_row_spacings(4); - TopTable.set_col_spacings(4); - contents->pack_start (TopTable, true, true, 0); + TopTable.set_col_spacings(0); + contents->pack_start (TopTable, false, false, 0); /* Create the label for the object id */ + LabelID.set_label (LabelID.get_label() + " "); LabelID.set_alignment (1, 0.5); TopTable.attach (LabelID, 0, 1, 0, 1, Gtk::SHRINK | Gtk::FILL, @@ -124,6 +124,7 @@ void ObjectProperties::MakeWidget(void) EntryID.grab_focus(); /* Create the label for the object label */ + LabelLabel.set_label (LabelLabel.get_label() + " "); LabelLabel.set_alignment (1, 0.5); TopTable.attach (LabelLabel, 0, 1, 1, 2, Gtk::SHRINK | Gtk::FILL, @@ -141,6 +142,7 @@ void ObjectProperties::MakeWidget(void) EntryLabel.signal_activate().connect(sigc::mem_fun(this, &ObjectProperties::label_changed)); /* Create the label for the object title */ + LabelTitle.set_label (LabelTitle.get_label() + " "); LabelTitle.set_alignment (1, 0.5); TopTable.attach (LabelTitle, 0, 1, 2, 3, Gtk::SHRINK | Gtk::FILL, @@ -149,18 +151,17 @@ void ObjectProperties::MakeWidget(void) /* Create the entry box for the object title */ EntryTitle.set_sensitive (FALSE); EntryTitle.set_max_length (256); - TopTable.attach (EntryTitle, 1, 3, 2, 3, + TopTable.attach (EntryTitle, 1, 2, 2, 3, Gtk::EXPAND | Gtk::FILL, Gtk::AttachOptions(), 0, 0 ); LabelTitle.set_mnemonic_widget (EntryTitle); + // pressing enter in the label field is the same as clicking Set: + EntryTitle.signal_activate().connect(sigc::mem_fun(this, &ObjectProperties::label_changed)); /* Create the frame for the object description */ FrameDescription.set_label_widget (LabelDescription); - FrameDescription.set_padding (4,0,0,0); - - TopTable.attach (FrameDescription, 0, 3, 3, 4, - Gtk::EXPAND | Gtk::FILL, - Gtk::EXPAND | Gtk::FILL, 0, 0 ); + FrameDescription.set_padding (0,0,0,0); + contents->pack_start (FrameDescription, true, true, 0); /* Create the text view box for the object description */ FrameTextDescription.set_border_width(4); @@ -175,8 +176,8 @@ void ObjectProperties::MakeWidget(void) /* Check boxes */ contents->pack_start (HBoxCheck, FALSE, FALSE, 0); - CheckTable.set_border_width(0); - HBoxCheck.pack_start (CheckTable, TRUE, TRUE, 10); + CheckTable.set_border_width(4); + HBoxCheck.pack_start (CheckTable, TRUE, TRUE, 0); /* Hide */ CBHide.set_tooltip_text (_("Check to make the object invisible")); @@ -195,7 +196,9 @@ void ObjectProperties::MakeWidget(void) /* Button for setting the object's id, label, title and description. */ - HBoxCheck.pack_start (BSet, TRUE, TRUE, 10); + CheckTable.attach (BSet, 2, 3, 0, 1, + Gtk::EXPAND | Gtk::FILL, + Gtk::AttachOptions(), 0, 0 ); BSet.signal_clicked().connect(sigc::mem_fun(this, &ObjectProperties::label_changed)); /* Create the frame for interactivity options */ @@ -332,7 +335,6 @@ void ObjectProperties::label_changed(void) /* Retrieve the label widget for the object's label */ Glib::ustring label = EntryLabel.get_text(); - g_assert(!label.empty()); /* Give feedback on success of setting the drawing object's label * using the widget's label text diff --git a/src/ui/dialog/ocaldialogs.cpp b/src/ui/dialog/ocaldialogs.cpp index bb06e3e79..c7bff185c 100644 --- a/src/ui/dialog/ocaldialogs.cpp +++ b/src/ui/dialog/ocaldialogs.cpp @@ -963,11 +963,7 @@ void SearchResultList::populate_from_xml(xmlNode * a_node) { if (!strcmp((const char*)cur_node->name, "title")) { -#if WITH_GTKMM_2_24 row_num = append(""); -#else - row_num = append_text(""); -#endif xmlChar *xml_title = xmlNodeGetContent(cur_node); char* title = (char*) xml_title; @@ -1116,8 +1112,14 @@ void ImportDialog::on_xml_file_read(const Glib::RefPtr<Gio::AsyncResult>& result xmlDoc *doc = NULL; xmlNode *root_element = NULL; - doc = xmlReadMemory(data, (int) length, xml_uri.c_str(), NULL, - XML_PARSE_RECOVER + XML_PARSE_NOWARNING + XML_PARSE_NOERROR); + int parse_options = XML_PARSE_RECOVER + XML_PARSE_NOWARNING + XML_PARSE_NOERROR; // do not use XML_PARSE_NOENT ! see bug lp:1025185 + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool allowNetAccess = prefs->getBool("/options/externalresources/xml/allow_net_access", false); + if (!allowNetAccess) { + parse_options |= XML_PARSE_NONET; + } + + doc = xmlReadMemory(data, (int) length, xml_uri.c_str(), NULL, parse_options); if (doc == NULL) { // If nothing is returned, no results could be found diff --git a/src/ui/dialog/ocaldialogs.h b/src/ui/dialog/ocaldialogs.h index 0dc61abb3..1cdfa15bb 100644 --- a/src/ui/dialog/ocaldialogs.h +++ b/src/ui/dialog/ocaldialogs.h @@ -64,7 +64,7 @@ public: FileDialogBase(const Glib::ustring &title, Gtk::Window& /*parent*/) : Gtk::Window(Gtk::WINDOW_TOPLEVEL) { set_title(title); - sp_transientize((GtkWidget*) gobj()); + sp_transientize(GTK_WIDGET(gobj())); // Allow shrinking of window so labels wrap correctly set_resizable(true); diff --git a/src/ui/dialog/print.cpp b/src/ui/dialog/print.cpp index e940a3f55..2ab8cf121 100644 --- a/src/ui/dialog/print.cpp +++ b/src/ui/dialog/print.cpp @@ -138,7 +138,7 @@ static void draw_page( #endif bool ret = ctx->setSurfaceTarget (surface, true, &ctm); if (ret) { - ret = renderer.setupDocument (ctx, junk->_doc, TRUE, NULL); + ret = renderer.setupDocument (ctx, junk->_doc, TRUE, 0., NULL); if (ret) { renderer.renderItem(ctx, junk->_base); ret = ctx->finish(); diff --git a/src/ui/dialog/spellcheck.cpp b/src/ui/dialog/spellcheck.cpp index 0da28061e..9cc18c02c 100644 --- a/src/ui/dialog/spellcheck.cpp +++ b/src/ui/dialog/spellcheck.cpp @@ -109,10 +109,6 @@ SpellCheck::SpellCheck (void) : tree_view.append_column(_("Suggestions:"), tree_columns.suggestions); { -// Backward compatibility fix: The GtkComboBoxText API was introduced with -// GTK+ 2.24. This check should eventually be dropped when we bump our -// GTK dependency. -#if GTK_CHECK_VERSION(2, 24, 0) dictionary_combo = gtk_combo_box_text_new(); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (dictionary_combo), _lang.c_str()); if (_lang2 != "") { @@ -121,16 +117,6 @@ SpellCheck::SpellCheck (void) : if (_lang3 != "") { gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (dictionary_combo), _lang3.c_str()); } -#else - dictionary_combo = gtk_combo_box_new_text(); - gtk_combo_box_append_text (GTK_COMBO_BOX (dictionary_combo), _lang.c_str()); - if (_lang2 != "") { - gtk_combo_box_append_text (GTK_COMBO_BOX (dictionary_combo), _lang2.c_str()); - } - if (_lang3 != "") { - gtk_combo_box_append_text (GTK_COMBO_BOX (dictionary_combo), _lang3.c_str()); - } -#endif gtk_combo_box_set_active (GTK_COMBO_BOX (dictionary_combo), 0); gtk_widget_show_all (dictionary_combo); } @@ -219,8 +205,8 @@ void SpellCheck::setTargetDesktop(SPDesktop *desktop) void SpellCheck::clearRects() { for (GSList *it = _rects; it; it = it->next) { - sp_canvas_item_hide((SPCanvasItem*) it->data); - sp_canvas_item_destroy((SPCanvasItem*) it->data); + sp_canvas_item_hide(SP_CANVAS_ITEM(it->data)); + sp_canvas_item_destroy(SP_CANVAS_ITEM(it->data)); } g_slist_free(_rects); _rects = NULL; @@ -330,8 +316,8 @@ SpellCheck::nextText() _text = getText(_root); if (_text) { - _modified_connection = ((SPObject*) _text)->connectModified(sigc::mem_fun(*this, &SpellCheck::onObjModified)); - _release_connection = ((SPObject*) _text)->connectRelease(sigc::mem_fun(*this, &SpellCheck::onObjReleased)); + _modified_connection = (SP_OBJECT(_text))->connectModified(sigc::mem_fun(*this, &SpellCheck::onObjModified)); + _release_connection = (SP_OBJECT(_text))->connectRelease(sigc::mem_fun(*this, &SpellCheck::onObjReleased)); _layout = te_get_layout (_text); _begin_w = _layout->begin(); diff --git a/src/ui/dialog/svg-fonts-dialog.cpp b/src/ui/dialog/svg-fonts-dialog.cpp index 16bb8222a..be69635e8 100644 --- a/src/ui/dialog/svg-fonts-dialog.cpp +++ b/src/ui/dialog/svg-fonts-dialog.cpp @@ -163,23 +163,14 @@ GlyphComboBox::GlyphComboBox(){ void GlyphComboBox::update(SPFont* spfont){ if (!spfont) return -//TODO: figure out why do we need to append_text("") before clearing items properly... +//TODO: figure out why do we need to append("") before clearing items properly... -#if WITH_GTKMM_2_24 this->append(""); //Gtk is refusing to clear the combobox when I comment out this line this->remove_all(); -#else - this->append_text(""); //Gtk is refusing to clear the combobox when I comment out this line - this->clear_items(); -#endif for(SPObject* node = spfont->children; node; node=node->next){ if (SP_IS_GLYPH(node)){ -#if WITH_GTKMM_2_24 this->append((static_cast<SPGlyph*>(node))->unicode); -#else - this->append_text((static_cast<SPGlyph*>(node))->unicode); -#endif } } } @@ -278,7 +269,7 @@ void SvgFontsDialog::update_fonts() _model->clear(); for(const GSList *l = fonts; l; l = l->next) { Gtk::TreeModel::Row row = *_model->append(); - SPFont* f = (SPFont*)l->data; + SPFont* f = SP_FONT(l->data); row[_columns.spfont] = f; row[_columns.svgfont] = new SvgFont(f); const gchar* lbl = f->label(); @@ -318,7 +309,7 @@ void SvgFontsDialog::update_global_settings_tab(){ SPObject* obj; for (obj=font->children; obj; obj=obj->next){ if (SP_IS_FONTFACE(obj)){ - _familyname_entry->set_text(((SPFontFace*) obj)->font_family); + _familyname_entry->set_text((SP_FONTFACE(obj))->font_family); } } } diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 68bafe549..43b88e5c6 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -54,6 +54,8 @@ #include "dialog-manager.h" #include "selection.h" #include "verbs.h" +#include "gradient-chemistry.h" +#include "helper/action.h" namespace Inkscape { namespace UI { @@ -62,10 +64,10 @@ namespace Dialogs { #define VBLOCK 16 #define PREVIEW_PIXBUF_WIDTH 128 -void _loadPaletteFile( gchar const *filename ); +void _loadPaletteFile( gchar const *filename, gboolean user=FALSE ); - -std::vector<SwatchPage*> possible; +std::list<SwatchPage*> userSwatchPages; +std::list<SwatchPage*> systemSwatchPages; static std::map<SPDocument*, SwatchPage*> docPalettes; static std::vector<DocTrack*> docTrackings; static std::map<SwatchesPanel*, SPDocument*> docPerPanel; @@ -142,8 +144,21 @@ static void editGradientImpl( SPDesktop* desktop, SPGradient* gr ) } if (!shown) { - GtkWidget *dialog = sp_gradient_vector_editor_new( gr ); - gtk_widget_show( dialog ); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if (prefs->getBool("/dialogs/gradienteditor/showlegacy", false)) { + // Legacy gradient dialog + GtkWidget *dialog = sp_gradient_vector_editor_new( gr ); + gtk_widget_show( dialog ); + } else { + // Invoke the gradient tool + Inkscape::Verb *verb = Inkscape::Verb::get( SP_VERB_CONTEXT_GRADIENT ); + if ( verb ) { + SPAction *action = verb->get_action( ( Inkscape::UI::View::View * ) SP_ACTIVE_DESKTOP); + if ( action ) { + sp_action_perform( action, NULL ); + } + } + } } } } @@ -197,20 +212,7 @@ void SwatchesPanelHook::deleteGradient( GtkMenuItem */*menuitem*/, gpointer /*us if ( bounceTarget ) { SwatchesPanel* swp = bouncePanel; SPDesktop* desktop = swp ? swp->getDesktop() : 0; - SPDocument *doc = desktop ? desktop->doc() : 0; - if (doc) { - std::string targetName(bounceTarget->def.descr); - const GSList *gradients = doc->getResourceList("gradient"); - for (const GSList *item = gradients; item; item = item->next) { - SPGradient* grad = SP_GRADIENT(item->data); - if ( targetName == grad->getId() ) { - grad->setSwatch(false); - DocumentUndo::done(doc, SP_VERB_CONTEXT_GRADIENT, - _("Delete")); - break; - } - } - } + sp_gradient_unset_swatch(desktop, bounceTarget->def.descr); } } @@ -237,6 +239,9 @@ static void removeit( GtkWidget *widget, gpointer data ) gtk_container_remove( GTK_CONTAINER(data), widget ); } +/* extern'ed from colot-item.cpp */ +gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data ); + gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data ) { gboolean handled = FALSE; @@ -371,13 +376,13 @@ static char* trim( char* str ) { return ret; } -void skipWhitespace( char*& str ) { +static void skipWhitespace( char*& str ) { while ( *str == ' ' || *str == '\t' ) { str++; } } -bool parseNum( char*& str, int& val ) { +static bool parseNum( char*& str, int& val ) { val = 0; while ( '0' <= *str && *str <= '9' ) { val = val * 10 + (*str - '0'); @@ -388,7 +393,7 @@ bool parseNum( char*& str, int& val ) { } -void _loadPaletteFile( gchar const *filename ) +void _loadPaletteFile( gchar const *filename, gboolean user/*=FALSE*/ ) { char block[1024]; FILE *f = Inkscape::IO::fopen_utf8name( filename, "r" ); @@ -490,7 +495,10 @@ void _loadPaletteFile( gchar const *filename ) } } while ( result && !hasErr ); if ( !hasErr ) { - possible.push_back(onceMore); + if (user) + userSwatchPages.push_back(onceMore); + else + systemSwatchPages.push_back(onceMore); #if ENABLE_MAGIC_COLORS ColorItem::_wireMagicColors( onceMore ); #endif // ENABLE_MAGIC_COLORS @@ -504,9 +512,16 @@ void _loadPaletteFile( gchar const *filename ) } } +static bool +compare_swatch_names(SwatchPage const *a, SwatchPage const *b) { + + return g_utf8_collate(a->_name.c_str(), b->_name.c_str()) < 0; +} + static void loadEmUp() { static bool beenHere = false; + gboolean userPalete = true; if ( !beenHere ) { beenHere = true; @@ -518,7 +533,6 @@ static void loadEmUp() // Use this loop to iterate through a list of possible document locations. while (!sources.empty()) { gchar *dirname = sources.front(); - if ( Inkscape::IO::file_test( dirname, G_FILE_TEST_EXISTS ) && Inkscape::IO::file_test( dirname, G_FILE_TEST_IS_DIR )) { GError *err = 0; @@ -532,11 +546,13 @@ static void loadEmUp() while ((filename = (gchar *)g_dir_read_name(directory)) != NULL) { gchar* lower = g_ascii_strdown( filename, -1 ); // if ( g_str_has_suffix(lower, ".gpl") ) { + if ( !g_str_has_suffix(lower, "~") ) { gchar* full = g_build_filename(dirname, filename, NULL); if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) { - _loadPaletteFile(full); + _loadPaletteFile(full, userPalete); } g_free(full); + } // } g_free(lower); } @@ -547,15 +563,15 @@ static void loadEmUp() // toss the dirname g_free(dirname); sources.pop_front(); + userPalete = false; } } -} - - - - + // Sort the list of swatches by name, grouped by user/system + userSwatchPages.sort(compare_swatch_names); + systemSwatchPages.sort(compare_swatch_names); +} @@ -589,7 +605,7 @@ SwatchesPanel::SwatchesPanel(gchar const* prefsPath) : } loadEmUp(); - if ( !possible.empty() ) { + if ( !systemSwatchPages.empty() ) { SwatchPage* first = 0; int index = 0; Glib::ustring targetName; @@ -600,8 +616,9 @@ SwatchesPanel::SwatchesPanel(gchar const* prefsPath) : if (targetName == "Auto") { first = docPalettes[0]; } else { - index++; - for ( std::vector<SwatchPage*>::iterator iter = possible.begin(); iter != possible.end(); ++iter ) { + //index++; + std::vector<SwatchPage*> pages = _getSwatchSets(); + for ( std::vector<SwatchPage*>::iterator iter = pages.begin(); iter != pages.end(); ++iter ) { if ( (*iter)->_name == targetName ) { first = *iter; break; @@ -632,6 +649,7 @@ SwatchesPanel::SwatchesPanel(gchar const* prefsPath) : hotItem = single; } _regItem( single, 3, i ); + i++; } } @@ -1024,6 +1042,7 @@ void SwatchesPanel::handleDefsModified(SPDocument *document) } } + std::vector<SwatchPage*> SwatchesPanel::_getSwatchSets() const { std::vector<SwatchPage*> tmp; @@ -1031,7 +1050,8 @@ std::vector<SwatchPage*> SwatchesPanel::_getSwatchSets() const tmp.push_back(docPalettes[_currentDocument]); } - tmp.insert(tmp.end(), possible.begin(), possible.end()); + tmp.insert(tmp.end(), userSwatchPages.begin(), userSwatchPages.end()); + tmp.insert(tmp.end(), systemSwatchPages.begin(), systemSwatchPages.end()); return tmp; } diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp new file mode 100644 index 000000000..9d4ab5d8a --- /dev/null +++ b/src/ui/dialog/symbols.cpp @@ -0,0 +1,610 @@ +/** + * @file + * Symbols dialog. + */ +/* Authors: + * Copyright (C) 2012 Tavmjong Bah + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <iostream> +#include <algorithm> + +#include <glibmm/i18n.h> + +#include <gtkmm/buttonbox.h> +#include <gtkmm/label.h> +#include <gtkmm/table.h> +#include <gtkmm/scrolledwindow.h> +#include <gtkmm/comboboxtext.h> +#include <gtkmm/iconview.h> +#include <gtkmm/liststore.h> +#include <gtkmm/treemodelcolumn.h> +#include <gtkmm/clipboard.h> + +#include "path-prefix.h" +#include "io/sys.h" + +#include "ui/cache/svg_preview_cache.h" +#include "ui/clipboard.h" + +#include "symbols.h" + +#include "desktop.h" +#include "desktop-handles.h" +#include "document.h" +#include "inkscape.h" +#include "sp-root.h" +#include "sp-use.h" +#include "sp-symbol.h" + +#include "verbs.h" +#include "xml/repr.h" + +namespace Inkscape { +namespace UI { + +static Cache::SvgPreview svg_preview_cache; + +namespace Dialog { + + // See: http://developer.gnome.org/gtkmm/stable/classGtk_1_1TreeModelColumnRecord.html +class SymbolColumns : public Gtk::TreeModel::ColumnRecord +{ +public: + + Gtk::TreeModelColumn<Glib::ustring> symbol_id; + Gtk::TreeModelColumn<Glib::ustring> symbol_title; + Gtk::TreeModelColumn< Glib::RefPtr<Gdk::Pixbuf> > symbol_image; + + SymbolColumns() { + add(symbol_id); + add(symbol_title); + add(symbol_image); + } +}; + +SymbolColumns* SymbolsDialog::getColumns() +{ + SymbolColumns* columns = new SymbolColumns(); + return columns; +} + +/** + * Constructor + */ +SymbolsDialog::SymbolsDialog( gchar const* prefsPath ) : + UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SYMBOLS), + store(Gtk::ListStore::create(*getColumns())), + iconView(0), + previewScale(0), + previewSize(0), + currentDesktop(0), + deskTrack(), + currentDocument(0), + previewDocument(0), + instanceConns() +{ + + /******************** Table *************************/ + // Replace by Grid for GTK 3.0 + Gtk::Table *table = new Gtk::Table(2, 4, false); + // panel is a cloked Gtk::VBox + _getContents()->pack_start(*Gtk::manage(table), Gtk::PACK_EXPAND_WIDGET); + guint row = 0; + + /******************** Symbol Sets *************************/ + Gtk::Label* labelSet = new Gtk::Label(_("Symbol set: ")); + table->attach(*Gtk::manage(labelSet),0,1,row,row+1,Gtk::SHRINK,Gtk::SHRINK); + + symbolSet = new Gtk::ComboBoxText(); // Fill in later + symbolSet->append(_("Current Document")); + symbolSet->set_active_text(_("Current Document")); + table->attach(*Gtk::manage(symbolSet),1,2,row,row+1,Gtk::FILL|Gtk::EXPAND,Gtk::SHRINK); + + sigc::connection connSet = + symbolSet->signal_changed().connect(sigc::mem_fun(*this, &SymbolsDialog::rebuild)); + instanceConns.push_back(connSet); + + ++row; + + /********************* Icon View **************************/ + SymbolColumns* columns = getColumns(); + + iconView = new Gtk::IconView(static_cast<Glib::RefPtr<Gtk::TreeModel> >(store)); + //iconView->set_text_column( columns->symbol_id ); + iconView->set_tooltip_column( 1 ); + iconView->set_pixbuf_column( columns->symbol_image ); + + std::vector< Gtk::TargetEntry > targets; + targets.push_back(Gtk::TargetEntry( "application/x-inkscape-paste")); + + iconView->enable_model_drag_source (targets, Gdk::BUTTON1_MASK, Gdk::ACTION_COPY); + iconView->signal_drag_data_get().connect(sigc::mem_fun(*this, &SymbolsDialog::iconDragDataGet)); + + sigc::connection connIconChanged; + connIconChanged = + iconView->signal_selection_changed().connect(sigc::mem_fun(*this, &SymbolsDialog::iconChanged)); + instanceConns.push_back(connIconChanged); + + Gtk::ScrolledWindow *scroller = new Gtk::ScrolledWindow(); + scroller->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); + scroller->add(*Gtk::manage(iconView)); + table->attach(*Gtk::manage(scroller),0,2,row,row+1,Gtk::EXPAND|Gtk::FILL,Gtk::EXPAND|Gtk::FILL); + + ++row; + + /******************** Preview Scale ***********************/ + Gtk::Label* labelScale = new Gtk::Label(_("Preview scale: ")); + table->attach(*Gtk::manage(labelScale),0,1,row,row+1,Gtk::SHRINK,Gtk::SHRINK); + + previewScale = new Gtk::ComboBoxText(); + const gchar *scales[] = + {_("Fit"), _("Fit to width"), _("Fit to height"), "0.1", "0.2", "0.5", "1.0", "2.0", "5.0", NULL}; + for( int i = 0; scales[i]; ++i ) { + previewScale->append(scales[i]); + } + previewScale->set_active_text(scales[0]); + table->attach(*Gtk::manage(previewScale),1,2,row,row+1,Gtk::FILL|Gtk::EXPAND,Gtk::SHRINK); + + sigc::connection connScale = + previewScale->signal_changed().connect(sigc::mem_fun(*this, &SymbolsDialog::rebuild)); + instanceConns.push_back(connScale); + + ++row; + + /******************** Preview Size ************************/ + Gtk::Label* labelSize = new Gtk::Label(_("Preview size: ")); + table->attach(*Gtk::manage(labelSize),0,1,row,row+1,Gtk::SHRINK,Gtk::SHRINK); + + previewSize = new Gtk::ComboBoxText(); + const gchar *sizes[] = {"16", "24", "32", "48", "64", NULL}; + for( int i = 0; sizes[i]; ++i ) { + previewSize->append(sizes[i]); + } + previewSize->set_active_text(sizes[2]); + table->attach(*Gtk::manage(previewSize),1,2,row,row+1,Gtk::FILL|Gtk::EXPAND,Gtk::SHRINK); + + sigc::connection connSize = + previewSize->signal_changed().connect(sigc::mem_fun(*this, &SymbolsDialog::rebuild)); + instanceConns.push_back(connSize); + + ++row; + + /**********************************************************/ + currentDesktop = inkscape_active_desktop(); + currentDocument = sp_desktop_document(currentDesktop); + + previewDocument = symbols_preview_doc(); /* Template to render symbols in */ + previewDocument->ensureUpToDate(); /* Necessary? */ + + key = SPItem::display_key_new(1); + renderDrawing.setRoot(previewDocument->getRoot()->invoke_show(renderDrawing, key, SP_ITEM_SHOW_DISPLAY )); + + get_symbols(); + draw_symbols( currentDocument ); /* Defaults to current document */ + + desktopChangeConn = + deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &SymbolsDialog::setTargetDesktop) ); + instanceConns.push_back( desktopChangeConn ); + deskTrack.connect(GTK_WIDGET(gobj())); +} + +SymbolsDialog::~SymbolsDialog() +{ + for (std::vector<sigc::connection>::iterator it = instanceConns.begin(); it != instanceConns.end(); ++it) { + it->disconnect(); + } + instanceConns.clear(); + deskTrack.disconnect(); +} + +SymbolsDialog& SymbolsDialog::getInstance() +{ + return *new SymbolsDialog(); +} + +void SymbolsDialog::rebuild() { + + store->clear(); + Glib::ustring symbolSetString = symbolSet->get_active_text(); + + SPDocument* symbolDocument = symbolSets[symbolSetString]; + if( !symbolDocument ) { + // Symbol must be from Current Document (this method of + // checking should be language independent). + symbolDocument = currentDocument; + } + draw_symbols( symbolDocument ); +} + +void SymbolsDialog::iconDragDataGet(const Glib::RefPtr<Gdk::DragContext>& context, Gtk::SelectionData& data, guint info, guint time) { + +#if WITH_GTKMM_3_0 + std::vector<Gtk::TreePath> iconArray = iconView->get_selected_items(); +#else + Gtk::IconView::ArrayHandle_TreePaths iconArray = iconView->get_selected_items(); +#endif + + if( iconArray.empty() ) { + //std::cout << " iconArray empty: huh? " << std::endl; + } else { + Gtk::TreeModel::Path const & path = *iconArray.begin(); + Gtk::ListStore::iterator row = store->get_iter(path); + Glib::ustring symbol_id = (*row)[getColumns()->symbol_id]; + + GdkAtom dataAtom = gdk_atom_intern( "application/x-inkscape-paste", FALSE ); + gtk_selection_data_set( data.gobj(), dataAtom, 9, (guchar*)symbol_id.c_str(), symbol_id.length() ); + } + +} + +void SymbolsDialog::iconChanged() { +#if WITH_GTKMM_3_0 + std::vector<Gtk::TreePath> iconArray = iconView->get_selected_items(); +#else + Gtk::IconView::ArrayHandle_TreePaths iconArray = iconView->get_selected_items(); +#endif + + if( iconArray.empty() ) { + //std::cout << " iconArray empty: huh? " << std::endl; + } else { + Gtk::TreeModel::Path const & path = *iconArray.begin(); + Gtk::ListStore::iterator row = store->get_iter(path); + Glib::ustring symbol_id = (*row)[getColumns()->symbol_id]; + + /* OK, we know symbol name... now we need to copy it to clipboard, bon chance! */ + Glib::ustring symbolSetString = symbolSet->get_active_text(); + + SPDocument* symbolDocument = symbolSets[symbolSetString]; + if( !symbolDocument ) { + // Symbol must be from Current Document (this method of + // checking should be language independent). + symbolDocument = currentDocument; + } + + SPObject* symbol = symbolDocument->getObjectById(symbol_id); + if( symbol ) { + + // Find style for use in <use> + // 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"); + } + } + + ClipboardManager *cm = ClipboardManager::get(); + cm->copySymbol(symbol->getRepr(), style); + } + } +} + +/* 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 ) ) { + 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 ) ) { + directories.push_back( profile_path("symbols") ); + } + + std::list<Glib::ustring>::iterator it; + for( it = directories.begin(); it != directories.end(); ++it ) { + + GError *err = 0; + 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 *fullname = g_build_filename((*it).c_str(), filename, NULL); + + if ( !Inkscape::IO::file_test( fullname, G_FILE_TEST_IS_DIR ) ) { + + SPDocument* symbol_doc = SPDocument::createNewDoc( fullname, FALSE ); + if( symbol_doc ) { + symbolSets[Glib::ustring(filename)]= symbol_doc; + symbolSet->append(filename); + } + } + g_free( fullname ); + } + g_dir_close( dir ); + } + } +} + +GSList* SymbolsDialog::symbols_in_doc_recursive (SPObject *r, GSList *l) +{ + + // Stop multiple counting of same symbol + if( SP_IS_USE(r) ) { + return l; + } + + if( SP_IS_SYMBOL(r) ) { + l = g_slist_prepend (l, r); + } + + for (SPObject *child = r->firstChild(); child; child = child->getNext()) { + l = symbols_in_doc_recursive( child, l ); + } + + return l; +} + +GSList* SymbolsDialog::symbols_in_doc( SPDocument* symbolDocument ) { + + GSList *l = NULL; + l = symbols_in_doc_recursive (symbolDocument->getRoot(), l ); + return l; +} + +GSList* SymbolsDialog::use_in_doc_recursive (SPObject *r, GSList *l) +{ + + if( SP_IS_USE(r) ) { + l = g_slist_prepend (l, r); + } + + for (SPObject *child = r->firstChild(); child; child = child->getNext()) { + l = use_in_doc_recursive( child, l ); + } + + return l; +} + +GSList* SymbolsDialog::use_in_doc( SPDocument* useDocument ) { + + GSList *l = NULL; + l = use_in_doc_recursive (useDocument->getRoot(), l ); + return l; +} + +// Returns style from first <use> element found that references id. +// This is a last ditch effort to find a style. +gchar const* SymbolsDialog::style_from_use( gchar const* id, SPDocument* document) { + + gchar const* style = 0; + GSList* l = use_in_doc( document ); + 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; + } + } + } + } + return style; +} + +void SymbolsDialog::draw_symbols( SPDocument* symbolDocument ) { + + + SymbolColumns* columns = getColumns(); + + GSList* l = symbols_in_doc( symbolDocument ); + for( ; l != NULL; l = l->next ) { + + SPObject* symbol = SP_OBJECT(l->data); + if (!SP_IS_SYMBOL(symbol)) { + //std::cout << " Error: not symbol" << std::endl; + continue; + } + + gchar const *id = symbol->getRepr()->attribute("id"); + gchar const *title = symbol->title(); // From title element + if( !title ) { + title = id; + } + + Glib::RefPtr<Gdk::Pixbuf> pixbuf = create_symbol_image(id, symbolDocument, &renderDrawing, key ); + if( pixbuf ) { + + Gtk::ListStore::iterator row = store->append(); + (*row)[columns->symbol_id] = Glib::ustring( id ); + (*row)[columns->symbol_title] = Glib::ustring( title ); + (*row)[columns->symbol_image] = pixbuf; + } + } + + delete columns; +} + +/* + * Returns image of symbol. + * + * Symbols normally are not visible. They must be referenced by a + * <use> element. A temporary document is created with a dummy + * <symbol> element and a <use> element that references the symbol + * element. Each real symbol is swapped in for the dummy symbol and + * the temporary document is rendered. + */ +Glib::RefPtr<Gdk::Pixbuf> +SymbolsDialog::create_symbol_image(gchar const *symbol_id, + SPDocument *source, + Inkscape::Drawing* drawing, + unsigned /*visionkey*/) +{ + // Retrieve the symbol named 'symbol_id' from the source SVG document + SPObject const* symbol = source->getObjectById(symbol_id); + if (symbol == NULL) { + //std::cout << " Failed to find symbol: " << symbol_id << std::endl; + //return 0; + } + + // Create a copy repr of the symbol with id="the_symbol" + Inkscape::XML::Document *xml_doc = previewDocument->getReprDoc(); + Inkscape::XML::Node *repr = symbol->getRepr()->duplicate(xml_doc); + repr->setAttribute("id", "the_symbol"); + + // Replace old "the_symbol" in previewDocument by new. + Inkscape::XML::Node *root = previewDocument->getReprRoot(); + SPObject *symbol_old = previewDocument->getObjectById("the_symbol"); + if (symbol_old) { + symbol_old->deleteObject(false); + } + + // First look for default style stored in <symbol> + gchar const* style = repr->attribute("inkscape:symbol-style"); + if( !style ) { + // If no default style in <symbol>, look in documents. + if( source == currentDocument ) { + style = style_from_use( symbol_id, source ); + } else { + style = source->getReprRoot()->attribute("style"); + } + } + // Last ditch effort to provide some default styling + if( !style ) style = "fill:#bbbbbb;stroke:#808080"; + + // This is for display in Symbols dialog only + if( style ) { + repr->setAttribute( "style", style ); + } + + // BUG: Symbols don't work if defined outside of <defs>. Causes Inkscape + // crash when trying to read in such a file. + root->appendChild(repr); + //defsrepr->appendChild(repr); + Inkscape::GC::release(repr); + + // Uncomment this to get the previewDocument documents saved (useful for debugging) + // FILE *fp = fopen (g_strconcat(symbol_id, ".svg", NULL), "w"); + // sp_repr_save_stream(previewDocument->getReprDoc(), fp); + // fclose (fp); + + // Make sure previewDocument is up-to-date. + previewDocument->getRoot()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + previewDocument->ensureUpToDate(); + + // Make sure we have symbol in previewDocument + SPObject *object_temp = previewDocument->getObjectById( "the_use" ); + previewDocument->getRoot()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + previewDocument->ensureUpToDate(); + + // if( object_temp == NULL || !SP_IS_ITEM(object_temp) ) { + // //std::cout << " previewDocument broken?" << std::endl; + // //return 0; + // } + + SPItem *item = SP_ITEM(object_temp); + + Glib::ustring previewSizeString = previewSize->get_active_text(); + unsigned psize = atol( previewSizeString.c_str() ); + + Glib::ustring previewScaleString = previewScale->get_active_text(); + int previewScaleRow = previewScale->get_active_row_number(); + + /* 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); + + // Find object's bbox in document. + // Note symbols can have own viewport... ignore for now. + //Geom::OptRect dbox = item->geometricBounds(); + Geom::OptRect dbox = item->documentVisualBounds(); + if (!dbox) { + //std::cout << " No dbox" << std::endl; + return pixbuf; + } + + if (!pixbuf) { + + /* Scale symbols to fit */ + double scale = 1.0; + double width = dbox->width(); + double height = dbox->height(); + if( width == 0.0 ) { + width = 1.0; + } + if( height == 0.0 ) { + height = 1.0; + } + + switch (previewScaleRow) { + case 0: + /* Fit */ + scale = psize/std::max(width,height); + break; + case 1: + /* Fit width */ + scale = psize/width; + break; + case 2: + /* Fit height */ + scale = psize/height; + break; + default: + scale = atof( previewScaleString.c_str() ); + } + + pixbuf = Glib::wrap(render_pixbuf(*drawing, scale, *dbox, psize)); + svg_preview_cache.set_preview_in_cache(key, pixbuf->gobj()); + } + + return pixbuf; +} + +/* + * Return empty doc to render symbols in. + * Symbols are by default not rendered so a <use> element is + * provided. + */ +SPDocument* SymbolsDialog::symbols_preview_doc() +{ + // BUG: <symbol> must be inside <defs> + gchar const *buffer = +"<svg xmlns=\"http://www.w3.org/2000/svg\"" +" xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"" +" xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"" +" xmlns:xlink=\"http://www.w3.org/1999/xlink\">" +" <defs id=\"defs\">" +" <symbol id=\"the_symbol\"/>" +" </defs>" +" <use id=\"the_use\" xlink:href=\"#the_symbol\"/>" +"</svg>"; + + return SPDocument::createNewDocFromMem( buffer, strlen(buffer), FALSE ); +} + +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(); + } + } +} + +} //namespace Dialogs +} //namespace UI +} //namespace Inkscape diff --git a/src/ui/dialog/symbols.h b/src/ui/dialog/symbols.h new file mode 100644 index 000000000..5486ff546 --- /dev/null +++ b/src/ui/dialog/symbols.h @@ -0,0 +1,115 @@ +/** @file + * @brief Symbols dialog + */ +/* Authors: + * Tavmjong Bah + * + * Copyright (C) 2012 Tavmjong Bah + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef INKSCAPE_UI_DIALOG_SYMBOLS_H +#define INKSCAPE_UI_DIALOG_SYMBOLS_H + +#include "ui/widget/panel.h" +#include "ui/widget/button.h" + +#include "ui/dialog/desktop-tracker.h" + +#include "display/drawing.h" + +#include <glib.h> +#include <gtkmm/treemodel.h> + +#include <vector> + +class SPObject; + +namespace Inkscape { +namespace UI { +namespace Dialog { + +class SymbolColumns; // For Gtk::ListStore + +/** + * A dialog that displays selectable symbols. + */ +class SymbolsDialog : public UI::Widget::Panel { + +public: + SymbolsDialog( gchar const* prefsPath = "/dialogs/symbols" ); + virtual ~SymbolsDialog(); + + static SymbolsDialog& getInstance(); + +protected: + + +private: + SymbolsDialog(SymbolsDialog const &); // no copy + SymbolsDialog &operator=(SymbolsDialog const &); // no assign + + static SymbolColumns *getColumns(); + + void rebuild(); + void iconChanged(); + void iconDragDataGet(const Glib::RefPtr<Gdk::DragContext>& context, Gtk::SelectionData& selection_data, guint info, guint time); + + void get_symbols(); + void draw_symbols( SPDocument* symbol_document ); + SPDocument* symbols_preview_doc(); + + GSList* symbols_in_doc_recursive(SPObject *r, GSList *l); + GSList* symbols_in_doc( SPDocument* document ); + GSList* use_in_doc_recursive(SPObject *r, GSList *l); + GSList* use_in_doc( SPDocument* document ); + gchar const* style_from_use( gchar const* id, SPDocument* document); + + Glib::RefPtr<Gdk::Pixbuf> + create_symbol_image(gchar const *symbol_name, + SPDocument *source, Inkscape::Drawing* drawing, + unsigned /*visionkey*/); + + /* Keep track of all symbol template documents */ + std::map<Glib::ustring, SPDocument*> symbolSets; + + + Glib::RefPtr<Gtk::ListStore> store; + Gtk::ComboBoxText* symbolSet; + Gtk::IconView* iconView; + Gtk::ComboBoxText* previewScale; + Gtk::ComboBoxText* previewSize; + + void setTargetDesktop(SPDesktop *desktop); + SPDesktop* currentDesktop; + DesktopTracker deskTrack; + SPDocument* currentDocument; + SPDocument* previewDocument; /* Document to render single symbol */ + + /* For rendering the template drawing */ + unsigned key; + Inkscape::Drawing renderDrawing; + + std::vector<sigc::connection> instanceConns; + sigc::connection desktopChangeConn; + +}; + +} //namespace Dialogs +} //namespace UI +} //namespace Inkscape + + +#endif // INKSCAPE_UI_DIALOG_SYMBOLS_H + +/* + 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/text-edit.cpp b/src/ui/dialog/text-edit.cpp index 033571bb4..6696db083 100644 --- a/src/ui/dialog/text-edit.cpp +++ b/src/ui/dialog/text-edit.cpp @@ -106,30 +106,12 @@ TextEdit::TextEdit() GtkWidget *px = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("text_line_spacing") ); layout_hbox.pack_start(*Gtk::manage(Glib::wrap(px)), false, false); -/* -This would introduce dependency on gtk version 2.24 which is currently not available in -Trisquel GNU/Linux 4.5.1 (released on May 25th, 2011) -This conditional and its #else block can be deleted in the future. -*/ -#if GTK_CHECK_VERSION(2, 24,0) spacing_combo = gtk_combo_box_text_new_with_entry (); -#else - spacing_combo = gtk_combo_box_entry_new_text (); -#endif gtk_widget_set_size_request (spacing_combo, 90, -1); const gchar *spacings[] = {"50%", "80%", "90%", "100%", "110%", "120%", "130%", "140%", "150%", "200%", "300%", NULL}; for (int i = 0; spacings[i]; i++) { -/* -This would introduce dependency on gtk version 2.24 which is currently not available in -Trisquel GNU/Linux 4.5.1 (released on May 25th, 2011) -This conditional and its #else block can be deleted in the future. -*/ -#if GTK_CHECK_VERSION(2, 24,0) gtk_combo_box_text_append_text((GtkComboBoxText *) spacing_combo, spacings[i]); -#else - gtk_combo_box_append_text((GtkComboBox *) spacing_combo, spacings[i]); -#endif } gtk_widget_set_tooltip_text (px, _("Spacing between lines (percent of font size)")); @@ -505,16 +487,7 @@ SPCSSAttr *TextEdit::getTextStyle () // Note that CSS 1.1 does not support line-height; we set it for consistency, but also set // sodipodi:linespacing for backwards compatibility; in 1.2 we use line-height for flowtext -/* -This would introduce dependency on gtk version 2.24 which is currently not available in -Trisquel GNU/Linux 4.5.1 (released on May 25th, 2011) -This conditional and its #else block can be deleted in the future. -*/ -#if GTK_CHECK_VERSION(2, 24,0) const gchar *sstr = gtk_combo_box_text_get_active_text ((GtkComboBoxText *) spacing_combo); -#else - const gchar *sstr = gtk_entry_get_text ((GtkEntry *) (gtk_bin_get_child (GTK_BIN (spacing_combo)))); -#endif sp_repr_css_set_property (css, "line-height", sstr); return css; diff --git a/src/ui/dialog/tile.cpp b/src/ui/dialog/tile.cpp index 5031a60b6..1ce78a278 100644 --- a/src/ui/dialog/tile.cpp +++ b/src/ui/dialog/tile.cpp @@ -42,7 +42,7 @@ * 0 *elem1 == *elem2 * >0 *elem1 goes after *elem2 */ -int sp_compare_x_position(SPItem *first, SPItem *second) +static int sp_compare_x_position(SPItem *first, SPItem *second) { using Geom::X; using Geom::Y; @@ -84,7 +84,7 @@ int sp_compare_x_position(SPItem *first, SPItem *second) /* * Sort items by their y co-ordinates. */ -int +static int sp_compare_y_position(SPItem *first, SPItem *second) { Geom::OptRect a = first->documentVisualBounds(); diff --git a/src/ui/dialog/tracedialog.cpp b/src/ui/dialog/tracedialog.cpp index a6495c205..1ad827a56 100644 --- a/src/ui/dialog/tracedialog.cpp +++ b/src/ui/dialog/tracedialog.cpp @@ -26,6 +26,8 @@ #include <glibmm/i18n.h> #include "desktop.h" +#include "desktop-tracker.h" +#include "selection.h" #include "trace/potrace/inkscape-potrace.h" #include "inkscape.h" @@ -83,6 +85,13 @@ class TraceDialogImpl : public TraceDialog void abort(); void previewCallback(); + void previewLiveCallback(); + void onSettingsChange(); + void onSelectionModified( guint flags ); + void onSetDefaults(); + + void setDesktop(SPDesktop *desktop); + void setTargetDesktop(SPDesktop *desktop); //############ General items @@ -90,6 +99,7 @@ class TraceDialogImpl : public TraceDialog Gtk::Button *mainOkButton; Gtk::Button *mainCancelButton; + Gtk::Button *mainResetButton; //######## Left pannel @@ -194,11 +204,40 @@ class TraceDialogImpl : public TraceDialog UI::Widget::Frame previewFrame; Gtk::VBox previewVBox; Gtk::Button previewButton; + Gtk::CheckButton previewLiveButton; + gboolean previewLive; Gtk::Image previewImage; + SPDesktop *desktop; + DesktopTracker deskTrack; + sigc::connection desktopChangeConn; + sigc::connection selectChangedConn; + sigc::connection selectModifiedConn; + }; +void TraceDialogImpl::setDesktop(SPDesktop *desktop) +{ + Panel::setDesktop(desktop); + deskTrack.setBase(desktop); +} +void TraceDialogImpl::setTargetDesktop(SPDesktop *desktop) +{ + if (this->desktop != desktop) { + if (this->desktop) { + selectChangedConn.disconnect(); + selectModifiedConn.disconnect(); + } + this->desktop = desktop; + if (desktop && desktop->selection) { + selectChangedConn = desktop->selection->connectChanged(sigc::hide(sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange))); + selectModifiedConn = desktop->selection->connectModified(sigc::hide<0>(sigc::mem_fun(*this, &TraceDialogImpl::onSelectionModified))); + + } + onSettingsChange(); + } +} //######################################################################### //## E V E N T S @@ -294,8 +333,9 @@ void TraceDialogImpl::potraceProcess(bool do_i_trace) { int width = preview->get_width(); int height = preview->get_height(); - double scaleFX = 200.0 / (double)width; - double scaleFY = 200.0 / (double)height; + const Gtk::Allocation& vboxAlloc = previewImage.get_allocation(); + double scaleFX = vboxAlloc.get_width() / (double)width; + double scaleFY = vboxAlloc.get_height() / (double)height; double scaleFactor = scaleFX > scaleFY ? scaleFY : scaleFX; int newWidth = (int) (((double)width) * scaleFactor); int newHeight = (int) (((double)height) * scaleFactor); @@ -351,6 +391,58 @@ void TraceDialogImpl::abort() //######################################################################### /** + * Callback for when any setting changes + */ +void TraceDialogImpl::onSettingsChange() +{ + if (previewLive) { + previewCallback(); + } +} + +void TraceDialogImpl::onSelectionModified( guint flags ) +{ + if (flags & ( SP_OBJECT_MODIFIED_FLAG | + SP_OBJECT_PARENT_MODIFIED_FLAG | + SP_OBJECT_STYLE_MODIFIED_FLAG) ) { + onSettingsChange(); + } +} + +/** + * Callback for when users resets defaults + */ +void TraceDialogImpl::onSetDefaults() +{ + + // temporarily disable live update + gboolean wasLive = previewLive; + previewLive = false; + + modeBrightnessRadioButton.set_active(true); + modeBrightnessSpinner.set_value(0.45); + modeCannyHiSpinner.set_value(0.65); + modeMultiScanNrColorSpinner.set_value(8.0); + modeMultiScanNrColorSpinner.set_value(8.0); + optionsSpecklesSizeSpinner.set_value(2); + optionsCornersThresholdSpinner.set_value(1.0); + optionsOptimToleranceSpinner.set_value(0.2); + + modeInvertButton.set_active(false); + modeMultiScanSmoothButton.set_active(true); + modeMultiScanStackButton.set_active(true); + modeMultiScanBackgroundButton.set_active(false); + optionsSpecklesButton.set_active(true); + optionsCornersButton.set_active(true); + optionsOptimButton.set_active(true); + sioxButton.set_active(false); + + previewLive = wasLive; + onSettingsChange(); + +} + +/** * Callback from the Preview button. Can be called from elsewhere. */ void TraceDialogImpl::previewCallback() @@ -359,24 +451,31 @@ void TraceDialogImpl::previewCallback() } /** + * Callback from the Preview Live button. + */ +void TraceDialogImpl::previewLiveCallback() +{ + previewLive = previewLiveButton.get_active(); + previewButton.set_sensitive(!previewLive); + onSettingsChange(); +} + +/** * Default response from the dialog. Let's intercept it */ void TraceDialogImpl::responseCallback(int response_id) { - if (response_id == GTK_RESPONSE_OK) - { - // for now, we assume potrace, as it's the only one we have - potraceProcess(true); - } - else if (response_id == GTK_RESPONSE_CANCEL) - { + if (response_id == GTK_RESPONSE_OK) { + // for now, we assume potrace, as it's the only one we have + potraceProcess(true); + } else if (response_id == GTK_RESPONSE_CANCEL) { abort(); - } - else - { + } else if (response_id == GTK_RESPONSE_HELP) { + onSetDefaults(); + } else { hide(); return; - } + } } @@ -417,6 +516,7 @@ TraceDialogImpl::TraceDialogImpl() : modeBrightnessSpinner.set_value(0.45); modeBrightnessBox.pack_end(modeBrightnessSpinner, false, false, MARGIN); modeBrightnessSpinner.set_tooltip_text(_("Brightness cutoff for black/white")); + modeBrightnessSpinner.get_adjustment()->signal_value_changed().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); modeBrightnessSpinnerLabel.set_label(_("_Threshold:")); modeBrightnessSpinnerLabel.set_use_underline(true); @@ -435,6 +535,8 @@ TraceDialogImpl::TraceDialogImpl() : modeCannyRadioButton.set_use_underline(true); modeCannyBox.pack_start(modeCannyRadioButton, false, false, MARGIN); modeCannyRadioButton.set_tooltip_text(_("Trace with optimal edge detection by J. Canny's algorithm")); + modeCannyRadioButton.signal_clicked().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); + /* modeCannyBox.pack_start(modeCannySeparator); modeCannyLoSpinnerLabel.set_label(_("Low")); @@ -451,6 +553,7 @@ TraceDialogImpl::TraceDialogImpl() : modeCannyHiSpinner.set_value(0.65); modeCannyBox.pack_end(modeCannyHiSpinner, false, false, MARGIN); modeCannyHiSpinner.set_tooltip_text(_("Brightness cutoff for adjacent pixels (determines edge thickness)")); + modeCannyHiSpinner.get_adjustment()->signal_value_changed().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); modeCannyHiSpinnerLabel.set_label(_("T_hreshold:")); modeCannyHiSpinnerLabel.set_use_underline(true); @@ -469,6 +572,7 @@ TraceDialogImpl::TraceDialogImpl() : modeQuantRadioButton.set_use_underline(true); modeQuantBox.pack_start(modeQuantRadioButton, false, false, MARGIN); modeQuantRadioButton.set_tooltip_text(_("Trace along the boundaries of reduced colors")); + modeQuantRadioButton.signal_clicked().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); modeQuantNrColorSpinner.set_digits(0); modeQuantNrColorSpinner.set_increments(1.0, 0); @@ -476,6 +580,7 @@ TraceDialogImpl::TraceDialogImpl() : modeQuantNrColorSpinner.set_value(8.0); modeQuantBox.pack_end(modeQuantNrColorSpinner, false, false, MARGIN); modeQuantNrColorSpinner.set_tooltip_text(_("The number of reduced colors")); + modeQuantNrColorSpinner.get_adjustment()->signal_value_changed().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); modeQuantNrColorLabel.set_label(_("_Colors:")); modeQuantNrColorLabel.set_mnemonic_widget(modeQuantNrColorSpinner); @@ -491,6 +596,7 @@ TraceDialogImpl::TraceDialogImpl() : modeInvertBox.pack_start(modeInvertButton, false, false, MARGIN); modeBrightnessVBox.pack_start(modeInvertBox, false, false, MARGIN); modeInvertButton.set_tooltip_text(_("Invert black and white regions")); + modeInvertButton.signal_clicked().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); modeBrightnessFrame.add(modeBrightnessVBox); modePageBox.pack_start(modeBrightnessFrame, false, false, 0); @@ -504,6 +610,7 @@ TraceDialogImpl::TraceDialogImpl() : modeMultiScanBrightnessRadioButton.set_use_underline(true); modeMultiScanHBox1.pack_start(modeMultiScanBrightnessRadioButton, false, false, MARGIN); modeMultiScanBrightnessRadioButton.set_tooltip_text(_("Trace the given number of brightness levels")); + modeMultiScanBrightnessRadioButton.signal_clicked().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); modeMultiScanNrColorSpinner.set_digits(0); modeMultiScanNrColorSpinner.set_increments(1.0, 0); @@ -515,6 +622,7 @@ TraceDialogImpl::TraceDialogImpl() : modeMultiScanNrColorLabel.set_mnemonic_widget(modeMultiScanNrColorSpinner); modeMultiScanHBox1.pack_end(modeMultiScanNrColorLabel, false, false, MARGIN); modeMultiScanNrColorSpinner.set_tooltip_text(_("The desired number of scans")); + modeMultiScanNrColorSpinner.get_adjustment()->signal_value_changed().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); modeMultiScanVBox.pack_start(modeMultiScanHBox1, false, false, MARGIN); @@ -523,6 +631,7 @@ TraceDialogImpl::TraceDialogImpl() : modeMultiScanColorRadioButton.set_use_underline(true); modeMultiScanHBox2.pack_start(modeMultiScanColorRadioButton, false, false, MARGIN); modeMultiScanColorRadioButton.set_tooltip_text(_("Trace the given number of reduced colors")); + modeMultiScanColorRadioButton.signal_clicked().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); modeMultiScanVBox.pack_start(modeMultiScanHBox2, false, false, MARGIN); @@ -531,6 +640,7 @@ TraceDialogImpl::TraceDialogImpl() : modeMultiScanMonoRadioButton.set_use_underline(true); modeMultiScanHBox3.pack_start(modeMultiScanMonoRadioButton, false, false, MARGIN); modeMultiScanMonoRadioButton.set_tooltip_text(_("Same as Colors, but the result is converted to grayscale")); + modeMultiScanMonoRadioButton.signal_clicked().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); modeMultiScanVBox.pack_start(modeMultiScanHBox3, false, false, MARGIN); @@ -540,6 +650,7 @@ TraceDialogImpl::TraceDialogImpl() : modeMultiScanSmoothButton.set_active(true); modeMultiScanHBox4.pack_start(modeMultiScanSmoothButton, false, false, MARGIN); modeMultiScanSmoothButton.set_tooltip_text(_("Apply Gaussian blur to the bitmap before tracing")); + modeMultiScanSmoothButton.signal_clicked().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); // TRANSLATORS: "Stack" is a verb here modeMultiScanStackButton.set_label(_("Stac_k scans")); @@ -547,6 +658,7 @@ TraceDialogImpl::TraceDialogImpl() : modeMultiScanStackButton.set_active(true); modeMultiScanHBox4.pack_start(modeMultiScanStackButton, false, false, MARGIN); modeMultiScanStackButton.set_tooltip_text(_("Stack scans on top of one another (no gaps) instead of tiling (usually with gaps)")); + modeMultiScanStackButton.signal_clicked().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); modeMultiScanBackgroundButton.set_label(_("Remo_ve background")); @@ -555,6 +667,7 @@ TraceDialogImpl::TraceDialogImpl() : modeMultiScanHBox4.pack_start(modeMultiScanBackgroundButton, false, false, MARGIN); // TRANSLATORS: "Layer" refers to one of the stacked paths in the multiscan modeMultiScanBackgroundButton.set_tooltip_text(_("Remove bottom (background) layer when done")); + modeMultiScanBackgroundButton.signal_clicked().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); modeMultiScanVBox.pack_start(modeMultiScanHBox4, false, false, MARGIN); @@ -577,12 +690,14 @@ TraceDialogImpl::TraceDialogImpl() : optionsSpecklesButton.set_use_underline(true); optionsSpecklesButton.set_tooltip_text(_("Ignore small spots (speckles) in the bitmap")); optionsSpecklesButton.set_active(true); + optionsSpecklesButton.signal_clicked().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); optionsSpecklesBox.pack_start(optionsSpecklesButton, false, false, MARGIN); optionsSpecklesSizeSpinner.set_digits(0); optionsSpecklesSizeSpinner.set_increments(1, 0); optionsSpecklesSizeSpinner.set_range(0, 1000); optionsSpecklesSizeSpinner.set_value(2); optionsSpecklesSizeSpinner.set_tooltip_text(_("Speckles of up to this many pixels will be suppressed")); + optionsSpecklesSizeSpinner.get_adjustment()->signal_value_changed().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); optionsSpecklesBox.pack_end(optionsSpecklesSizeSpinner, false, false, MARGIN); optionsSpecklesSizeLabel.set_label(_("S_ize:")); optionsSpecklesSizeLabel.set_use_underline(true); @@ -593,6 +708,7 @@ TraceDialogImpl::TraceDialogImpl() : optionsCornersButton.set_use_underline(true); optionsCornersButton.set_tooltip_text(_("Smooth out sharp corners of the trace")); optionsCornersButton.set_active(true); + optionsCornersButton.signal_clicked().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); optionsCornersBox.pack_start(optionsCornersButton, false, false, MARGIN); optionsCornersThresholdSpinner.set_digits(2); optionsCornersThresholdSpinner.set_increments(0.01, 0); @@ -600,6 +716,7 @@ TraceDialogImpl::TraceDialogImpl() : optionsCornersThresholdSpinner.set_value(1.0); optionsCornersBox.pack_end(optionsCornersThresholdSpinner, false, false, MARGIN); optionsCornersThresholdSpinner.set_tooltip_text(_("Increase this to smooth corners more")); + optionsCornersThresholdSpinner.get_adjustment()->signal_value_changed().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); optionsCornersThresholdLabel.set_label(_("_Threshold:")); optionsCornersThresholdLabel.set_use_underline(true); optionsCornersThresholdLabel.set_mnemonic_widget(optionsCornersThresholdSpinner); @@ -609,6 +726,7 @@ TraceDialogImpl::TraceDialogImpl() : optionsOptimButton.set_use_underline(true); optionsOptimButton.set_active(true); optionsOptimButton.set_tooltip_text(_("Try to optimize paths by joining adjacent Bezier curve segments")); + optionsOptimButton.signal_clicked().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); optionsOptimBox.pack_start(optionsOptimButton, false, false, MARGIN); optionsOptimToleranceSpinner.set_digits(2); optionsOptimToleranceSpinner.set_increments(0.05, 0); @@ -616,6 +734,7 @@ TraceDialogImpl::TraceDialogImpl() : optionsOptimToleranceSpinner.set_value(0.2); optionsOptimBox.pack_end(optionsOptimToleranceSpinner, false, false, MARGIN); optionsOptimToleranceSpinner.set_tooltip_text(_("Increase this to reduce the number of nodes in the trace by more aggressive optimization")); + optionsOptimToleranceSpinner.get_adjustment()->signal_value_changed().connect( sigc::mem_fun(*this, &TraceDialogImpl::onSettingsChange) ); optionsOptimToleranceLabel.set_label(_("To_lerance:")); optionsOptimToleranceLabel.set_use_underline(true); optionsOptimToleranceLabel.set_mnemonic_widget(optionsOptimToleranceSpinner); @@ -645,7 +764,7 @@ TraceDialogImpl::TraceDialogImpl() : //#### end left panel - mainHBox.pack_start(leftVBox); + mainHBox.pack_start(leftVBox, false, false, 0); //#### begin right panel @@ -658,12 +777,20 @@ TraceDialogImpl::TraceDialogImpl() : rightVBox.pack_start(sioxBox, false, false, 0); //## preview + Gtk::HBox *previewButtonHBox = manage(new Gtk::HBox(false, MARGIN )); + previewLiveButton.set_label(_("Live Preview")); + previewLiveButton.set_use_underline(true); + previewLiveCallback(); + previewLiveButton.signal_clicked().connect( + sigc::mem_fun(*this, &TraceDialogImpl::previewLiveCallback) ); previewButton.set_label(_("_Update")); previewButton.set_use_underline(true); previewButton.signal_clicked().connect( sigc::mem_fun(*this, &TraceDialogImpl::previewCallback) ); - previewVBox.pack_end(previewButton, false, false, 0); + previewButtonHBox->pack_start(previewLiveButton, false, false, 0); + previewButtonHBox->pack_end(previewButton, true, true, 0); + previewVBox.pack_end(*previewButtonHBox, false, false, 0); // I guess it's correct to call the "intermediate bitmap" a preview of the trace previewButton.set_tooltip_text(_("Preview the intermediate bitmap with the current settings, without actual tracing")); previewImage.set_size_request(200,200); @@ -677,11 +804,13 @@ TraceDialogImpl::TraceDialogImpl() : //#### end right panel - mainHBox.pack_start(rightVBox); + mainHBox.pack_start(rightVBox, true, true, 0); //#### Global stuff contents->pack_start(mainHBox); + 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); @@ -694,6 +823,9 @@ TraceDialogImpl::TraceDialogImpl() : show_all_children(); + desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &TraceDialogImpl::setTargetDesktop) ); + deskTrack.connect(GTK_WIDGET(gobj())); + //## Connect the signal signalResponse().connect( sigc::mem_fun(*this, &TraceDialogImpl::responseCallback)); @@ -714,6 +846,9 @@ TraceDialog &TraceDialog::getInstance() */ TraceDialogImpl::~TraceDialogImpl() { + selectChangedConn.disconnect(); + selectModifiedConn.disconnect(); + desktopChangeConn.disconnect(); } diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp index 1c9d6689b..329450b52 100644 --- a/src/ui/dialog/transformation.cpp +++ b/src/ui/dialog/transformation.cpp @@ -42,16 +42,16 @@ namespace Inkscape { namespace UI { namespace Dialog { -void on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection *selection, Transformation *daad) +static void on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection *selection, Transformation *daad) { int page = daad->getCurrentPage(); daad->updateSelection((Inkscape::UI::Dialog::Transformation::PageType)page, selection); } -void on_selection_modified( Inkscape::Application */*inkscape*/, - Inkscape::Selection *selection, - guint /*flags*/, - Transformation *daad ) +static void on_selection_modified( Inkscape::Application */*inkscape*/, + Inkscape::Selection *selection, + guint /*flags*/, + Transformation *daad ) { int page = daad->getCurrentPage(); daad->updateSelection((Inkscape::UI::Dialog::Transformation::PageType)page, selection); diff --git a/src/ui/dialog/undo-history.cpp b/src/ui/dialog/undo-history.cpp index 73b76054e..b96c9158a 100644 --- a/src/ui/dialog/undo-history.cpp +++ b/src/ui/dialog/undo-history.cpp @@ -167,7 +167,7 @@ UndoHistory::UndoHistory() { if ( !_document || !_event_log || !_columns ) return; - set_size_request(300, 95); + set_size_request(-1, 95); _getContents()->pack_start(_scrolled_window); _scrolled_window.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); @@ -180,31 +180,35 @@ UndoHistory::UndoHistory() _event_list_view.set_headers_visible(false); CellRendererSPIcon* icon_renderer = Gtk::manage(new CellRendererSPIcon()); - icon_renderer->property_xpad() = 8; - icon_renderer->property_width() = 36; + icon_renderer->property_xpad() = 2; + icon_renderer->property_width() = 24; int cols_count = _event_list_view.append_column("Icon", *icon_renderer); Gtk::TreeView::Column* icon_column = _event_list_view.get_column(cols_count-1); icon_column->add_attribute(icon_renderer->property_event_type(), _columns->type); + CellRendererInt* children_renderer = Gtk::manage(new CellRendererInt(greater_than_1)); + children_renderer->property_weight() = 600; // =Pango::WEIGHT_SEMIBOLD (not defined in old versions of pangomm) + children_renderer->property_xalign() = 1.0; + children_renderer->property_xpad() = 2; + children_renderer->property_width() = 24; + + cols_count = _event_list_view.append_column("Children", *children_renderer); + Gtk::TreeView::Column* children_column = _event_list_view.get_column(cols_count-1); + children_column->add_attribute(children_renderer->property_number(), _columns->child_count); + Gtk::CellRendererText* description_renderer = Gtk::manage(new Gtk::CellRendererText()); + description_renderer->property_ellipsize() = Pango::ELLIPSIZE_END; cols_count = _event_list_view.append_column("Description", *description_renderer); Gtk::TreeView::Column* description_column = _event_list_view.get_column(cols_count-1); description_column->add_attribute(description_renderer->property_text(), _columns->description); description_column->set_resizable(); + description_column->set_sizing(Gtk::TREE_VIEW_COLUMN_AUTOSIZE); + description_column->set_min_width (150); _event_list_view.set_expander_column( *_event_list_view.get_column(cols_count-1) ); - CellRendererInt* children_renderer = Gtk::manage(new CellRendererInt(greater_than_1)); - children_renderer->property_weight() = 600; // =Pango::WEIGHT_SEMIBOLD (not defined in old versions of pangomm) - children_renderer->property_xalign() = 1.0; - children_renderer->property_xpad() = 20; - - cols_count = _event_list_view.append_column("Children", *children_renderer); - Gtk::TreeView::Column* children_column = _event_list_view.get_column(cols_count-1); - children_column->add_attribute(children_renderer->property_number(), _columns->child_count); - _scrolled_window.add(_event_list_view); // connect EventLog callbacks diff --git a/src/ui/previewable.h b/src/ui/previewable.h index 9a086a9a2..377e109fb 100644 --- a/src/ui/previewable.h +++ b/src/ui/previewable.h @@ -35,12 +35,13 @@ typedef enum { VIEW_TYPE_GRID } ViewType; + class Previewable { public: // TODO need to add some nice parameters virtual ~Previewable() {} - virtual Gtk::Widget* getPreview( PreviewStyle style, ViewType view, ::PreviewSize size, guint ratio ) = 0; + virtual Gtk::Widget* getPreview( PreviewStyle style, ViewType view, ::PreviewSize size, guint ratio, guint border) = 0; }; diff --git a/src/ui/previewfillable.h b/src/ui/previewfillable.h index d5f609a0b..044357503 100644 --- a/src/ui/previewfillable.h +++ b/src/ui/previewfillable.h @@ -28,11 +28,12 @@ public: virtual void addPreview( Previewable* preview ) = 0; virtual void freezeUpdates() = 0; virtual void thawUpdates() = 0; - virtual void setStyle( ::PreviewSize size, ViewType type, guint ratio) = 0; + virtual void setStyle( ::PreviewSize size, ViewType type, guint ratio, ::BorderStyle border ) = 0; virtual void setOrientation(SPAnchorType how) = 0; virtual ::PreviewSize getPreviewSize() const = 0; virtual ViewType getPreviewType() const = 0; virtual guint getPreviewRatio() const = 0; + virtual ::BorderStyle getPreviewBorder() const = 0; virtual void setWrap( bool b ) = 0; virtual bool getWrap() const = 0; }; diff --git a/src/ui/previewholder.cpp b/src/ui/previewholder.cpp index e1c2c718a..0b280ccb9 100644 --- a/src/ui/previewholder.cpp +++ b/src/ui/previewholder.cpp @@ -12,10 +12,12 @@ #include "previewholder.h" +#include "preferences.h" #include <gtkmm/scrolledwindow.h> #include <gtkmm/sizegroup.h> #include <gtkmm/scrollbar.h> +#include <gtkmm/adjustment.h> #define COLUMNS_FOR_SMALL 16 #define COLUMNS_FOR_LARGE 8 @@ -38,7 +40,8 @@ PreviewHolder::PreviewHolder() : _baseSize(PREVIEW_SIZE_SMALL), _ratio(100), _view(VIEW_TYPE_LIST), - _wrap(false) + _wrap(false), + _border(BORDER_NONE) { _scroller = manage(new Gtk::ScrolledWindow()); _insides = manage(new Gtk::Table( 1, 2 )); @@ -54,9 +57,30 @@ PreviewHolder::PreviewHolder() : PreviewHolder::~PreviewHolder() { + } +bool PreviewHolder::on_scroll_event(GdkEventScroll *event) +{ + // Scroll horizontally by page on mouse wheel +#if WITH_GTKMM_3_0 + Glib::RefPtr<Gtk::Adjustment> adj = dynamic_cast<Gtk::ScrolledWindow*>(_scroller)->get_hadjustment(); +#else + Gtk::Adjustment *adj = dynamic_cast<Gtk::ScrolledWindow*>(_scroller)->get_hadjustment(); +#endif + + if (!adj) { + return FALSE; + } + + int move = (event->direction == GDK_SCROLL_DOWN) ? adj->get_page_size() : -adj->get_page_size(); + double value = std::min(adj->get_upper() - move, adj->get_value() + move ); + + adj->set_value(value); + + return FALSE; +} void PreviewHolder::clear() { @@ -77,13 +101,13 @@ void PreviewHolder::addPreview( Previewable* preview ) int i = items.size() - 1; if ( _view == VIEW_TYPE_LIST ) { - Gtk::Widget* label = manage(preview->getPreview(PREVIEW_STYLE_BLURB, VIEW_TYPE_LIST, _baseSize, _ratio)); - Gtk::Widget* thing = manage(preview->getPreview(PREVIEW_STYLE_PREVIEW, VIEW_TYPE_LIST, _baseSize, _ratio)); + Gtk::Widget* label = manage(preview->getPreview(PREVIEW_STYLE_BLURB, VIEW_TYPE_LIST, _baseSize, _ratio, _border)); + Gtk::Widget* thing = manage(preview->getPreview(PREVIEW_STYLE_PREVIEW, VIEW_TYPE_LIST, _baseSize, _ratio, _border)); _insides->attach( *thing, 0, 1, i, i+1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); _insides->attach( *label, 1, 2, i, i+1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK ); } else { - Gtk::Widget* thing = manage(items[i]->getPreview(PREVIEW_STYLE_PREVIEW, VIEW_TYPE_GRID, _baseSize, _ratio)); + Gtk::Widget* thing = manage(items[i]->getPreview(PREVIEW_STYLE_PREVIEW, VIEW_TYPE_GRID, _baseSize, _ratio, _border)); int width = 1; int height = 1; @@ -129,12 +153,13 @@ void PreviewHolder::thawUpdates() rebuildUI(); } -void PreviewHolder::setStyle( ::PreviewSize size, ViewType view, guint ratio ) +void PreviewHolder::setStyle( ::PreviewSize size, ViewType view, guint ratio, ::BorderStyle border ) { - if ( size != _baseSize || view != _view || ratio != _ratio ) { + if ( size != _baseSize || view != _view || ratio != _ratio || border != _border ) { _baseSize = size; _view = view; _ratio = ratio; + _border = border; // Kludge to restore scrollbars if ( !_wrap && (_view != VIEW_TYPE_LIST) && (_anchor == SP_ANCHOR_NORTH || _anchor == SP_ANCHOR_SOUTH) ) { dynamic_cast<Gtk::ScrolledWindow*>(_scroller)->set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_NEVER ); @@ -304,12 +329,15 @@ void PreviewHolder::rebuildUI() if ( _view == VIEW_TYPE_LIST ) { _insides = manage(new Gtk::Table( 1, 2 )); _insides->set_col_spacings( 8 ); + if (_border == BORDER_WIDE) { + _insides->set_row_spacings( 1 ); + } for ( unsigned int i = 0; i < items.size(); i++ ) { - Gtk::Widget* label = manage(items[i]->getPreview(PREVIEW_STYLE_BLURB, _view, _baseSize, _ratio)); + Gtk::Widget* label = manage(items[i]->getPreview(PREVIEW_STYLE_BLURB, _view, _baseSize, _ratio, _border)); //label->set_alignment(Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER); - Gtk::Widget* thing = manage(items[i]->getPreview(PREVIEW_STYLE_PREVIEW, _view, _baseSize, _ratio)); + Gtk::Widget* thing = manage(items[i]->getPreview(PREVIEW_STYLE_PREVIEW, _view, _baseSize, _ratio, _border)); _insides->attach( *thing, 0, 1, i, i+1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); _insides->attach( *label, 1, 2, i, i+1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK ); @@ -322,11 +350,18 @@ void PreviewHolder::rebuildUI() int height = 1; for ( unsigned int i = 0; i < items.size(); i++ ) { - Gtk::Widget* thing = manage(items[i]->getPreview(PREVIEW_STYLE_PREVIEW, _view, _baseSize, _ratio)); + + // If this is the last row, flag so the previews can draw a bottom + ::BorderStyle border = ((row == height -1) && (_border == BORDER_SOLID)) ? BORDER_SOLID_LAST_ROW : _border; + Gtk::Widget* thing = manage(items[i]->getPreview(PREVIEW_STYLE_PREVIEW, _view, _baseSize, _ratio, border)); if ( !_insides ) { calcGridSize( thing, items.size(), width, height ); _insides = manage(new Gtk::Table( height, width )); + if (_border == BORDER_WIDE) { + _insides->set_col_spacings( 1 ); + _insides->set_row_spacings( 1 ); + } } _insides->attach( *thing, col, col+1, row, row+1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); diff --git a/src/ui/previewholder.h b/src/ui/previewholder.h index b7073024e..4c591bfaf 100644 --- a/src/ui/previewholder.h +++ b/src/ui/previewholder.h @@ -33,18 +33,20 @@ public: virtual void addPreview( Previewable* preview ); virtual void freezeUpdates(); virtual void thawUpdates(); - virtual void setStyle( ::PreviewSize size, ViewType view, guint ratio ); + virtual void setStyle( ::PreviewSize size, ViewType view, guint ratio, ::BorderStyle border ); virtual void setOrientation(SPAnchorType how); virtual int getColumnPref() const { return _prefCols; } virtual void setColumnPref( int cols ); virtual ::PreviewSize getPreviewSize() const { return _baseSize; } virtual ViewType getPreviewType() const { return _view; } virtual guint getPreviewRatio() const { return _ratio; } + virtual ::BorderStyle getPreviewBorder() const { return _border; } virtual void setWrap( bool b ); virtual bool getWrap() const { return _wrap; } protected: virtual void on_size_allocate( Gtk::Allocation& allocation ); + virtual bool on_scroll_event(GdkEventScroll*); // virtual void on_size_request( Gtk::Requisition* requisition ); @@ -62,6 +64,7 @@ private: guint _ratio; ViewType _view; bool _wrap; + ::BorderStyle _border; }; } //namespace UI diff --git a/src/ui/tool/node-tool.cpp b/src/ui/tool/node-tool.cpp index b532c8b65..7b6502ec3 100644 --- a/src/ui/tool/node-tool.cpp +++ b/src/ui/tool/node-tool.cpp @@ -197,6 +197,10 @@ void ink_node_tool_dispose(GObject *object) nt->enableGrDrag(false); + if (nt->flash_tempitem) { + nt->desktop->remove_temporary_canvasitem(nt->flash_tempitem); + } + nt->_selection_changed_connection.disconnect(); nt->_selection_modified_connection.disconnect(); nt->_mouseover_changed_connection.disconnect(); diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index bda410856..dc6e0fbae 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -293,7 +293,7 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event) Geom::Point parent_pos = _parent->position(); Geom::Point origin = _last_drag_origin(); SnapManager &sm = _desktop->namedview->snap_manager; - bool snap = sm.someSnapperMightSnap(); + bool snap = held_shift(*event) ? false : sm.someSnapperMightSnap(); boost::optional<Inkscape::Snapper::SnapConstraint> ctrl_constraint; // with Alt, preserve length diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert index 8589f16b0..bbda64648 100644 --- a/src/ui/widget/Makefile_insert +++ b/src/ui/widget/Makefile_insert @@ -19,6 +19,8 @@ ink_common_sources += \ ui/widget/entry.h \ ui/widget/filter-effect-chooser.h \ ui/widget/filter-effect-chooser.cpp \ + ui/widget/gimpspinscale.c \ + ui/widget/gimpspinscale.h \ ui/widget/frame.cpp \ ui/widget/frame.h \ ui/widget/imageicon.cpp \ @@ -62,6 +64,8 @@ ink_common_sources += \ ui/widget/selected-style.cpp \ ui/widget/spinbutton.h \ ui/widget/spinbutton.cpp \ + ui/widget/spin-scale.h \ + ui/widget/spin-scale.cpp \ ui/widget/spin-slider.h \ ui/widget/spin-slider.cpp \ ui/widget/style-subject.h \ diff --git a/src/ui/widget/color-picker.cpp b/src/ui/widget/color-picker.cpp index e5c542a7c..31fb3096c 100644 --- a/src/ui/widget/color-picker.cpp +++ b/src/ui/widget/color-picker.cpp @@ -55,7 +55,7 @@ void ColorPicker::setupDialog(const Glib::ustring &title) _colorSelectorDialog.hide(); _colorSelectorDialog.set_title (title); _colorSelectorDialog.set_border_width (4); - _colorSelector = (SPColorSelector*)sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK); + _colorSelector = SP_COLOR_SELECTOR(sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK)); _colorSelectorDialog.get_vbox()->pack_start ( *Glib::wrap(&_colorSelector->vbox), true, true, 0); diff --git a/src/ui/widget/dock.cpp b/src/ui/widget/dock.cpp index a7dabef1c..a38a93fb1 100644 --- a/src/ui/widget/dock.cpp +++ b/src/ui/widget/dock.cpp @@ -81,9 +81,15 @@ Dock::Dock(Gtk::Orientation orientation) static_cast<GdlSwitcherStyle>(prefs->getIntLimited("/options/dock/switcherstyle", GDL_SWITCHER_STYLE_BOTH, 0, 4)); - g_object_set (GDL_DOCK_OBJECT(_gdl_dock)->master, - "switcher-style", gdl_switcher_style, - NULL); + GdlDockMaster* master = NULL; + + g_object_get(GDL_DOCK_OBJECT(_gdl_dock), + "master", &master, + NULL); + + g_object_set(master, + "switcher-style", gdl_switcher_style, + NULL); GdlDockBarStyle gdl_dock_bar_style = static_cast<GdlDockBarStyle>(prefs->getIntLimited("/options/dock/dockbarstyle", diff --git a/src/ui/widget/filter-effect-chooser.cpp b/src/ui/widget/filter-effect-chooser.cpp index 8d6bcf60f..65706a9dc 100644 --- a/src/ui/widget/filter-effect-chooser.cpp +++ b/src/ui/widget/filter-effect-chooser.cpp @@ -22,12 +22,9 @@ namespace UI { namespace Widget { SimpleFilterModifier::SimpleFilterModifier(int flags) - : _hb_blur(false, 0), - _lb_blend(_("Blend mode:")), - _lb_blur(_("_Blur:")), - _lb_blur_unit(_("%")), + : _lb_blend(_("Blend mode:")), _blend(BlendModeConverter, SP_ATTR_INVALID, false), - _blur(0, 0, 100, 1, 0.01, 1) + _blur(_("Blur (%)"), 0, 0, 100, 1, 0.01, 1) { _flags = flags; @@ -37,11 +34,7 @@ SimpleFilterModifier::SimpleFilterModifier(int flags) _hb_blend.pack_start(_blend); } if (flags & BLUR) { - add(_hb_blur); - _lb_blur.set_alignment(Gtk::ALIGN_END, Gtk::ALIGN_CENTER); - _hb_blur.pack_start(_lb_blur, false, false, 0); - _hb_blur.pack_start(_blur, true, true, 0); - _hb_blur.pack_start(_lb_blur_unit, false, false, 3); + add(_blur); } show_all_children(); @@ -49,8 +42,6 @@ SimpleFilterModifier::SimpleFilterModifier(int flags) _hb_blend.set_spacing(12); _lb_blend.set_use_underline(); _lb_blend.set_mnemonic_widget(_blend); - _lb_blur.set_use_underline(); - _lb_blur.set_mnemonic_widget(_blur.get_scale()); _blend.signal_changed().connect(signal_blend_blur_changed()); _blur.signal_value_changed().connect(signal_blend_blur_changed()); } diff --git a/src/ui/widget/filter-effect-chooser.h b/src/ui/widget/filter-effect-chooser.h index 6afb6c180..ae3ec07c4 100644 --- a/src/ui/widget/filter-effect-chooser.h +++ b/src/ui/widget/filter-effect-chooser.h @@ -18,6 +18,7 @@ #include "combo-enums.h" #include "filter-enums.h" #include "spin-slider.h" +#include "spin-scale.h" namespace Inkscape { namespace UI { @@ -45,17 +46,14 @@ public: double get_blur_value() const; void set_blur_value(const double); void set_blur_sensitive(const bool); - Gtk::Label *get_blur_label() { return &_lb_blur; }; - private: int _flags; Gtk::HBox _hb_blend; - Gtk::HBox _hb_blur; - Gtk::Label _lb_blend, _lb_blur, _lb_blur_unit; + Gtk::Label _lb_blend; ComboBoxEnum<Inkscape::Filters::FilterBlendMode> _blend; - SpinSlider _blur; + SpinScale _blur; sigc::signal<void> _signal_blend_blur_changed; }; diff --git a/src/ui/widget/frame.cpp b/src/ui/widget/frame.cpp index b2968f806..eaa4336bb 100644 --- a/src/ui/widget/frame.cpp +++ b/src/ui/widget/frame.cpp @@ -56,9 +56,7 @@ Frame::set_label(const Glib::ustring &label_text, gboolean label_bold /*= TRUE*/ void Frame::set_padding (guint padding_top, guint padding_bottom, guint padding_left, guint padding_right) { -#if WITH_GTKMM_2_24 _alignment.set_padding(padding_top, padding_bottom, padding_left, padding_right); -#endif } Gtk::Label const * diff --git a/src/ui/widget/gimpspinscale.c b/src/ui/widget/gimpspinscale.c new file mode 100644 index 000000000..f9f9a3807 --- /dev/null +++ b/src/ui/widget/gimpspinscale.c @@ -0,0 +1,1092 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpspinscale.c + * Copyright (C) 2010 Michael Natterer <mitch@gimp.org> + * 2012 Øyvind Kolås <pippin@gimp.org> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <math.h> +#include <string.h> +#include <gdk/gdkkeysyms.h> + +#include "gimpspinscale.h" + + +enum +{ + PROP_0, + PROP_LABEL, + PROP_FOCUS_WIDGET +}; + +typedef enum +{ + TARGET_NUMBER, + TARGET_UPPER, + TARGET_LOWER +#if WITH_GTKMM_3_0 + ,TARGET_NONE +#endif +} SpinScaleTarget; + +typedef enum +{ + APPEARANCE_FULL = 1, /* Full size suitable for tablets */ + APPEARANCE_COMPACT, /* Compact, suitable for desktops with mouse control */ +} SpinScaleAppearance; + +typedef struct _GimpSpinScalePrivate GimpSpinScalePrivate; + +struct _GimpSpinScalePrivate +{ + gchar *label; + + gboolean scale_limits_set; + gdouble scale_lower; + gdouble scale_upper; + gdouble gamma; + + PangoLayout *layout; + gboolean changing_value; + gboolean relative_change; + gdouble start_x; + gdouble start_value; + + GtkWidget* focusWidget; + gboolean transferFocus; + SpinScaleAppearance appearanceMode; +}; + +#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + GIMP_TYPE_SPIN_SCALE, \ + GimpSpinScalePrivate)) + + +static void gimp_spin_scale_dispose (GObject *object); +static void gimp_spin_scale_finalize (GObject *object); +static void gimp_spin_scale_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_spin_scale_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static void gimp_spin_scale_style_set (GtkWidget *widget, + GtkStyle *prev_style); + +#if WITH_GTKMM_3_0 +static void gimp_spin_scale_get_preferred_width (GtkWidget *widget, + gint *minimum_width, + gint *natural_width); +static void gimp_spin_scale_get_preferred_height (GtkWidget *widget, + gint *minimum_width, + gint *natural_width); +static gboolean gimp_spin_scale_draw (GtkWidget *widget, + cairo_t *cr); +#else +static void gimp_spin_scale_size_request (GtkWidget *widget, + GtkRequisition *requisition); + +static gboolean gimp_spin_scale_expose (GtkWidget *widget, + GdkEventExpose *event); +#endif + +static gboolean gimp_spin_scale_button_press (GtkWidget *widget, + GdkEventButton *event); +static gboolean gimp_spin_scale_button_release (GtkWidget *widget, + GdkEventButton *event); +static gboolean gimp_spin_scale_motion_notify (GtkWidget *widget, + GdkEventMotion *event); +static gboolean gimp_spin_scale_leave_notify (GtkWidget *widget, + GdkEventCrossing *event); +static gboolean gimp_spin_scale_keypress( GtkWidget *widget, + GdkEventKey *event); + +static void gimp_spin_scale_defocus( GtkSpinButton *spin_button ); + +static void gimp_spin_scale_value_changed (GtkSpinButton *spin_button); + + +G_DEFINE_TYPE (GimpSpinScale, gimp_spin_scale, GTK_TYPE_SPIN_BUTTON); + +#define parent_class gimp_spin_scale_parent_class + + +static void +gimp_spin_scale_class_init (GimpSpinScaleClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GtkSpinButtonClass *spin_button_class = GTK_SPIN_BUTTON_CLASS (klass); + + object_class->dispose = gimp_spin_scale_dispose; + object_class->finalize = gimp_spin_scale_finalize; + object_class->set_property = gimp_spin_scale_set_property; + object_class->get_property = gimp_spin_scale_get_property; + + widget_class->style_set = gimp_spin_scale_style_set; +#if WITH_GTKMM_3_0 + widget_class->get_preferred_width = gimp_spin_scale_get_preferred_width; + widget_class->get_preferred_height = gimp_spin_scale_get_preferred_height; + widget_class->draw = gimp_spin_scale_draw; +#else + widget_class->size_request = gimp_spin_scale_size_request; + widget_class->expose_event = gimp_spin_scale_expose; +#endif + widget_class->button_press_event = gimp_spin_scale_button_press; + widget_class->button_release_event = gimp_spin_scale_button_release; + widget_class->motion_notify_event = gimp_spin_scale_motion_notify; + widget_class->leave_notify_event = gimp_spin_scale_leave_notify; + widget_class->key_press_event = gimp_spin_scale_keypress; + + spin_button_class->value_changed = gimp_spin_scale_value_changed; + + g_object_class_install_property (object_class, PROP_LABEL, + g_param_spec_string ("label", NULL, NULL, + NULL, + G_PARAM_READWRITE)); + + g_type_class_add_private (klass, sizeof (GimpSpinScalePrivate)); +} + +static void +gimp_spin_scale_init (GimpSpinScale *scale) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (scale); + + gtk_entry_set_alignment (GTK_ENTRY (scale), 1.0); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (scale), TRUE); + + private->gamma = 1.0; + private->focusWidget = NULL; + private->transferFocus = FALSE; + private->appearanceMode = APPEARANCE_COMPACT; +} + +static void +gimp_spin_scale_dispose (GObject *object) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (object); + + if (private->layout) + { + g_object_unref (private->layout); + private->layout = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gimp_spin_scale_finalize (GObject *object) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (object); + + if (private->label) + { + g_free (private->label); + private->label = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gimp_spin_scale_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (object); + + switch (property_id) + { + case PROP_LABEL: + g_free (private->label); + private->label = g_value_dup_string (value); + if (private->layout) + { + g_object_unref (private->layout); + private->layout = NULL; + } + gtk_widget_queue_resize (GTK_WIDGET (object)); + break; + + case PROP_FOCUS_WIDGET: + { + /* TODO unhook prior */ + private->focusWidget = (GtkWidget*)g_value_get_pointer( value ); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_spin_scale_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (object); + + switch (property_id) + { + case PROP_LABEL: + g_value_set_string (value, private->label); + break; + + case PROP_FOCUS_WIDGET: + g_value_set_pointer( value, private->focusWidget ); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + + +void +gimp_spin_scale_set_focuswidget( GtkWidget *scale, GtkWidget* widget ) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (scale); + + /* TODO unhook prior */ + + private->focusWidget = widget; +} + +void +gimp_spin_scale_set_appearance( GtkWidget *widget, const gchar *appearance) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); + + if ( strcmp("full", appearance) == 0 ) { + private->appearanceMode = APPEARANCE_FULL; + } else if ( strcmp("compact", appearance) == 0 ) { + private->appearanceMode = APPEARANCE_COMPACT; + } +} + +static void +#if WITH_GTKMM_3_0 +gimp_spin_scale_get_preferred_width (GtkWidget *widget, + gint *minimum_width, + gint *natural_width) +#else +gimp_spin_scale_size_request (GtkWidget *widget, + GtkRequisition *requisition) +#endif +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); + GtkStyle *style = gtk_widget_get_style (widget); + PangoContext *context = gtk_widget_get_pango_context (widget); + PangoFontMetrics *metrics; + +#if WITH_GTKMM_3_0 + GTK_WIDGET_CLASS (parent_class)->get_preferred_width (widget, + minimum_width, + natural_width); +#else + gint height; + GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition); +#endif + + metrics = pango_context_get_metrics (context, style->font_desc, + pango_context_get_language (context)); + +#if WITH_GTKMM_3_0 +#else + height = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) + + pango_font_metrics_get_descent (metrics)); + + if (private->appearanceMode == APPEARANCE_COMPACT) { + requisition->height += 1; + } else { + requisition->height += height; + } + +#endif + + + if (private->label) + { + gint char_width; + gint digit_width; + gint char_pixels; + + char_width = pango_font_metrics_get_approximate_char_width (metrics); + digit_width = pango_font_metrics_get_approximate_digit_width (metrics); + char_pixels = PANGO_PIXELS (MAX (char_width, digit_width)); + +#if WITH_GTKMM_3_0 + *minimum_width += char_pixels * 3; + *natural_width += char_pixels * 3; +#else + /* ~3 chars for the ellipses */ + requisition->width += char_pixels * 3; +#endif + + } + + pango_font_metrics_unref (metrics); +} + +#if WITH_GTKMM_3_0 +static void +gimp_spin_scale_get_preferred_height (GtkWidget *widget, + gint *minimum_height, + gint *natural_height) +{ + GtkStyle *style = gtk_widget_get_style (widget); + PangoContext *context = gtk_widget_get_pango_context (widget); + PangoFontMetrics *metrics; + //gint height; + + GTK_WIDGET_CLASS (parent_class)->get_preferred_height (widget, + minimum_height, + natural_height); + + metrics = pango_context_get_metrics (context, style->font_desc, + pango_context_get_language (context)); + + //height = PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) + + // pango_font_metrics_get_descent (metrics)); + + *minimum_height += 1; + *natural_height += 1; + + pango_font_metrics_unref (metrics); +} +#endif + +static void +gimp_spin_scale_style_set (GtkWidget *widget, + GtkStyle *prev_style) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); + + GTK_WIDGET_CLASS (parent_class)->style_set (widget, prev_style); + + if (private->layout) + { + g_object_unref (private->layout); + private->layout = NULL; + } +} + + +static gboolean + +#if WITH_GTKMM_3_0 + gimp_spin_scale_draw (GtkWidget *widget, cairo_t *cr) +#else + gimp_spin_scale_expose (GtkWidget *widget, GdkEventExpose *event) +#endif +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); + +#if WITH_GTKMM_3_0 + GtkStyleContext *style = gtk_widget_get_style_context(widget); + GtkAllocation allocation; + GdkRGBA color; + + cairo_save (cr); + GTK_WIDGET_CLASS (parent_class)->draw (widget, cr); + cairo_restore (cr); + + gtk_widget_get_allocation (widget, &allocation); +#else + GtkStyle *style = gtk_widget_get_style (widget); + cairo_t *cr; + gint w; + + GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event); + + cr = gdk_cairo_create (event->window); + gdk_cairo_region (cr, event->region); + cairo_clip (cr); + + w = gdk_window_get_width (event->window); +#endif + + cairo_set_line_width (cr, 1.0); + + +#if WITH_GTKMM_3_0 + if (private->label) + { + GdkRectangle text_area; + gint minimum_width; + gint natural_width; +#else + if (private->label && + gtk_widget_is_drawable (widget) && + event->window == gtk_entry_get_text_window (GTK_ENTRY (widget))) + { + GtkRequisition requisition; + GtkAllocation allocation; +#endif + + PangoRectangle logical; + gint layout_offset_x; + gint layout_offset_y; + +#if WITH_GTKMM_3_0 + gtk_entry_get_text_area (GTK_ENTRY (widget), &text_area); + + GTK_WIDGET_CLASS (parent_class)->get_preferred_width (widget, + &minimum_width, + &natural_width); +#else + GTK_WIDGET_CLASS (parent_class)->size_request (widget, &requisition); + gtk_widget_get_allocation (widget, &allocation); +#endif + + if (! private->layout) + { + private->layout = gtk_widget_create_pango_layout (widget, + private->label); + pango_layout_set_ellipsize (private->layout, PANGO_ELLIPSIZE_END); + } + + pango_layout_set_width (private->layout, + PANGO_SCALE * +#if WITH_GTKMM_3_0 + (allocation.width - minimum_width + 10)); +#else + (allocation.width - requisition.width + 10)); +#endif + pango_layout_get_pixel_extents (private->layout, NULL, &logical); + + gtk_entry_get_layout_offsets (GTK_ENTRY (widget), NULL, &layout_offset_y); + + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) +#if WITH_GTKMM_3_0 + layout_offset_x = text_area.x + text_area.width - logical.width - 4; +#else + layout_offset_x = w - logical.width - 4; +#endif + else + layout_offset_x = 4; + + layout_offset_x -= logical.x; + +#if WITH_GTKMM_3_0 + cairo_move_to (cr, layout_offset_x, text_area.y + layout_offset_y-3); + + gtk_style_context_get_color (style, gtk_widget_get_state_flags (widget), + &color); + + gdk_cairo_set_source_rgba (cr, &color); +#else + cairo_move_to (cr, layout_offset_x, layout_offset_y-3); + + gdk_cairo_set_source_color (cr, + &style->text[gtk_widget_get_state (widget)]); +#endif + + pango_cairo_show_layout (cr, private->layout); + } + +#if WITH_GTKMM_3_0 +#else + cairo_destroy (cr); +#endif + + return FALSE; +} + +#if WITH_GTKMM_3_0 +/* Returns TRUE if a translation should be done */ +static gboolean +gtk_widget_get_translation_to_window (GtkWidget *widget, + GdkWindow *window, + int *x, + int *y) +{ + GdkWindow *w, *widget_window; + + if (!gtk_widget_get_has_window (widget)) + { + GtkAllocation allocation; + + gtk_widget_get_allocation (widget, &allocation); + + *x = -allocation.x; + *y = -allocation.y; + } + else + { + *x = 0; + *y = 0; + } + + widget_window = gtk_widget_get_window (widget); + + for (w = window; w && w != widget_window; w = gdk_window_get_parent (w)) + { + int wx, wy; + gdk_window_get_position (w, &wx, &wy); + *x += wx; + *y += wy; + } + + if (w == NULL) + { + *x = 0; + *y = 0; + return FALSE; + } + + return TRUE; +} + +static void +gimp_spin_scale_event_to_widget_coords (GtkWidget *widget, + GdkWindow *window, + gdouble event_x, + gdouble event_y, + gint *widget_x, + gint *widget_y) +{ + gint tx, ty; + + if (gtk_widget_get_translation_to_window (widget, window, &tx, &ty)) + { + event_x += tx; + event_y += ty; + } + + *widget_x = event_x; + *widget_y = event_y; +} +#endif + +static SpinScaleTarget +gimp_spin_scale_get_target (GtkWidget *widget, + gdouble x, + gdouble y) +{ + GtkAllocation allocation; + PangoRectangle logical; + gint layout_x; + gint layout_y; + + gtk_widget_get_allocation (widget, &allocation); + gtk_entry_get_layout_offsets (GTK_ENTRY (widget), &layout_x, &layout_y); + pango_layout_get_pixel_extents (gtk_entry_get_layout (GTK_ENTRY (widget)), + NULL, &logical); + +#if WITH_GTKMM_3_0 + GdkRectangle text_area; + gtk_entry_get_text_area (GTK_ENTRY (widget), &text_area); + + if (x >= text_area.x && x < text_area.width && + y >= text_area.y && y < text_area.height) + { + x -= text_area.x; + y -= text_area.y; + + if (x > layout_x && x < layout_x + logical.width && + y > layout_y && y < layout_y + logical.height) + { + return TARGET_NUMBER; + } + else if (y > text_area.height / 2) + { + return TARGET_LOWER; + } + + return TARGET_UPPER; + } + + return TARGET_NONE; +#else + if (x > layout_x && x < layout_x + logical.width && + y > layout_y && y < layout_y + logical.height) + { + return TARGET_NUMBER; + } + + else if (y > allocation.height / 2) + { + return TARGET_LOWER; + } + return TARGET_UPPER; +#endif +} + +static void +gimp_spin_scale_get_limits (GimpSpinScale *scale, + gdouble *lower, + gdouble *upper) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (scale); + + if (private->scale_limits_set) + { + *lower = private->scale_lower; + *upper = private->scale_upper; + } + else + { + GtkSpinButton *spin_button = GTK_SPIN_BUTTON (scale); + GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin_button); + + *lower = gtk_adjustment_get_lower (adjustment); + *upper = gtk_adjustment_get_upper (adjustment); + } +} + +static void +gimp_spin_scale_change_value (GtkWidget *widget, + gdouble x) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); + GtkSpinButton *spin_button = GTK_SPIN_BUTTON (widget); + GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin_button); + gdouble lower; + gdouble upper; + gdouble value; +#if WITH_GTKMM_3_0 +#else +#endif +#if WITH_GTKMM_3_0 + GdkRectangle text_area; + gtk_entry_get_text_area (GTK_ENTRY (widget), &text_area); + gimp_spin_scale_get_limits (GIMP_SPIN_SCALE (widget), &lower, &upper); +#else + GdkWindow *text_window = gtk_entry_get_text_window (GTK_ENTRY (widget)); + gint width; + + gimp_spin_scale_get_limits (GIMP_SPIN_SCALE (widget), &lower, &upper); + + width = gdk_window_get_width (text_window); +#endif + + + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) +#if WITH_GTKMM_3_0 + x = text_area.width - x; +#else + x = width - x; +#endif + + + if (private->relative_change) + { + gdouble diff; + gdouble step; + + +#if WITH_GTKMM_3_0 + step = (upper - lower) / text_area.width / 10.0; +#else + step = (upper - lower) / width / 10.0; +#endif + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL) + +#if WITH_GTKMM_3_0 + diff = x - (text_area.width - private->start_x); +#else + diff = x - (width - private->start_x); +#endif + else + diff = x - private->start_x; + + value = (private->start_value + diff * step); + } + else + { + gdouble fraction; + + +#if WITH_GTKMM_3_0 + fraction = x / (gdouble) text_area.width; +#else + fraction = x / (gdouble) width; +#endif + if (fraction > 0.0) + fraction = pow (fraction, private->gamma); + + value = fraction * (upper - lower) + lower; + } + + gtk_adjustment_set_value (adjustment, value); +} + +static gboolean +gimp_spin_scale_button_press (GtkWidget *widget, + GdkEventButton *event) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); + + private->changing_value = FALSE; + private->relative_change = FALSE; + +#if WITH_GTKMM_3_0 + gint x, y; + gimp_spin_scale_event_to_widget_coords (widget, event->window, + event->x, event->y, + &x, &y); + switch (gimp_spin_scale_get_target (widget, x, y)) + { + case TARGET_UPPER: + private->changing_value = TRUE; + + gtk_widget_grab_focus (widget); + + gimp_spin_scale_change_value (widget, x); + + return TRUE; + + case TARGET_LOWER: + private->changing_value = TRUE; + + gtk_widget_grab_focus (widget); + + private->relative_change = TRUE; + private->start_x = x; + private->start_value = gtk_adjustment_get_value (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (widget))); + + return TRUE; + + default: + break; + } +#else + if (event->window == gtk_entry_get_text_window (GTK_ENTRY (widget))) + { + switch (gimp_spin_scale_get_target (widget, event->x, event->y)) + { + case TARGET_UPPER: + private->changing_value = TRUE; + + gtk_widget_grab_focus (widget); + + gimp_spin_scale_change_value (widget, event->x); + + return TRUE; + + case TARGET_LOWER: + private->changing_value = TRUE; + + gtk_widget_grab_focus (widget); + + private->relative_change = TRUE; + private->start_x = event->x; + private->start_value = gtk_adjustment_get_value (gtk_spin_button_get_adjustment (GTK_SPIN_BUTTON (widget))); + + return TRUE; + + default: + break; + } + } +#endif + + return GTK_WIDGET_CLASS (parent_class)->button_press_event (widget, event); +} + +static gboolean +gimp_spin_scale_button_release (GtkWidget *widget, + GdkEventButton *event) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); +#if WITH_GTKMM_3_0 + gint x, y; + + gimp_spin_scale_event_to_widget_coords (widget, event->window, + event->x, event->y, + &x, &y); +#endif + + if (private->changing_value) + { + private->changing_value = FALSE; +#if WITH_GTKMM_3_0 + gimp_spin_scale_change_value (widget, x); +#else + gimp_spin_scale_change_value (widget, event->x); +#endif + return TRUE; + } + + return GTK_WIDGET_CLASS (parent_class)->button_release_event (widget, event); +} + +static gboolean +gimp_spin_scale_motion_notify (GtkWidget *widget, + GdkEventMotion *event) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); +#if WITH_GTKMM_3_0 + gint x, y; + + gimp_spin_scale_event_to_widget_coords (widget, event->window, + event->x, event->y, + &x, &y); +#endif + + if (private->changing_value) + { +#if WITH_GTKMM_3_0 + gimp_spin_scale_change_value (widget, x); +#else + gimp_spin_scale_change_value (widget, event->x); +#endif + + return TRUE; + } + + GTK_WIDGET_CLASS (parent_class)->motion_notify_event (widget, event); + + if (! (event->state & + (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) +#if WITH_GTKMM_3_0 +#else + && event->window == gtk_entry_get_text_window (GTK_ENTRY (widget)) +#endif + ) + { + GdkDisplay *display = gtk_widget_get_display (widget); + GdkCursor *cursor = NULL; + +#if WITH_GTKMM_3_0 + switch (gimp_spin_scale_get_target (widget, x, y)) +#else + switch (gimp_spin_scale_get_target (widget, event->x, event->y)) +#endif + { + case TARGET_NUMBER: + cursor = gdk_cursor_new_for_display (display, GDK_XTERM); + break; + + case TARGET_UPPER: + cursor = gdk_cursor_new_for_display (display, GDK_SB_UP_ARROW); + break; + + case TARGET_LOWER: + cursor = gdk_cursor_new_for_display (display, GDK_SB_H_DOUBLE_ARROW); + break; + + default: + break; + } + + +#if WITH_GTKMM_3_0 + if (cursor) + { + gdk_window_set_cursor (event->window, cursor); + g_object_unref (cursor); + } +#else + gdk_window_set_cursor (event->window, cursor); + gdk_cursor_unref (cursor); +#endif + } + + return FALSE; +} + +static gboolean +gimp_spin_scale_leave_notify (GtkWidget *widget, + GdkEventCrossing *event) +{ + gdk_window_set_cursor (event->window, NULL); + + return GTK_WIDGET_CLASS (parent_class)->leave_notify_event (widget, event); +} + +gboolean gimp_spin_scale_keypress( GtkWidget *widget, GdkEventKey *event) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (widget); + guint key = 0; + gdk_keymap_translate_keyboard_state( gdk_keymap_get_for_display( gdk_display_get_default() ), + event->hardware_keycode, (GdkModifierType)event->state, + 0, &key, 0, 0, 0 ); + + switch ( key ) { + + case GDK_KEY_Escape: + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + { + private->transferFocus = TRUE; + gimp_spin_scale_defocus( GTK_SPIN_BUTTON(widget) ); + } + break; + + } + + return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); +} + +static void +gimp_spin_scale_defocus( GtkSpinButton *spin_button ) +{ + GimpSpinScalePrivate *private = GET_PRIVATE (spin_button); + + if ( private->transferFocus ) { + if ( private->focusWidget ) { + gtk_widget_grab_focus( private->focusWidget ); + } + } +} + +static void +gimp_spin_scale_value_changed (GtkSpinButton *spin_button) +{ + GtkAdjustment *adjustment = gtk_spin_button_get_adjustment (spin_button); + GimpSpinScalePrivate *private = GET_PRIVATE (spin_button); + gdouble lower; + gdouble upper; + gdouble value; + + gimp_spin_scale_get_limits (GIMP_SPIN_SCALE (spin_button), &lower, &upper); + + value = CLAMP (gtk_adjustment_get_value (adjustment), lower, upper); + + + gtk_entry_set_progress_fraction (GTK_ENTRY (spin_button), + pow ((value - lower) / (upper - lower), + 1.0 / private->gamma)); + + // TODO - Allow scrollwheel to change value then return focus, + // but clicks/keypress should keep focus in the control + //if ( gtk_widget_has_focus( GTK_WIDGET(spin_button) ) ) { + // gimp_spin_scale_defocus( spin_button ); + //} +} + + +/* public functions */ + +GtkWidget * +gimp_spin_scale_new (GtkAdjustment *adjustment, + const gchar *label, + gint digits) +{ + g_return_val_if_fail (GTK_IS_ADJUSTMENT (adjustment), NULL); + + return g_object_new (GIMP_TYPE_SPIN_SCALE, + "adjustment", adjustment, + "label", label, + "digits", digits, + NULL); +} + +void +gimp_spin_scale_set_scale_limits (GimpSpinScale *scale, + gdouble lower, + gdouble upper) +{ + GimpSpinScalePrivate *private; + GtkSpinButton *spin_button; + GtkAdjustment *adjustment; + + g_return_if_fail (GIMP_IS_SPIN_SCALE (scale)); + + private = GET_PRIVATE (scale); + spin_button = GTK_SPIN_BUTTON (scale); + adjustment = gtk_spin_button_get_adjustment (spin_button); + + g_return_if_fail (lower >= gtk_adjustment_get_lower (adjustment)); + g_return_if_fail (upper <= gtk_adjustment_get_upper (adjustment)); + + private->scale_limits_set = TRUE; + private->scale_lower = lower; + private->scale_upper = upper; + private->gamma = 1.0; + + gimp_spin_scale_value_changed (spin_button); +} + +void +gimp_spin_scale_set_gamma (GimpSpinScale *scale, + gdouble gamma) +{ + GimpSpinScalePrivate *private; + + g_return_if_fail (GIMP_IS_SPIN_SCALE (scale)); + + private = GET_PRIVATE (scale); + + private->gamma = gamma; + + gimp_spin_scale_value_changed (GTK_SPIN_BUTTON (scale)); +} + +gdouble +gimp_spin_scale_get_gamma (GimpSpinScale *scale) +{ + GimpSpinScalePrivate *private; + + g_return_val_if_fail (GIMP_IS_SPIN_SCALE (scale), 1.0); + + private = GET_PRIVATE (scale); + + return private->gamma; +} + +void +gimp_spin_scale_unset_scale_limits (GimpSpinScale *scale) +{ + GimpSpinScalePrivate *private; + + g_return_if_fail (GIMP_IS_SPIN_SCALE (scale)); + + private = GET_PRIVATE (scale); + + private->scale_limits_set = FALSE; + private->scale_lower = 0.0; + private->scale_upper = 0.0; + + gimp_spin_scale_value_changed (GTK_SPIN_BUTTON (scale)); +} + +gboolean +gimp_spin_scale_get_scale_limits (GimpSpinScale *scale, + gdouble *lower, + gdouble *upper) +{ + GimpSpinScalePrivate *private; + + g_return_val_if_fail (GIMP_IS_SPIN_SCALE (scale), FALSE); + + private = GET_PRIVATE (scale); + + if (lower) + *lower = private->scale_lower; + + if (upper) + *upper = private->scale_upper; + + return private->scale_limits_set; +} diff --git a/src/ui/widget/gimpspinscale.h b/src/ui/widget/gimpspinscale.h new file mode 100644 index 000000000..ad63625ac --- /dev/null +++ b/src/ui/widget/gimpspinscale.h @@ -0,0 +1,76 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * gimpspinscale.h + * Copyright (C) 2010 Michael Natterer <mitch@gimp.org> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __GIMP_SPIN_SCALE_H__ +#define __GIMP_SPIN_SCALE_H__ + +#ifndef WITH_GIMP +#include <gtk/gtk.h> +#endif + +G_BEGIN_DECLS + +#define GIMP_TYPE_SPIN_SCALE (gimp_spin_scale_get_type ()) +#define GIMP_SPIN_SCALE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_SPIN_SCALE, GimpSpinScale)) +#define GIMP_SPIN_SCALE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_SPIN_SCALE, GimpSpinScaleClass)) +#define GIMP_IS_SPIN_SCALE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_SPIN_SCALE)) +#define GIMP_IS_SPIN_SCALE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_SPIN_SCALE)) +#define GIMP_SPIN_SCALE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_SPIN_SCALE, GimpSpinScaleClass)) + + +typedef struct _GimpSpinScale GimpSpinScale; +typedef struct _GimpSpinScaleClass GimpSpinScaleClass; + +struct _GimpSpinScale +{ + GtkSpinButton parent_instance; +}; + +struct _GimpSpinScaleClass +{ + GtkSpinButtonClass parent_class; +}; + + +GType gimp_spin_scale_get_type (void) G_GNUC_CONST; + +GtkWidget * gimp_spin_scale_new (GtkAdjustment *adjustment, + const gchar *label, + gint digits); + +void gimp_spin_scale_set_scale_limits (GimpSpinScale *scale, + gdouble lower, + gdouble upper); +void gimp_spin_scale_unset_scale_limits (GimpSpinScale *scale); +gboolean gimp_spin_scale_get_scale_limits (GimpSpinScale *scale, + gdouble *lower, + gdouble *upper); + +void gimp_spin_scale_set_gamma (GimpSpinScale *scale, + gdouble gamma); +gdouble gimp_spin_scale_get_gamma (GimpSpinScale *scale); + +void gimp_spin_scale_set_focuswidget( GtkWidget *scale, GtkWidget* widget ); + +void gimp_spin_scale_set_appearance( GtkWidget *scale, const gchar *appearance); + +G_END_DECLS + +#endif /* __GIMP_SPIN_SCALE_H__ */ diff --git a/src/ui/widget/layer-selector.cpp b/src/ui/widget/layer-selector.cpp index c6622627b..fbb9c0e24 100644 --- a/src/ui/widget/layer-selector.cpp +++ b/src/ui/widget/layer-selector.cpp @@ -34,6 +34,7 @@ #include "widgets/icon.h" #include "widgets/shrink-wrap-button.h" #include "xml/node-event-vector.h" +#include "widgets/gradient-vector.h" namespace Inkscape { namespace Widgets { @@ -185,7 +186,10 @@ void LayerSelector::setDesktop(SPDesktop *desktop) { if (_desktop) { // _desktop_shutdown_connection.disconnect(); - _layer_changed_connection.disconnect(); + if (_current_layer_changed_connection) + _current_layer_changed_connection.disconnect(); + if (_layers_changed_connection) + _layers_changed_connection.disconnect(); // g_signal_handlers_disconnect_by_func(_desktop, (gpointer)&detach, this); } _desktop = desktop; @@ -195,9 +199,13 @@ void LayerSelector::setDesktop(SPDesktop *desktop) { // sigc::bind (sigc::ptr_fun (detach), this)); // g_signal_connect_after(_desktop, "shutdown", GCallback(detach), this); - _layer_changed_connection = _desktop->connectCurrentLayerChanged( - sigc::mem_fun(*this, &LayerSelector::_selectLayer) - ); + LayerManager *mgr = _desktop->layer_manager; + if ( mgr ) { + _current_layer_changed_connection = mgr->connectCurrentLayerChanged( sigc::mem_fun(*this, &LayerSelector::_selectLayer) ); + //_layerUpdatedConnection = mgr->connectLayerDetailsChanged( sigc::mem_fun(*this, &LayerSelector::_updateLayer) ); + _layers_changed_connection = mgr->connectChanged( sigc::mem_fun(*this, &LayerSelector::_layersChanged) ); + } + _selectLayer(_desktop->currentLayer()); } } @@ -230,6 +238,17 @@ private: } +void LayerSelector::_layersChanged() +{ + if (_desktop) { + /* + * This code fixes #166691 but causes issues #1066543 and #1080378. + * Comment out until solution found. + */ + //_selectLayer(_desktop->currentLayer()); + } +} + /** Selects the given layer in the dropdown selector. */ void LayerSelector::_selectLayer(SPObject *layer) { @@ -300,11 +319,13 @@ void LayerSelector::_setDesktopLayer() { Gtk::ListStore::iterator selected(_selector.get_active()); SPObject *layer=_selector.get_active()->get_value(_model_columns.object); if ( _desktop && layer ) { - _layer_changed_connection.block(); + _current_layer_changed_connection.block(); + _layers_changed_connection.block(); _desktop->layer_manager->setCurrentLayer(layer); - _layer_changed_connection.unblock(); + _current_layer_changed_connection.unblock(); + _layers_changed_connection.unblock(); _selectLayer(_desktop->currentLayer()); } @@ -565,7 +586,7 @@ void LayerSelector::_prepareLabelRenderer( gchar const *label; if ( object != root ) { label = object->label(); - if (!label) { + if (!object->label()) { label = object->defaultLabel(); label_defaulted = true; } @@ -573,7 +594,7 @@ void LayerSelector::_prepareLabelRenderer( label = _("(root)"); } - gchar *text = g_markup_printf_escaped(format, label); + gchar *text = g_markup_printf_escaped(format, gr_ellipsize_text (label, 50).c_str()); _label_renderer.property_markup() = text; g_free(text); g_free(format); @@ -585,6 +606,7 @@ void LayerSelector::_prepareLabelRenderer( _label_renderer.property_style() = ( label_defaulted ? Pango::STYLE_ITALIC : Pango::STYLE_NORMAL ); + } void LayerSelector::_lockLayer(bool lock) { diff --git a/src/ui/widget/layer-selector.h b/src/ui/widget/layer-selector.h index 6fbdc9857..ff9e4ddfc 100644 --- a/src/ui/widget/layer-selector.h +++ b/src/ui/widget/layer-selector.h @@ -68,7 +68,8 @@ private: Glib::RefPtr<Gtk::ListStore> _layer_model; // sigc::connection _desktop_shutdown_connection; - sigc::connection _layer_changed_connection; + sigc::connection _layers_changed_connection; + sigc::connection _current_layer_changed_connection; sigc::connection _selection_changed_connection; sigc::connection _visibility_toggled_connection; sigc::connection _lock_toggled_connection; @@ -76,6 +77,8 @@ private: SPObject *_layer; void _selectLayer(SPObject *layer); + void _layersChanged(); + void _setDesktopLayer(); void _buildEntry(unsigned depth, SPObject &object); diff --git a/src/ui/widget/licensor.cpp b/src/ui/widget/licensor.cpp index 7fff7d87f..8ecd36af2 100644 --- a/src/ui/widget/licensor.cpp +++ b/src/ui/widget/licensor.cpp @@ -44,7 +44,7 @@ const struct rdf_license_t _other_license = class LicenseItem : public Gtk::RadioButton { public: - LicenseItem (struct rdf_license_t const* license, EntityEntry* entity, Registry &wr); + LicenseItem (struct rdf_license_t const* license, EntityEntry* entity, Registry &wr, Gtk::RadioButtonGroup *group); protected: void on_toggled(); struct rdf_license_t const *_lic; @@ -52,13 +52,12 @@ protected: Registry &_wr; }; -LicenseItem::LicenseItem (struct rdf_license_t const* license, EntityEntry* entity, Registry &wr) +LicenseItem::LicenseItem (struct rdf_license_t const* license, EntityEntry* entity, Registry &wr, Gtk::RadioButtonGroup *group) : Gtk::RadioButton(_(license->name)), _lic(license), _eep(entity), _wr(wr) { - static Gtk::RadioButtonGroup group = get_group(); - static bool first = true; - if (first) first = false; - else set_group (group); + if (group) { + set_group (*group); + } } /// \pre it is assumed that the license URI entry is a Gtk::Entry @@ -97,18 +96,19 @@ void Licensor::init (Registry& wr) LicenseItem *i; wr.setUpdating (true); - i = manage (new LicenseItem (&_proprietary_license, _eentry, wr)); + i = manage (new LicenseItem (&_proprietary_license, _eentry, wr, NULL)); + Gtk::RadioButtonGroup group = i->get_group(); add (*i); LicenseItem *pd = i; for (struct rdf_license_t * license = rdf_licenses; license && license->name; license++) { - i = manage (new LicenseItem (license, _eentry, wr)); + i = manage (new LicenseItem (license, _eentry, wr, &group)); add(*i); } // add Other at the end before the URI field for the confused ppl. - LicenseItem *io = manage (new LicenseItem (&_other_license, _eentry, wr)); + LicenseItem *io = manage (new LicenseItem (&_other_license, _eentry, wr, &group)); add (*io); pd->set_active(); diff --git a/src/ui/widget/object-composite-settings.cpp b/src/ui/widget/object-composite-settings.cpp index 1cb384501..2789676ea 100644 --- a/src/ui/widget/object-composite-settings.cpp +++ b/src/ui/widget/object-composite-settings.cpp @@ -16,6 +16,7 @@ #include <glibmm/i18n.h> +#include "desktop.h" #include "desktop-handles.h" #include "desktop-style.h" #include "document.h" @@ -32,6 +33,7 @@ #include "ui/icon-names.h" #include "display/sp-canvas.h" #include "ui/widget/style-subject.h" +#include "ui/widget/gimpspinscale.h" namespace Inkscape { namespace UI { @@ -62,50 +64,34 @@ ObjectCompositeSettings::ObjectCompositeSettings(unsigned int verb_code, char co _blur_tag(Glib::ustring(history_prefix) + ":blur"), _opacity_tag(Glib::ustring(history_prefix) + ":opacity"), _opacity_vbox(false, 0), - _opacity_label(_("Opacity:")), - _opacity_label_unit(_("%")), -#if WITH_GTKMM_3_0 - _opacity_adjustment(Gtk::Adjustment::create(100.0, 0.0, 100.0, 1.0, 1.0, 0.0)), -#else - _opacity_adjustment(100.0, 0.0, 100.0, 1.0, 1.0, 0.0), -#endif - _opacity_hscale(_opacity_adjustment), - _opacity_spin_button(_opacity_adjustment, 0.01, 1), + _opacity_scale(_("Opacity (%)"), 100.0, 0.0, 100.0, 1.0, 1.0, 1), _fe_cb(flags), _fe_vbox(false, 0), - _fe_alignment(1, 1, 1, 1), _blocked(false) { // Filter Effects pack_start(_fe_vbox, false, false, 2); - _fe_alignment.set_padding(0, 0, 4, 0); - _fe_alignment.add(_fe_cb); - _fe_vbox.pack_start(_fe_alignment, false, false, 0); + _fe_vbox.pack_start(_fe_cb, false, false, 0); _fe_cb.signal_blend_blur_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_blendBlurValueChanged)); // Opacity pack_start(_opacity_vbox, false, false, 2); - _opacity_label.set_alignment(Gtk::ALIGN_END, Gtk::ALIGN_CENTER); - _opacity_hbox.pack_start(_opacity_label, false, false, 3); - //_opacity_vbox.pack_start(_opacity_label_box, false, false, 0); - _opacity_vbox.pack_start(_opacity_hbox, false, false, 0); - _opacity_hbox.pack_start(_opacity_hscale, true, true, 0); - _opacity_hbox.pack_start(_opacity_spin_button, false, false, 0); - _opacity_hbox.pack_start(_opacity_label_unit, false, false, 3); - _opacity_hscale.set_draw_value(false); -#if WITH_GTKMM_3_0 - _opacity_adjustment->signal_value_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_opacityValueChanged)); - _opacity_label.set_mnemonic_widget(_opacity_hscale); -#else - _opacity_adjustment.signal_value_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_opacityValueChanged)); - _opacity_label.set_mnemonic_widget(_opacity_hscale); -#endif + _opacity_vbox.pack_start(_opacity_scale); + + _opacity_scale.set_appearance("compact"); + + _opacity_scale.signal_value_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_opacityValueChanged)); + + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + _opacity_scale.set_focuswidget(GTK_WIDGET(desktop->canvas)); /* SizeGroup keeps the blur and opacity labels aligned in Fill & Stroke dlg */ +/* GtkSizeGroup *labels = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); gtk_size_group_add_widget(labels, (GtkWidget *) _opacity_label.gobj()); gtk_size_group_add_widget(labels, (GtkWidget *) _fe_cb.get_blur_label()->gobj()); +*/ show_all_children(); @@ -223,11 +209,7 @@ ObjectCompositeSettings::_opacityValueChanged() SPCSSAttr *css = sp_repr_css_attr_new (); Inkscape::CSSOStringStream os; -#if WITH_GTKMM_3_0 - os << CLAMP (_opacity_adjustment->get_value() / 100, 0.0, 1.0); -#else - os << CLAMP (_opacity_adjustment.get_value() / 100, 0.0, 1.0); -#endif + os << CLAMP (_opacity_scale.get_adjustment()->get_value() / 100, 0.0, 1.0); sp_repr_css_set_property (css, "opacity", os.str().c_str()); _subject->setCSS(css); @@ -263,18 +245,14 @@ ObjectCompositeSettings::_subjectChanged() { switch (result) { case QUERY_STYLE_NOTHING: - _opacity_hbox.set_sensitive(false); + _opacity_vbox.set_sensitive(false); // gtk_widget_set_sensitive (opa, FALSE); break; case QUERY_STYLE_SINGLE: case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently case QUERY_STYLE_MULTIPLE_SAME: - _opacity_hbox.set_sensitive(true); -#if WITH_GTKMM_3_0 - _opacity_adjustment->set_value(100 * SP_SCALE24_TO_FLOAT(query->opacity.value)); -#else - _opacity_adjustment.set_value(100 * SP_SCALE24_TO_FLOAT(query->opacity.value)); -#endif + _opacity_vbox.set_sensitive(true); + _opacity_scale.get_adjustment()->set_value(100 * SP_SCALE24_TO_FLOAT(query->opacity.value)); break; } diff --git a/src/ui/widget/object-composite-settings.h b/src/ui/widget/object-composite-settings.h index 32da626d6..d3a208525 100644 --- a/src/ui/widget/object-composite-settings.h +++ b/src/ui/widget/object-composite-settings.h @@ -45,22 +45,12 @@ private: Glib::ustring _opacity_tag; Gtk::VBox _opacity_vbox; - Gtk::HBox _opacity_hbox; - Gtk::Label _opacity_label; - Gtk::Label _opacity_label_unit; -#if WITH_GTKMM_3_0 - Glib::RefPtr<Gtk::Adjustment> _opacity_adjustment; -#else - Gtk::Adjustment _opacity_adjustment; -#endif - Gtk::HScale _opacity_hscale; - Inkscape::UI::Widget::SpinButton _opacity_spin_button; + Inkscape::UI::Widget::SpinScale _opacity_scale; StyleSubject *_subject; SimpleFilterModifier _fe_cb; Gtk::VBox _fe_vbox; - Gtk::Alignment _fe_alignment; bool _blocked; gulong _desktop_activated; diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp index 90eb6a3fd..2ab72d6c7 100644 --- a/src/ui/widget/page-sizer.cpp +++ b/src/ui/widget/page-sizer.cpp @@ -245,12 +245,14 @@ PageSizer::PageSizer(Registry & _wr) _widgetRegistry(&_wr) { // set precision of scalar entry boxes + _wr.setUpdating (true); _dimensionWidth.setDigits(5); _dimensionHeight.setDigits(5); _marginTop.setDigits(5); _marginLeft.setDigits(5); _marginRight.setDigits(5); _marginBottom.setDigits(5); + _wr.setUpdating (false); //# Set up the Paper Size combo box _paperSizeListStore = Gtk::ListStore::create(_paperSizeListColumns); @@ -315,11 +317,13 @@ PageSizer::PageSizer(Registry & _wr) // Setting default custom unit to document unit SPDesktop *dt = SP_ACTIVE_DESKTOP; SPNamedView *nv = sp_desktop_namedview(dt); + _wr.setUpdating (true); if (nv->units) { _dimensionUnits.setUnit(nv->units); } else if (nv->doc_units) { _dimensionUnits.setUnit(nv->doc_units); } + _wr.setUpdating (false); //## Set up custom size frame _customFrame.set_label(_("Custom size")); diff --git a/src/ui/widget/panel.cpp b/src/ui/widget/panel.cpp index a1ae6a36d..dcf5956bf 100644 --- a/src/ui/widget/panel.cpp +++ b/src/ui/widget/panel.cpp @@ -42,7 +42,8 @@ static const int PANEL_SETTING_SIZE = 0; static const int PANEL_SETTING_MODE = 1; static const int PANEL_SETTING_SHAPE = 2; static const int PANEL_SETTING_WRAP = 3; -static const int PANEL_SETTING_NEXTFREE = 4; +static const int PANEL_SETTING_BORDER = 4; +static const int PANEL_SETTING_NEXTFREE = 5; void Panel::prep() { @@ -93,7 +94,7 @@ void Panel::_init() Glib::ustring tmp("<"); _anchor = SP_ANCHOR_CENTER; - guint panel_size = 0, panel_mode = 0, panel_ratio = 100; + guint panel_size = 0, panel_mode = 0, panel_ratio = 100, panel_border = 0; bool panel_wrap = 0; if (!_prefs_path.empty()) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -101,6 +102,7 @@ void Panel::_init() panel_size = prefs->getIntLimited(_prefs_path + "/panel_size", 1, 0, PREVIEW_SIZE_HUGE); panel_mode = prefs->getIntLimited(_prefs_path + "/panel_mode", 1, 0, 10); panel_ratio = prefs->getIntLimited(_prefs_path + "/panel_ratio", 100, 0, 500 ); + panel_border = prefs->getIntLimited(_prefs_path + "/panel_border", BORDER_NONE, 0, 2 ); } _menu = new Gtk::Menu(); @@ -198,6 +200,42 @@ void Panel::_init() } { + Glib::ustring widthItemLabel(C_("Swatches", "Border")); + + //TRANSLATORS: Indicates border of colour swatches + const gchar *widthLabels[] = { + NC_("Swatches border", "None"), + NC_("Swatches border", "Solid"), + NC_("Swatches border", "Wide"), + }; + + Gtk::MenuItem *item = manage( new Gtk::MenuItem(widthItemLabel)); + Gtk::Menu *type_menu = manage(new Gtk::Menu()); + item->set_submenu(*type_menu); + _menu->append(*item); + + Gtk::RadioMenuItem::Group widthGroup; + + guint values[] = {0, 1, 2}; + guint hot_index = 0; + for ( guint i = 0; i < G_N_ELEMENTS(widthLabels); ++i ) { + // Assume all values are in increasing order + if ( values[i] <= panel_border ) { + hot_index = i; + } + } + for ( guint i = 0; i < G_N_ELEMENTS(widthLabels); ++i ) { + Glib::ustring _label(g_dpgettext2(NULL, "Swatches border", widthLabels[i])); + Gtk::RadioMenuItem *_item = manage(new Gtk::RadioMenuItem(widthGroup, _label)); + type_menu->append(*_item); + if ( i <= hot_index ) { + _item->set_active(true); + } + _item->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_BORDER, values[i])); + } + } + + { //TRANSLATORS: "Wrap" indicates how colour swatches are displayed Glib::ustring wrap_label(C_("Swatches","Wrap")); Gtk::CheckMenuItem *check = manage(new Gtk::CheckMenuItem(wrap_label)); @@ -259,6 +297,7 @@ void Panel::_init() _bounceCall(PANEL_SETTING_MODE, panel_mode); _bounceCall(PANEL_SETTING_SHAPE, panel_ratio); _bounceCall(PANEL_SETTING_WRAP, panel_wrap); + _bounceCall(PANEL_SETTING_BORDER, panel_border); } void Panel::setLabel(Glib::ustring const &label) @@ -323,7 +362,7 @@ void Panel::present() void Panel::restorePanelPrefs() { - guint panel_size = 0, panel_mode = 0, panel_ratio = 100; + guint panel_size = 0, panel_mode = 0, panel_ratio = 100, panel_border = 0; bool panel_wrap = 0; if (!_prefs_path.empty()) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -331,11 +370,13 @@ void Panel::restorePanelPrefs() panel_size = prefs->getIntLimited(_prefs_path + "/panel_size", 1, 0, PREVIEW_SIZE_HUGE); panel_mode = prefs->getIntLimited(_prefs_path + "/panel_mode", 1, 0, 10); panel_ratio = prefs->getIntLimited(_prefs_path + "/panel_ratio", 000, 0, 500 ); + panel_border = prefs->getIntLimited(_prefs_path + "/panel_border", BORDER_NONE, 0, 2 ); } _bounceCall(PANEL_SETTING_SIZE, panel_size); _bounceCall(PANEL_SETTING_MODE, panel_mode); _bounceCall(PANEL_SETTING_SHAPE, panel_ratio); _bounceCall(PANEL_SETTING_WRAP, panel_wrap); + _bounceCall(PANEL_SETTING_BORDER, panel_border); } sigc::signal<void, int> &Panel::signalResponse() @@ -360,30 +401,32 @@ void Panel::_bounceCall(int i, int j) if (_fillable) { ViewType curr_type = _fillable->getPreviewType(); guint curr_ratio = _fillable->getPreviewRatio(); + ::BorderStyle curr_border = _fillable->getPreviewBorder(); + switch (j) { case 0: { - _fillable->setStyle(::PREVIEW_SIZE_TINY, curr_type, curr_ratio); + _fillable->setStyle(::PREVIEW_SIZE_TINY, curr_type, curr_ratio, curr_border); } break; case 1: { - _fillable->setStyle(::PREVIEW_SIZE_SMALL, curr_type, curr_ratio); + _fillable->setStyle(::PREVIEW_SIZE_SMALL, curr_type, curr_ratio, curr_border); } break; case 2: { - _fillable->setStyle(::PREVIEW_SIZE_MEDIUM, curr_type, curr_ratio); + _fillable->setStyle(::PREVIEW_SIZE_MEDIUM, curr_type, curr_ratio, curr_border); } break; case 3: { - _fillable->setStyle(::PREVIEW_SIZE_BIG, curr_type, curr_ratio); + _fillable->setStyle(::PREVIEW_SIZE_BIG, curr_type, curr_ratio, curr_border); } break; case 4: { - _fillable->setStyle(::PREVIEW_SIZE_HUGE, curr_type, curr_ratio); + _fillable->setStyle(::PREVIEW_SIZE_HUGE, curr_type, curr_ratio, curr_border); } break; default: @@ -399,15 +442,16 @@ void Panel::_bounceCall(int i, int j) if (_fillable) { ::PreviewSize curr_size = _fillable->getPreviewSize(); guint curr_ratio = _fillable->getPreviewRatio(); + ::BorderStyle curr_border = _fillable->getPreviewBorder(); switch (j) { case 0: { - _fillable->setStyle(curr_size, VIEW_TYPE_LIST, curr_ratio); + _fillable->setStyle(curr_size, VIEW_TYPE_LIST, curr_ratio, curr_border); } break; case 1: { - _fillable->setStyle(curr_size, VIEW_TYPE_GRID, curr_ratio); + _fillable->setStyle(curr_size, VIEW_TYPE_GRID, curr_ratio, curr_border); } break; default: @@ -423,7 +467,40 @@ void Panel::_bounceCall(int i, int j) if ( _fillable ) { ViewType curr_type = _fillable->getPreviewType(); ::PreviewSize curr_size = _fillable->getPreviewSize(); - _fillable->setStyle(curr_size, curr_type, j); + ::BorderStyle curr_border = _fillable->getPreviewBorder(); + + _fillable->setStyle(curr_size, curr_type, j, curr_border); + } + break; + case PANEL_SETTING_BORDER: + if (!_prefs_path.empty()) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setInt(_prefs_path + "/panel_border", j); + } + if ( _fillable ) { + ::PreviewSize curr_size = _fillable->getPreviewSize(); + ViewType curr_type = _fillable->getPreviewType(); + guint curr_ratio = _fillable->getPreviewRatio(); + + switch (j) { + case 0: + { + _fillable->setStyle(curr_size, curr_type, curr_ratio, BORDER_NONE); + } + break; + case 1: + { + _fillable->setStyle(curr_size, curr_type, curr_ratio, BORDER_SOLID); + } + break; + case 2: + { + _fillable->setStyle(curr_size, curr_type, curr_ratio, BORDER_WIDE); + } + break; + default: + break; + } } break; case PANEL_SETTING_WRAP: @@ -483,6 +560,7 @@ void Panel::_regItem(Gtk::MenuItem* item, int group, int id) _menu->append(*item); item->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), group + PANEL_SETTING_NEXTFREE, id)); item->show(); + } void Panel::_handleAction(int /*set_id*/, int /*item_id*/) @@ -495,21 +573,21 @@ void Panel::_apply() g_warning("Apply button clicked for panel [Panel::_apply()]"); } -Gtk::Button *Panel::addResponseButton(const Glib::ustring &button_text, int response_id) +Gtk::Button *Panel::addResponseButton(const Glib::ustring &button_text, int response_id, bool pack_start) { Gtk::Button *button = new Gtk::Button(button_text); - _addResponseButton(button, response_id); + _addResponseButton(button, response_id, pack_start); return button; } -Gtk::Button *Panel::addResponseButton(const Gtk::StockID &stock_id, int response_id) +Gtk::Button *Panel::addResponseButton(const Gtk::StockID &stock_id, int response_id, bool pack_start) { Gtk::Button *button = new Gtk::Button(stock_id); - _addResponseButton(button, response_id); + _addResponseButton(button, response_id, pack_start); return button; } -void Panel::_addResponseButton(Gtk::Button *button, int response_id) +void Panel::_addResponseButton(Gtk::Button *button, int response_id, bool pack_start) { // Create a button box for the response buttons if it's the first button to be added if (!_action_area) { @@ -520,6 +598,10 @@ void Panel::_addResponseButton(Gtk::Button *button, int response_id) _action_area->pack_end(*button); + if (pack_start) { + _action_area->set_child_secondary( *button , true); + } + if (response_id != 0) { // Re-emit clicked signals as response signals button->signal_clicked().connect(sigc::bind(_signal_response.make_slot(), response_id)); diff --git a/src/ui/widget/panel.h b/src/ui/widget/panel.h index 2d92d65c9..b4cc04809 100644 --- a/src/ui/widget/panel.h +++ b/src/ui/widget/panel.h @@ -96,8 +96,8 @@ public: /* Methods providing a Gtk::Dialog like interface for adding buttons that emit Gtk::RESPONSE * signals on click. */ - Gtk::Button* addResponseButton (const Glib::ustring &button_text, int response_id); - Gtk::Button* addResponseButton (const Gtk::StockID &stock_id, int response_id); + Gtk::Button* addResponseButton (const Glib::ustring &button_text, int response_id, bool pack_start=false); + Gtk::Button* addResponseButton (const Gtk::StockID &stock_id, int response_id, bool pack_start=false); void setDefaultResponse(int response_id); void setResponseSensitive(int response_id, bool setting); @@ -119,7 +119,7 @@ protected: virtual void _handleResponse(int response_id); /* Helper methods */ - void _addResponseButton(Gtk::Button *button, int response_id); + void _addResponseButton(Gtk::Button *button, int response_id, bool pack_start=false); Inkscape::Selection *_getSelection(); /** diff --git a/src/ui/widget/preferences-widget.cpp b/src/ui/widget/preferences-widget.cpp index 07145f5f3..e7e317d11 100644 --- a/src/ui/widget/preferences-widget.cpp +++ b/src/ui/widget/preferences-widget.cpp @@ -378,12 +378,7 @@ ZoomCorrRuler::redraw() { Glib::RefPtr<Gdk::Window> window = get_window(); Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context(); -#if WITH_GTKMM_2_24 int w = window->get_width(); -#else - int w, h; - window->get_size(w, h); -#endif _drawing_width = w - _border * 2; cr->set_source_rgb(1.0, 1.0, 1.0); @@ -597,11 +592,7 @@ void PrefCombo::init(Glib::ustring const &prefs_path, for (int i = 0 ; i < num_items; ++i) { -#if WITH_GTKMM_2_24 this->append(labels[i]); -#else - this->append_text(labels[i]); -#endif _values.push_back(values[i]); if (value == values[i]) row = i; @@ -623,11 +614,7 @@ void PrefCombo::init(Glib::ustring const &prefs_path, for (int i = 0 ; i < num_items; ++i) { -#if WITH_GTKMM_2_24 this->append(labels[i]); -#else - this->append_text(labels[i]); -#endif _ustr_values.push_back(values[i]); if (value == values[i]) row = i; @@ -640,7 +627,7 @@ void PrefCombo::on_changed() if (this->get_visible()) //only take action if user changed value { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - if(_values.size() > 0) + if(!_values.empty()) { prefs->setInt(_prefs_path, _values[this->get_active_row_number()]); } diff --git a/src/ui/widget/rotateable.cpp b/src/ui/widget/rotateable.cpp index 7be666843..1d91515e5 100644 --- a/src/ui/widget/rotateable.cpp +++ b/src/ui/widget/rotateable.cpp @@ -24,12 +24,15 @@ Rotateable::Rotateable(): { dragging = false; working = false; + scrolling = false; modifier = 0; current_axis = axis; signal_button_press_event().connect(sigc::mem_fun(*this, &Rotateable::on_click)); signal_motion_notify_event().connect(sigc::mem_fun(*this, &Rotateable::on_motion)); signal_button_release_event().connect(sigc::mem_fun(*this, &Rotateable::on_release)); + signal_scroll_event().connect(sigc::mem_fun(*this, &Rotateable::on_scroll)); + } bool Rotateable::on_click(GdkEventButton *event) { @@ -124,6 +127,34 @@ bool Rotateable::on_release(GdkEventButton *event) { return false; } +bool Rotateable::on_scroll(GdkEventScroll* event) +{ + double change = 0.0; + + if (event->direction == GDK_SCROLL_UP) { + change = 1.0; + } else if (event->direction == GDK_SCROLL_DOWN) { + change = -1.0; + } else { + return FALSE; + } + + drag_started_x = event->x; + drag_started_y = event->y; + modifier = get_single_modifier(modifier, event->state); + dragging = false; + working = false; + scrolling = true; + current_axis = axis; + + do_scroll(change, modifier); + + dragging = false; + working = false; + scrolling = false; + + return TRUE; +} Rotateable::~Rotateable() { } diff --git a/src/ui/widget/rotateable.h b/src/ui/widget/rotateable.h index 15e0bf71c..52fb5306c 100644 --- a/src/ui/widget/rotateable.h +++ b/src/ui/widget/rotateable.h @@ -31,10 +31,12 @@ public: bool on_click(GdkEventButton *event); bool on_motion(GdkEventMotion *event); bool on_release(GdkEventButton *event); + bool on_scroll(GdkEventScroll* event); double axis; double current_axis; double maxdecl; + bool scrolling; private: double drag_started_x; @@ -47,6 +49,7 @@ private: virtual void do_motion (double /*by*/, guint /*state*/) {} virtual void do_release (double /*by*/, guint /*state*/) {} + virtual void do_scroll (double /*by*/, guint /*state*/) {} }; } // namespace Widget diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp index a37f36eea..41d7c8be2 100644 --- a/src/ui/widget/selected-style.cpp +++ b/src/ui/widget/selected-style.cpp @@ -23,6 +23,7 @@ #include "desktop-handles.h" #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-pattern.h" @@ -38,7 +39,6 @@ #include "sp-gradient.h" #include "svg/svg-color.h" #include "svg/css-ostringstream.h" -#include "helper/units.h" #include "event-context.h" #include "message-context.h" #include "verbs.h" @@ -47,7 +47,9 @@ #include "pixmaps/cursor-adj-h.xpm" #include "pixmaps/cursor-adj-s.xpm" #include "pixmaps/cursor-adj-l.xpm" +#include "pixmaps/cursor-adj-a.xpm" #include "sp-cursor.h" +#include "gradient-chemistry.h" static gdouble const _sw_presets[] = { 32 , 16 , 10 , 8 , 6 , 4 , 3 , 2 , 1.5 , 1 , 0.75 , 0.5 , 0.25 , 0.1 }; static gchar const *const _sw_presets_str[] = {"32", "16", "10", "8", "6", "4", "3", "2", "1.5", "1", "0.75", "0.5", "0.25", "0.1"}; @@ -143,10 +145,7 @@ SelectedStyle::SelectedStyle(bool /*layout*/) _opacity_blocked (false), - _popup_px(_sw_group), - _popup_pt(_sw_group), - _popup_mm(_sw_group), - + _unit_mis(NULL), _sw_unit(NULL) { _drop[0] = _drop[1] = 0; @@ -297,34 +296,39 @@ SelectedStyle::SelectedStyle(bool /*layout*/) } { - _popup_px.add(*(new Gtk::Label(_("px"), 0.0, 0.5))); - _popup_px.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_popup_px)); - _popup_sw.attach(_popup_px, 0,1, 0,1); - - _popup_pt.add(*(new Gtk::Label(_("pt"), 0.0, 0.5))); - _popup_pt.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_popup_pt)); - _popup_sw.attach(_popup_pt, 0,1, 1,2); - - _popup_mm.add(*(new Gtk::Label(_("mm"), 0.0, 0.5))); - _popup_mm.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_popup_mm)); - _popup_sw.attach(_popup_mm, 0,1, 2,3); + 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); + Gtk::RadioMenuItem *mi = Gtk::manage(new Gtk::RadioMenuItem(_sw_group)); + mi->add(*(new Gtk::Label(u->abbr, 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)); + _popup_sw.attach(*mi, 0,1, row, row+1); + row++; + } - _popup_sw.attach(*(new Gtk::SeparatorMenuItem()), 0,1, 3,4); + _popup_sw.attach(*(new Gtk::SeparatorMenuItem()), 0,1, row, row+1); + row++; for (guint i = 0; i < G_N_ELEMENTS(_sw_presets_str); ++i) { Gtk::MenuItem *mi = Gtk::manage(new Gtk::MenuItem()); mi->add(*(new Gtk::Label(_sw_presets_str[i], 0.0, 0.5))); mi->signal_activate().connect(sigc::bind<int>(sigc::mem_fun(*this, &SelectedStyle::on_popup_preset), i)); - _popup_sw.attach(*mi, 0,1, 4+i, 5+i); + _popup_sw.attach(*mi, 0,1, row, row+1); + row++; } - guint i = G_N_ELEMENTS(_sw_presets_str) + 5; - - _popup_sw.attach(*(new Gtk::SeparatorMenuItem()), 0,1, i,i+1); + _popup_sw.attach(*(new Gtk::SeparatorMenuItem()), 0,1, row, row+1); + row++; _popup_sw_remove.add(*(new Gtk::Label(_("Remove"), 0.0, 0.5))); _popup_sw_remove.signal_activate().connect(sigc::mem_fun(*this, &SelectedStyle::on_stroke_remove)); - _popup_sw.attach(_popup_sw_remove, 0,1, i+1,i+2); + _popup_sw.attach(_popup_sw_remove, 0,1, row, row+1); + row++; + + sp_set_font_size_smaller (GTK_WIDGET(_popup_sw.gobj())); _popup_sw.show_all(); } @@ -335,6 +339,7 @@ SelectedStyle::SelectedStyle(bool /*layout*/) _stroke_width_place.signal_button_press_event().connect(sigc::mem_fun(*this, &SelectedStyle::on_sw_click)); _stroke_width_place.signal_button_release_event().connect(sigc::mem_fun(*this, &SelectedStyle::on_sw_click)); + _opacity_sb.signal_populate_popup().connect(sigc::mem_fun(*this, &SelectedStyle::on_opacity_menu)); _opacity_sb.signal_value_changed().connect(sigc::mem_fun(*this, &SelectedStyle::on_opacity_changed)); // Connect to key-press to ensure focus is consistent with other spin buttons when using the keys vs mouse-click @@ -446,7 +451,17 @@ SelectedStyle::setDesktop(SPDesktop *desktop) this ) )); - //_sw_unit = (SPUnit *) sp_desktop_namedview(desktop)->doc_units; + _sw_unit = const_cast<SPUnit*>(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)) { + mi->set_active(); + break; + } + } } void SelectedStyle::dragDataReceived( GtkWidget */*widget*/, @@ -598,6 +613,12 @@ void SelectedStyle::on_fill_invert() { SPCSSAttr *css = sp_repr_css_attr_new (); guint32 color = _thisselected[SS_FILL]; gchar c[64]; + if (_mode[SS_FILL] == SS_LGRADIENT || _mode[SS_FILL] == SS_RGRADIENT) { + sp_gradient_invert_selected_gradients(_desktop, Inkscape::FOR_FILL); + return; + + } + if (_mode[SS_FILL] != SS_COLOR) return; sp_svg_write_color (c, sizeof(c), SP_RGBA32_U_COMPOSE( @@ -618,6 +639,10 @@ void SelectedStyle::on_stroke_invert() { SPCSSAttr *css = sp_repr_css_attr_new (); guint32 color = _thisselected[SS_STROKE]; gchar c[64]; + if (_mode[SS_STROKE] == SS_LGRADIENT || _mode[SS_STROKE] == SS_RGRADIENT) { + sp_gradient_invert_selected_gradients(_desktop, Inkscape::FOR_STROKE); + return; + } if (_mode[SS_STROKE] != SS_COLOR) return; sp_svg_write_color (c, sizeof(c), SP_RGBA32_U_COMPOSE( @@ -876,16 +901,8 @@ SelectedStyle::on_opacity_click(GdkEventButton *event) return false; } -void SelectedStyle::on_popup_px() { - _sw_unit = (SPUnit *) &(sp_unit_get_by_id(SP_UNIT_PX)); - update(); -} -void SelectedStyle::on_popup_pt() { - _sw_unit = (SPUnit *) &(sp_unit_get_by_id(SP_UNIT_PT)); - update(); -} -void SelectedStyle::on_popup_mm() { - _sw_unit = (SPUnit *) &(sp_unit_get_by_id(SP_UNIT_MM)); +void SelectedStyle::on_popup_units(SPUnitId id) { + _sw_unit = (SPUnit *) &(sp_unit_get_by_id(id)); update(); } @@ -971,13 +988,13 @@ SelectedStyle::update() if (SP_IS_LINEARGRADIENT (server)) { SPGradient *vector = SP_GRADIENT(server)->getVector(); - sp_gradient_image_set_gradient ((SPGradientImage *) _gradient_preview_l[i], vector); + sp_gradient_image_set_gradient(SP_GRADIENT_IMAGE(_gradient_preview_l[i]), vector); place->add(_gradient_box_l[i]); place->set_tooltip_text(__lgradient[i]); _mode[i] = SS_LGRADIENT; } else if (SP_IS_RADIALGRADIENT (server)) { SPGradient *vector = SP_GRADIENT(server)->getVector(); - sp_gradient_image_set_gradient ((SPGradientImage *) _gradient_preview_r[i], vector); + sp_gradient_image_set_gradient(SP_GRADIENT_IMAGE(_gradient_preview_r[i]), vector); place->add(_gradient_box_r[i]); place->set_tooltip_text(__rgradient[i]); _mode[i] = SS_RGRADIENT; @@ -993,7 +1010,7 @@ SelectedStyle::update() guint32 color = paint->value.color.toRGBA32( SP_SCALE24_TO_FLOAT ((i == SS_FILL)? query->fill_opacity.value : query->stroke_opacity.value)); _lastselected[i] = _thisselected[i]; - _thisselected[i] = color | 0xff; // only color, opacity === 1 + _thisselected[i] = color; // include opacity ((Inkscape::UI::Widget::ColorPreview*)_color_preview[i])->setRgba32 (color); _color_preview[i]->show_all(); place->add(*_color_preview[i]); @@ -1196,39 +1213,43 @@ RotateableSwatch::~RotateableSwatch() { } double -RotateableSwatch::color_adjust(float *hsl, double by, guint32 cc, guint modifier) +RotateableSwatch::color_adjust(float *hsla, double by, guint32 cc, guint modifier) { - sp_color_rgb_to_hsl_floatv (hsl, SP_RGBA32_R_F(cc), SP_RGBA32_G_F(cc), SP_RGBA32_B_F(cc)); - + sp_color_rgb_to_hsl_floatv (hsla, SP_RGBA32_R_F(cc), SP_RGBA32_G_F(cc), SP_RGBA32_B_F(cc)); + hsla[3] = SP_RGBA32_A_F(cc); double diff = 0; if (modifier == 2) { // saturation - double old = hsl[1]; + double old = hsla[1]; if (by > 0) { - hsl[1] += by * (1 - hsl[1]); + hsla[1] += by * (1 - hsla[1]); } else { - hsl[1] += by * (hsl[1]); + hsla[1] += by * (hsla[1]); } - diff = hsl[1] - old; + diff = hsla[1] - old; } else if (modifier == 1) { // lightness - double old = hsl[2]; + double old = hsla[2]; if (by > 0) { - hsl[2] += by * (1 - hsl[2]); + hsla[2] += by * (1 - hsla[2]); } else { - hsl[2] += by * (hsl[2]); + hsla[2] += by * (hsla[2]); } - diff = hsl[2] - old; + diff = hsla[2] - old; + } else if (modifier == 3) { // alpha + double old = hsla[3]; + hsla[3] += by/2; + diff = hsla[3] - old; } else { // hue - double old = hsl[0]; - hsl[0] += by/2; - while (hsl[0] < 0) - hsl[0] += 1; - while (hsl[0] > 1) - hsl[0] -= 1; - diff = hsl[0] - old; + double old = hsla[0]; + hsla[0] += by/2; + while (hsla[0] < 0) + hsla[0] += 1; + while (hsla[0] > 1) + hsla[0] -= 1; + diff = hsla[0] - old; } float rgb[3]; - sp_color_hsl_to_rgb_floatv (rgb, hsl[0], hsl[1], hsl[2]); + sp_color_hsl_to_rgb_floatv (rgb, hsla[0], hsla[1], hsla[2]); gchar c[64]; sp_svg_write_color (c, sizeof(c), @@ -1241,10 +1262,14 @@ RotateableSwatch::color_adjust(float *hsl, double by, guint32 cc, guint modifier ); SPCSSAttr *css = sp_repr_css_attr_new (); - if (fillstroke == SS_FILL) - sp_repr_css_set_property (css, "fill", c); - else - sp_repr_css_set_property (css, "stroke", c); + + if (modifier == 3) { // alpha + Inkscape::CSSOStringStream osalpha; + osalpha << hsla[3]; + sp_repr_css_set_property(css, (fillstroke == SS_FILL) ? "fill-opacity" : "stroke-opacity", osalpha.str().c_str()); + } else { + sp_repr_css_set_property (css, (fillstroke == SS_FILL) ? "fill" : "stroke", c); + } sp_desktop_set_style (parent->getDesktop(), css); sp_repr_css_attr_unref (css); return diff; @@ -1255,7 +1280,7 @@ RotateableSwatch::do_motion(double by, guint modifier) { if (parent->_mode[fillstroke] != SS_COLOR) return; - if (!cr_set && modifier != 3) { + if (!scrolling && !cr_set) { GtkWidget *w = GTK_WIDGET(gobj()); GdkPixbuf *pixbuf = NULL; @@ -1263,6 +1288,8 @@ RotateableSwatch::do_motion(double by, guint modifier) { pixbuf = gdk_pixbuf_new_from_xpm_data((const gchar **)cursor_adj_s_xpm); } else if (modifier == 1) { // lightness pixbuf = gdk_pixbuf_new_from_xpm_data((const gchar **)cursor_adj_l_xpm); + } else if (modifier == 3) { // alpha + pixbuf = gdk_pixbuf_new_from_xpm_data((const gchar **)cursor_adj_a_xpm); } else { // hue pixbuf = gdk_pixbuf_new_from_xpm_data((const gchar **)cursor_adj_h_xpm); } @@ -1290,43 +1317,51 @@ RotateableSwatch::do_motion(double by, guint modifier) { cc = startcolor; } - float hsl[3]; + float hsla[4]; double diff = 0; - if (modifier != 3) { - diff = color_adjust(hsl, by, cc, modifier); - } - if (modifier == 3) { // Alt, do nothing + diff = color_adjust(hsla, by, cc, modifier); + + if (modifier == 3) { // alpha + 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); } else if (modifier == 2) { // saturation DocumentUndo::maybeDone(sp_desktop_document(parent->getDesktop()), undokey, SP_VERB_DIALOG_FILL_STROKE, (_("Adjust saturation"))); - double ch = hsl[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, without modifiers to adjust hue"), ch - diff, ch, diff); + 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); } else if (modifier == 1) { // lightness DocumentUndo::maybeDone(sp_desktop_document(parent->getDesktop()), undokey, SP_VERB_DIALOG_FILL_STROKE, (_("Adjust lightness"))); - double ch = hsl[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, without modifiers to adjust hue"), ch - diff, ch, diff); + 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); } else { // hue DocumentUndo::maybeDone(sp_desktop_document(parent->getDesktop()), undokey, SP_VERB_DIALOG_FILL_STROKE, (_("Adjust hue"))); - double ch = hsl[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>Ctrl</b> to adjust lightness"), ch - diff, ch, diff); + 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); } } + +void +RotateableSwatch::do_scroll(double by, guint modifier) { + do_motion(by/30.0, modifier); + do_release(by/30.0, modifier); +} + void RotateableSwatch::do_release(double by, guint modifier) { if (parent->_mode[fillstroke] != SS_COLOR) return; - float hsl[3]; - if (modifier != 3) { - color_adjust(hsl, by, startcolor, modifier); - } + float hsla[4]; + color_adjust(hsla, by, startcolor, modifier); if (cr_set) { GtkWidget *w = GTK_WIDGET(gobj()); @@ -1342,7 +1377,9 @@ RotateableSwatch::do_release(double by, guint modifier) { cr_set = false; } - if (modifier == 3) { // Alt, do nothing + if (modifier == 3) { // alpha + DocumentUndo::maybeDone(sp_desktop_document(parent->getDesktop()), undokey, + SP_VERB_DIALOG_FILL_STROKE, ("Adjust alpha")); } else if (modifier == 2) { // saturation DocumentUndo::maybeDone(sp_desktop_document(parent->getDesktop()), undokey, SP_VERB_DIALOG_FILL_STROKE, ("Adjust saturation")); @@ -1452,6 +1489,11 @@ RotateableStrokeWidth::do_release(double by, guint modifier) { parent->getDesktop()->event_context->_message_context->clear(); } +void +RotateableStrokeWidth::do_scroll(double by, guint modifier) { + do_motion(by/10.0, modifier); + startvalue_set = false; +} Dialog::FillAndStroke *get_fill_and_stroke_panel(SPDesktop *desktop) { diff --git a/src/ui/widget/selected-style.h b/src/ui/widget/selected-style.h index 542983b53..fac4f22e6 100644 --- a/src/ui/widget/selected-style.h +++ b/src/ui/widget/selected-style.h @@ -27,6 +27,7 @@ #include <sigc++/sigc++.h> #include "rotateable.h" +#include "helper/units.h" class SPDesktop; class SPUnit; @@ -60,8 +61,10 @@ public: ~RotateableSwatch(); double color_adjust (float *hsl, double by, guint32 cc, guint state); + virtual void do_motion (double by, guint state); virtual void do_release (double by, guint state); + virtual void do_scroll (double by, guint state); private: guint fillstroke; @@ -86,6 +89,7 @@ public: double value_adjust(double current, double by, guint modifier, bool final); virtual void do_motion (double by, guint state); virtual void do_release (double by, guint state); + virtual void do_scroll (double by, guint state); private: SelectedStyle *parent; @@ -250,12 +254,8 @@ protected: Gtk::Menu _popup_sw; Gtk::RadioButtonGroup _sw_group; - Gtk::RadioMenuItem _popup_px; - void on_popup_px(); - Gtk::RadioMenuItem _popup_pt; - void on_popup_pt(); - Gtk::RadioMenuItem _popup_mm; - void on_popup_mm(); + GSList *_unit_mis; + void on_popup_units(SPUnitId id); void on_popup_preset(int i); Gtk::MenuItem _popup_sw_remove; diff --git a/src/ui/widget/spin-scale.cpp b/src/ui/widget/spin-scale.cpp new file mode 100644 index 000000000..00c575568 --- /dev/null +++ b/src/ui/widget/spin-scale.cpp @@ -0,0 +1,248 @@ +/* + * Author: + * + * Copyright (C) 2012 Author + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#include <glib.h> +#include <glibmm/i18n.h> +#include <glibmm/stringutils.h> +#include <gtkmm/adjustment.h> + +#include "spin-scale.h" +#include "ui/widget/gimpspinscale.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +SpinScale::SpinScale(const char* label, double value, double lower, double upper, double step_inc, + double climb_rate, int digits, const SPAttributeEnum a, const char* tip_text) + : AttrWidget(a, value) +{ + +#if WITH_GTKMM_3_0 + _adjustment = Gtk::Adjustment::create(value, lower, upper, step_inc); + _spinscale = gimp_spin_scale_new (_adjustment->gobj(), label, digits); +#else + _adjustment = new Gtk::Adjustment(value, lower, upper, step_inc); + _spinscale = gimp_spin_scale_new (_adjustment->gobj(), label, digits); +#endif + + signal_value_changed().connect(signal_attr_changed().make_slot()); + + pack_start(*Gtk::manage(Glib::wrap(_spinscale))); + + if (tip_text){ + gtk_widget_set_tooltip_text( _spinscale, tip_text ); + } + + show_all_children(); +} + +SpinScale::SpinScale(const char* label, +#if WITH_GTKMM_3_0 + Glib::RefPtr<Gtk::Adjustment> adj, +#else + Gtk::Adjustment *adj, +#endif + int digits, const SPAttributeEnum a, const char* tip_text) + : AttrWidget(a, 0.0), + _adjustment(adj) + +{ + + _spinscale = gimp_spin_scale_new (_adjustment->gobj(), label, digits); + + signal_value_changed().connect(signal_attr_changed().make_slot()); + + pack_start(*Gtk::manage(Glib::wrap(_spinscale))); + + if (tip_text){ + gtk_widget_set_tooltip_text( _spinscale, tip_text ); + } + + show_all_children(); +} + +Glib::ustring SpinScale::get_as_attribute() const +{ + const double val = _adjustment->get_value(); + + //if(_spin.get_digits() == 0) + // return Glib::Ascii::dtostr((int)val); + //else + return Glib::Ascii::dtostr(val); +} + +void SpinScale::set_from_attribute(SPObject* o) +{ + const gchar* val = attribute_value(o); + if(val) + _adjustment->set_value(Glib::Ascii::strtod(val)); + else + _adjustment->set_value(get_default()->as_double()); +} + +Glib::SignalProxy0<void> SpinScale::signal_value_changed() +{ + return _adjustment->signal_value_changed(); +} + +double SpinScale::get_value() const +{ + return _adjustment->get_value(); +} + +void SpinScale::set_value(const double val) +{ + _adjustment->set_value(val); +} + +void SpinScale::set_focuswidget(GtkWidget *widget) +{ + gimp_spin_scale_set_focuswidget(_spinscale, widget); +} + + +void SpinScale::set_appearance(const gchar* appearance) +{ + gimp_spin_scale_set_appearance(_spinscale, appearance); +} + +#if WITH_GTKMM_3_0 +const Glib::RefPtr<Gtk::Adjustment> SpinScale::get_adjustment() const +#else +const Gtk::Adjustment *SpinScale::get_adjustment() const +#endif +{ + return _adjustment; +} +#if WITH_GTKMM_3_0 +Glib::RefPtr<Gtk::Adjustment> SpinScale::get_adjustment() +#else +Gtk::Adjustment *SpinScale::get_adjustment() +#endif +{ + return _adjustment; +} + + +DualSpinScale::DualSpinScale(const char* label1, const char* label2, double value, double lower, double upper, double step_inc, + double climb_rate, int digits, const SPAttributeEnum a, char* tip_text1, char* tip_text2) + : AttrWidget(a), + _s1(label1, value, lower, upper, step_inc, climb_rate, digits, SP_ATTR_INVALID, tip_text1), + _s2(label2, value, lower, upper, step_inc, climb_rate, digits, SP_ATTR_INVALID, tip_text2), + //TRANSLATORS: "Link" means to _link_ two sliders together + _link(C_("Sliders", "Link")) +{ + signal_value_changed().connect(signal_attr_changed().make_slot()); + + _s1.get_adjustment()->signal_value_changed().connect(_signal_value_changed.make_slot()); + _s2.get_adjustment()->signal_value_changed().connect(_signal_value_changed.make_slot()); + _s1.get_adjustment()->signal_value_changed().connect(sigc::mem_fun(*this, &DualSpinScale::update_linked)); + + _link.signal_toggled().connect(sigc::mem_fun(*this, &DualSpinScale::link_toggled)); + + Gtk::VBox* vb = Gtk::manage(new Gtk::VBox); + vb->add(_s1); + vb->add(_s2); + pack_start(*vb); + pack_start(_link, false, false); + _link.set_active(true); + + show_all(); +} + +Glib::ustring DualSpinScale::get_as_attribute() const +{ + if(_link.get_active()) + return _s1.get_as_attribute(); + else + return _s1.get_as_attribute() + " " + _s2.get_as_attribute(); +} + +void DualSpinScale::set_from_attribute(SPObject* o) +{ + const gchar* val = attribute_value(o); + if(val) { + // Split val into parts + gchar** toks = g_strsplit(val, " ", 2); + + if(toks) { + double v1 = 0.0, v2 = 0.0; + if(toks[0]) + v1 = v2 = Glib::Ascii::strtod(toks[0]); + if(toks[1]) + v2 = Glib::Ascii::strtod(toks[1]); + + _link.set_active(toks[1] == 0); + + _s1.get_adjustment()->set_value(v1); + _s2.get_adjustment()->set_value(v2); + + g_strfreev(toks); + } + } +} + +sigc::signal<void>& DualSpinScale::signal_value_changed() +{ + return _signal_value_changed; +} + +const SpinScale& DualSpinScale::get_SpinScale1() const +{ + return _s1; +} + +SpinScale& DualSpinScale::get_SpinScale1() +{ + return _s1; +} + +const SpinScale& DualSpinScale::get_SpinScale2() const +{ + return _s2; +} + +SpinScale& DualSpinScale::get_SpinScale2() +{ + return _s2; +} + +/*void DualSpinScale::remove_scale() +{ + _s1.remove_scale(); + _s2.remove_scale(); +}*/ + +void DualSpinScale::link_toggled() +{ + _s2.set_sensitive(!_link.get_active()); + update_linked(); +} + +void DualSpinScale::update_linked() +{ + if(_link.get_active()) + _s2.set_value(_s1.get_value()); +} + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/spin-scale.h b/src/ui/widget/spin-scale.h new file mode 100644 index 000000000..a8403307f --- /dev/null +++ b/src/ui/widget/spin-scale.h @@ -0,0 +1,117 @@ +/* + * Author: + * + * Copyright (C) 2012 Author + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_SPIN_SCALE_H +#define INKSCAPE_UI_WIDGET_SPIN_SCALE_H + +#include <gtkmm/adjustment.h> +#include <gtkmm/box.h> +#include <gtkmm/scale.h> +#include <gtkmm/togglebutton.h> +#include "spinbutton.h" +#include "attr-widget.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +/** + * Wrap the gimpspinscale class + * A combo widget with label, scale slider, spinbutton and adjustment + */ +class SpinScale : public Gtk::HBox, public AttrWidget +{ + +public: + SpinScale(const char* label, double value, double lower, double upper, double step_inc, double climb_rate, + int digits, const SPAttributeEnum a = SP_ATTR_INVALID, const char* tip_text = NULL); + + SpinScale(const char* label, +#if WITH_GTKMM_3_0 + Glib::RefPtr<Gtk::Adjustment> adj, +#else + Gtk::Adjustment *adj, +#endif + int digits, const SPAttributeEnum a = SP_ATTR_INVALID, const char* tip_text = NULL); + + virtual Glib::ustring get_as_attribute() const; + virtual void set_from_attribute(SPObject*); + + // Shortcuts to _adjustment + Glib::SignalProxy0<void> signal_value_changed(); + double get_value() const; + void set_value(const double); + void set_focuswidget(GtkWidget *widget); + void set_appearance(const gchar* appearance); + +#if WITH_GTKMM_3_0 + const Glib::RefPtr<Gtk::Adjustment> get_adjustment() const; + Glib::RefPtr<Gtk::Adjustment> get_adjustment(); +#else + const Gtk::Adjustment *get_adjustment() const; + Gtk::Adjustment *get_adjustment(); +#endif + +private: +#if WITH_GTKMM_3_0 + Glib::RefPtr<Gtk::Adjustment> _adjustment; +#else + Gtk::Adjustment *_adjustment; +#endif + + GtkWidget *_spinscale; +}; + + +/** + * Contains two SpinScales for controlling number-opt-number attributes. + * + * @see SpinScale + */ +class DualSpinScale : public Gtk::HBox, public AttrWidget +{ +public: + DualSpinScale(const char* label1, const char* label2, double value, double lower, double upper, double step_inc, + double climb_rate, int digits, const SPAttributeEnum, char* tip_text1, char* tip_text2); + + virtual Glib::ustring get_as_attribute() const; + virtual void set_from_attribute(SPObject*); + + sigc::signal<void>& signal_value_changed(); + + const SpinScale& get_SpinScale1() const; + SpinScale& get_SpinScale1(); + + const SpinScale& get_SpinScale2() const; + SpinScale& get_SpinScale2(); + + //void remove_scale(); +private: + void link_toggled(); + void update_linked(); + sigc::signal<void> _signal_value_changed; + SpinScale _s1, _s2; + Gtk::ToggleButton _link; +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIDGET_SPIN_SCALE_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/widget/spin-slider.cpp b/src/ui/widget/spin-slider.cpp index 97ae18e20..323b1209c 100644 --- a/src/ui/widget/spin-slider.cpp +++ b/src/ui/widget/spin-slider.cpp @@ -186,7 +186,7 @@ void DualSpinSlider::set_from_attribute(SPObject* o) gchar** toks = g_strsplit(val, " ", 2); if(toks) { - double v1, v2; + double v1 = 0.0, v2 = 0.0; if(toks[0]) v1 = v2 = Glib::Ascii::strtod(toks[0]); if(toks[1]) diff --git a/src/ui/widget/style-swatch.cpp b/src/ui/widget/style-swatch.cpp index 857ae7019..60d5f6ecc 100644 --- a/src/ui/widget/style-swatch.cpp +++ b/src/ui/widget/style-swatch.cpp @@ -340,15 +340,12 @@ void StyleSwatch::setStyle(SPStyle *query) if (op != 1) { { gchar *str; - if (op == 0) - str = g_strdup_printf(_("O:%.3g"), op); - else - str = g_strdup_printf(_("O:.%d"), (int) (op*10)); + str = g_strdup_printf(_("O: %2.0f"), (op*100.0)); _opacity_value.set_markup (str); g_free (str); } { - gchar *str = g_strdup_printf(_("Opacity: %.3g"), op); + gchar *str = g_strdup_printf(_("Opacity: %2.1f %%"), (op*100.0)); _opacity_place.set_tooltip_text(str); g_free (str); } diff --git a/src/ui/widget/unit-menu.cpp b/src/ui/widget/unit-menu.cpp index 86e8c9e58..18b7bcab9 100644 --- a/src/ui/widget/unit-menu.cpp +++ b/src/ui/widget/unit-menu.cpp @@ -34,11 +34,7 @@ bool UnitMenu::setUnitType(UnitType unit_type) UnitTable::UnitMap::iterator iter = m.begin(); while(iter != m.end()) { Glib::ustring text = (*iter).first; -#if WITH_GTKMM_2_24 append(text); -#else - append_text(text); -#endif ++iter; } _type = unit_type; @@ -49,11 +45,7 @@ bool UnitMenu::setUnitType(UnitType unit_type) bool UnitMenu::resetUnitType(UnitType unit_type) { -#if WITH_GTKMM_2_24 - remove_all(); -#else - clear_items(); -#endif + remove_all(); return setUnitType(unit_type); } @@ -61,11 +53,7 @@ bool UnitMenu::resetUnitType(UnitType unit_type) void UnitMenu::addUnit(Unit const& u) { _unit_table.addUnit(u, false); -#if WITH_GTKMM_2_24 append(u.abbr); -#else - append_text(u.abbr); -#endif } Unit UnitMenu::getUnit() const |
