From 26b7e9efd3bdb5fa4079ecaab68de24cd6407965 Mon Sep 17 00:00:00 2001 From: gustav_b Date: Sat, 2 Jun 2007 12:45:58 +0000 Subject: [PATCH] Gtkmm:ified Fill and Stroke dialog (disabled by default). It's still using the old fill/stroke style and paint style widgets, though. --- src/ui/dialog/fill-and-stroke.cpp | 274 ++++++++++++++++++++++++++++-- src/ui/dialog/fill-and-stroke.h | 38 ++++- src/ui/widget/notebook-page.cpp | 4 +- src/ui/widget/notebook-page.h | 2 +- src/verbs.cpp | 1 + 5 files changed, 303 insertions(+), 16 deletions(-) diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index ae48fc1ab..6206c4345 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -1,10 +1,12 @@ /** - * \brief Fill and Stroke dialog + * \brief Fill and Stroke dialog, + * based on sp_object_properties_dialog * * Authors: * Bryce W. Harrington + * Gustav Broberg * - * Copyright (C) 2004, 2005 Authors + * Copyright (C) 2004--2007 Authors * * Released under GNU GPL. Read the file 'COPYING' for more information. */ @@ -13,31 +15,104 @@ # include #endif +#include "desktop-handles.h" +#include "desktop-style.h" +#include "document.h" #include "fill-and-stroke.h" +#include "filter-chemistry.h" +#include "inkscape.h" +#include "inkscape-stock.h" +#include "selection.h" +#include "style.h" +#include "svg/css-ostringstream.h" #include "verbs.h" +#include "xml/repr.h" +#include "widgets/icon.h" + +#include "dialogs/fill-style.h" +#include "dialogs/stroke-style.h" + +#include namespace Inkscape { namespace UI { namespace Dialog { +void on_selection_changed(Inkscape::Application *inkscape, + Inkscape::Selection *selection, + FillAndStroke *dlg) +{ + dlg->selectionChanged(inkscape, selection); +} + +void on_selection_modified(Inkscape::Application *inkscape, + Inkscape::Selection *selection, + guint flags, + FillAndStroke *dlg) +{ + dlg->selectionChanged(inkscape, selection); +} + + FillAndStroke::FillAndStroke() : Dialog ("dialogs.fillstroke", SP_VERB_DIALOG_FILL_STROKE), - _page_fill(1, 1), - _page_stroke_paint(1, 1), - _page_stroke_style(1, 1) + _page_fill(1, 1, true, true), + _page_stroke_paint(1, 1, true, true), + _page_stroke_style(1, 1, true, true), + _blur_vbox(false, 0), + _blur_label_box(false, 0), + _blur_label(_("_Blur, %"), 0.0, 1.0, true), + _blur_adjustment(0.0, 0.0, 100.0, 1.0, 1.0, 0.0), + _blur_hscale(_blur_adjustment), + _blur_spin_button(_blur_adjustment, 0.01, 1), + _opacity_vbox(false, 0), + _opacity_label_box(false, 0), + _opacity_label(_("Master _opacity, %"), 0.0, 1.0, true), + _opacity_adjustment(100.0, 0.0, 100.0, 1.0, 1.0, 0.0), + _opacity_hscale(_opacity_adjustment), + _opacity_spin_button(_opacity_adjustment, 0.01, 1), + _blocked(false) { - // Top level vbox Gtk::VBox *vbox = get_vbox(); - vbox->set_spacing(4); + vbox->set_spacing(0); - // Notebook for individual transformations vbox->pack_start(_notebook, true, true); - _notebook.append_page(_page_fill, _("Fill")); - _notebook.append_page(_page_stroke_paint, _("Stroke Paint")); - _notebook.append_page(_page_stroke_style, _("Stroke Style")); + _notebook.append_page(_page_fill, _createPageTabLabel(_("Fill"), INKSCAPE_STOCK_PROPERTIES_FILL_PAGE)); + _notebook.append_page(_page_stroke_paint, _createPageTabLabel(_("Stroke _paint"), INKSCAPE_STOCK_PROPERTIES_STROKE_PAINT_PAGE)); + _notebook.append_page(_page_stroke_style, _createPageTabLabel(_("Stroke st_yle"), INKSCAPE_STOCK_PROPERTIES_STROKE_PAGE)); + + _layoutPageFill(); + _layoutPageStrokePaint(); + _layoutPageStrokeStyle(); + + // Blur + vbox->pack_start(_blur_vbox, false, false, 2); + _blur_label_box.pack_start(_blur_label, false, false, 4); + _blur_vbox.pack_start(_blur_label_box, false, false, 0); + _blur_vbox.pack_start(_blur_hbox, false, false, 0); + _blur_hbox.pack_start(_blur_hscale, true, true, 4); + _blur_hbox.pack_start(_blur_spin_button, false, false, 0); + _blur_hscale.set_draw_value(false); + _blur_adjustment.signal_value_changed().connect(sigc::mem_fun(*this, &Inkscape::UI::Dialog::FillAndStroke::_blurValueChanged)); + + // Opacity + vbox->pack_start(_opacity_vbox, false, false, 2); + _opacity_label_box.pack_start(_opacity_label, false, false, 4); + _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, 4); + _opacity_hbox.pack_start(_opacity_spin_button, false, false, 0); + _opacity_hscale.set_draw_value(false); + _opacity_adjustment.signal_value_changed().connect(sigc::mem_fun(*this, &Inkscape::UI::Dialog::FillAndStroke::_opacityValueChanged)); - // TODO: Insert widgets + // these callbacks are only for the blur and master opacity update; the tabs above take care of themselves + g_signal_connect ( G_OBJECT (INKSCAPE), "change_selection", G_CALLBACK (on_selection_changed), this ); + g_signal_connect ( G_OBJECT (INKSCAPE), "change_subselection", G_CALLBACK (on_selection_changed), this ); + g_signal_connect ( G_OBJECT (INKSCAPE), "modify_selection", G_CALLBACK (on_selection_modified), this ); + g_signal_connect ( G_OBJECT (INKSCAPE), "activate_desktop", G_CALLBACK (on_selection_changed), this ); + + selectionChanged(INKSCAPE, sp_desktop_selection(SP_ACTIVE_DESKTOP)); show_all_children(); } @@ -46,6 +121,181 @@ FillAndStroke::~FillAndStroke() { } +void +FillAndStroke::_layoutPageFill() +{ + Gtk::Widget *fs = manage(Glib::wrap(sp_fill_style_widget_new())); + _page_fill.table().attach(*fs, 0, 1, 0, 1); +} + +void +FillAndStroke::_layoutPageStrokePaint() +{ + Gtk::Widget *ssp = manage(Glib::wrap(sp_stroke_style_paint_widget_new())); + _page_stroke_paint.table().attach(*ssp, 0, 1, 0, 1); +} + +void +FillAndStroke::_layoutPageStrokeStyle() +{ + Gtk::Widget *ssl = manage(Glib::wrap(sp_stroke_style_line_widget_new())); + _page_stroke_style.table().attach(*ssl, 0, 1, 0, 1); +} + +void +FillAndStroke::_blurValueChanged() +{ + if (_blocked) + return; + _blocked = true; + + //get desktop + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (!desktop) { + return; + } + + // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed; here it results in crash 1580903 + sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(desktop), 0); + + //get current selection + Inkscape::Selection *selection = sp_desktop_selection (desktop); + + NR::Maybe bbox = selection->bounds(); + if (!bbox) { + return; + } + //get list of selected items + GSList const *items = selection->itemList(); + //get current document + SPDocument *document = sp_desktop_document (desktop); + + double perimeter = bbox->extent(NR::X) + bbox->extent(NR::Y); + double radius = _blur_adjustment.get_value() * perimeter / 400; + + //apply created filter to every selected item + for (GSList const *i = items; i != NULL; i = i->next) { + + SPItem * item = SP_ITEM(i->data); + SPStyle *style = SP_OBJECT_STYLE(item); + g_assert(style != NULL); + + if (radius == 0.0) { + remove_filter (item, false); + } else { + SPFilter *constructed = new_filter_gaussian_blur_from_item(document, item, radius); + sp_style_set_property_url (SP_OBJECT(item), "filter", SP_OBJECT(constructed), false); + } + //request update + SP_OBJECT(item)->requestDisplayUpdate(( SP_OBJECT_MODIFIED_FLAG | + SP_OBJECT_STYLE_MODIFIED_FLAG )); + } + + sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "fillstroke:blur", SP_VERB_DIALOG_FILL_STROKE, _("Change blur")); + + // resume interruptibility + sp_canvas_end_forced_full_redraws(sp_desktop_canvas(desktop)); + + _blocked = false; +} + +void +FillAndStroke::_opacityValueChanged() +{ + if (_blocked) + return; + _blocked = true; + + // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed; here it results in crash 1580903 + // UPDATE: crash fixed in GTK+ 2.10.7 (bug 374378), remove this as soon as it's reasonably common + // (though this only fixes the crash, not the multiple change events) + sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(SP_ACTIVE_DESKTOP), 0); + + SPCSSAttr *css = sp_repr_css_attr_new (); + + Inkscape::CSSOStringStream os; + os << CLAMP (_opacity_adjustment.get_value() / 100, 0.0, 1.0); + sp_repr_css_set_property (css, "opacity", os.str().c_str()); + + sp_desktop_set_style (SP_ACTIVE_DESKTOP, css); + + sp_repr_css_attr_unref (css); + + sp_document_maybe_done (sp_desktop_document (SP_ACTIVE_DESKTOP), "fillstroke:opacity", SP_VERB_DIALOG_FILL_STROKE, + _("Change opacity")); + + // resume interruptibility + sp_canvas_end_forced_full_redraws(sp_desktop_canvas(SP_ACTIVE_DESKTOP)); + + _blocked = false; +} + +void +FillAndStroke::selectionChanged(Inkscape::Application *inkscape, + Inkscape::Selection *selection) +{ + if (_blocked) + return; + _blocked = true; + + // create temporary style + SPStyle *query = sp_style_new (); + // query style from desktop into it. This returns a result flag and fills query with the style of subselection, if any, or selection + int result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_MASTEROPACITY); + + switch (result) { + case QUERY_STYLE_NOTHING: + _opacity_hbox.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); + _opacity_adjustment.set_value(100 * SP_SCALE24_TO_FLOAT(query->opacity.value)); + break; + } + + //query now for current average blurring of selection + int blur_result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_BLUR); + switch (blur_result) { + case QUERY_STYLE_NOTHING: //no blurring + _blur_hbox.set_sensitive(false); + break; + case QUERY_STYLE_SINGLE: + case QUERY_STYLE_MULTIPLE_AVERAGED: + case QUERY_STYLE_MULTIPLE_SAME: + NR::Maybe bbox = sp_desktop_selection(SP_ACTIVE_DESKTOP)->bounds(); + if (bbox) { + double perimeter = bbox->extent(NR::X) + bbox->extent(NR::Y); + _blur_hbox.set_sensitive(true); + //update blur widget value + float radius = query->filter_gaussianBlur_deviation.value; + float percent = radius * 400 / perimeter; // so that for a square, 100% == half side + _blur_adjustment.set_value(percent); + } + break; + } + + g_free (query); + + _blocked = false; +} + +Gtk::HBox& +FillAndStroke::_createPageTabLabel(const Glib::ustring& label, const char *label_image) +{ + Gtk::HBox *_tab_label_box = manage(new Gtk::HBox(false, 0)); + _tab_label_box->pack_start(*Glib::wrap(sp_icon_new(Inkscape::ICON_SIZE_DECORATION, + label_image))); + + Gtk::Label *_tab_label = manage(new Gtk::Label(label, true)); + _tab_label_box->pack_start(*_tab_label); + _tab_label_box->show_all(); + + return *_tab_label_box; +} + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/fill-and-stroke.h b/src/ui/dialog/fill-and-stroke.h index 0e63ef1c3..f4acf0086 100644 --- a/src/ui/dialog/fill-and-stroke.h +++ b/src/ui/dialog/fill-and-stroke.h @@ -1,10 +1,12 @@ /** * \brief Fill and Stroke dialog + * based on sp_object_properties_dialog * * Authors: * Bryce W. Harrington + * Gustav Broberg * - * Copyright (C) 2004, 2005 Authors + * Copyright (C) 2004--2007 Authors * * Released under GNU GPL. Read the file 'COPYING' for more information. */ @@ -12,7 +14,10 @@ #ifndef INKSCAPE_UI_DIALOG_FILL_AND_STROKE_H #define INKSCAPE_UI_DIALOG_FILL_AND_STROKE_H +#include #include +#include +#include #include #include "dialog.h" @@ -31,6 +36,9 @@ public: static FillAndStroke *create() { return new FillAndStroke(); } + void selectionChanged(Inkscape::Application *inkscape, + Inkscape::Selection *selection); + protected: Gtk::Notebook _notebook; @@ -38,6 +46,34 @@ protected: NotebookPage _page_stroke_paint; NotebookPage _page_stroke_style; + Gtk::VBox _blur_vbox; + Gtk::HBox _blur_label_box; + Gtk::HBox _blur_hbox; + Gtk::Label _blur_label; + Gtk::Adjustment _blur_adjustment; + Gtk::HScale _blur_hscale; + Gtk::SpinButton _blur_spin_button; + + Gtk::VBox _opacity_vbox; + Gtk::HBox _opacity_label_box; + Gtk::HBox _opacity_hbox; + Gtk::Label _opacity_label; + Gtk::Adjustment _opacity_adjustment; + Gtk::HScale _opacity_hscale; + Gtk::SpinButton _opacity_spin_button; + + Gtk::HBox& _createPageTabLabel(const Glib::ustring& label, + const char *label_image); + + void _layoutPageFill(); + void _layoutPageStrokePaint(); + void _layoutPageStrokeStyle(); + + void _blurValueChanged(); + void _opacityValueChanged(); + + bool _blocked; + private: FillAndStroke(FillAndStroke const &d); FillAndStroke& operator=(FillAndStroke const &d); diff --git a/src/ui/widget/notebook-page.cpp b/src/ui/widget/notebook-page.cpp index 83be16a43..47035ce2f 100644 --- a/src/ui/widget/notebook-page.cpp +++ b/src/ui/widget/notebook-page.cpp @@ -25,12 +25,12 @@ namespace Widget { * \param label Label. */ -NotebookPage::NotebookPage(int n_rows, int n_columns) +NotebookPage::NotebookPage(int n_rows, int n_columns, bool expand, bool fill, guint padding) :_table(n_rows, n_columns) { set_border_width(2); _table.set_spacings(2); - pack_start(_table, false, false, 0); + pack_start(_table, expand, fill, padding); } } // namespace Widget diff --git a/src/ui/widget/notebook-page.h b/src/ui/widget/notebook-page.h index 0341cb659..38c13005e 100644 --- a/src/ui/widget/notebook-page.h +++ b/src/ui/widget/notebook-page.h @@ -24,7 +24,7 @@ class NotebookPage : public Gtk::VBox { public: NotebookPage(); - NotebookPage(int n_rows, int n_columns); + NotebookPage(int n_rows, int n_columns, bool expand=false, bool fill=false, guint padding=0); Gtk::Table& table() { return _table; } diff --git a/src/verbs.cpp b/src/verbs.cpp index 6a81dc7e0..01172f102 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -1662,6 +1662,7 @@ DialogVerb::perform(SPAction *action, void *data, void *pdata) break; case SP_VERB_DIALOG_FILL_STROKE: sp_object_properties_dialog(); + // dt->_dlg_mgr->showDialog("FillAndStroke"); break; case SP_VERB_DIALOG_SWATCHES: show_panel( Inkscape::UI::Dialogs::SwatchesPanel::getInstance(), "dialogs.swatches", SP_VERB_DIALOG_SWATCHES); -- 2.30.2