From ad83b521a557c8a2d91c469f74137ca4ff4ab2d1 Mon Sep 17 00:00:00 2001 From: mental Date: Tue, 1 Jan 2008 04:40:11 +0000 Subject: [PATCH] abstraction for style widget subjects --- src/ui/widget/Makefile_insert | 2 + src/ui/widget/object-composite-settings.cpp | 98 +++++----- src/ui/widget/object-composite-settings.h | 19 +- src/ui/widget/style-subject.cpp | 193 ++++++++++++++++++++ src/ui/widget/style-subject.h | 123 +++++++++++++ 5 files changed, 364 insertions(+), 71 deletions(-) create mode 100644 src/ui/widget/style-subject.cpp create mode 100644 src/ui/widget/style-subject.h diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert index 7661aeb8e..fbbc686ab 100644 --- a/src/ui/widget/Makefile_insert +++ b/src/ui/widget/Makefile_insert @@ -69,6 +69,8 @@ ui_widget_libuiwidget_a_SOURCES = \ ui/widget/selected-style.cpp \ ui/widget/spin-slider.h \ ui/widget/spin-slider.cpp \ + ui/widget/style-subject.h \ + ui/widget/style-subject.cpp \ ui/widget/style-swatch.h \ ui/widget/style-swatch.cpp \ ui/widget/svg-canvas.cpp \ diff --git a/src/ui/widget/object-composite-settings.cpp b/src/ui/widget/object-composite-settings.cpp index 65458dc94..b9a88b8da 100644 --- a/src/ui/widget/object-composite-settings.cpp +++ b/src/ui/widget/object-composite-settings.cpp @@ -31,32 +31,23 @@ namespace Inkscape { namespace UI { namespace Widget { -void ObjectCompositeSettings::on_selection_changed( - Inkscape::Application *inkscape, - Inkscape::Selection *selection, +void ObjectCompositeSettings::_on_desktop_switch( + Inkscape::Application *application, + SPDesktop *desktop, ObjectCompositeSettings *w ) { - w->selectionChanged(inkscape, selection); -} - -void ObjectCompositeSettings::on_selection_modified( - Inkscape::Application *inkscape, - Inkscape::Selection *selection, - guint /*flags*/, - ObjectCompositeSettings *w -) { - w->selectionChanged(inkscape, selection); + w->_subject.setDesktop(desktop); } ObjectCompositeSettings::ObjectCompositeSettings() -: _fe_vbox(false, 0), - _fe_alignment(1, 1, 1, 1), - _opacity_vbox(false, 0), +: _opacity_vbox(false, 0), _opacity_label_box(false, 0), _opacity_label(_("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), + _fe_vbox(false, 0), + _fe_alignment(1, 1, 1, 1), _blocked(false) { // Filter Effects @@ -76,50 +67,36 @@ ObjectCompositeSettings::ObjectCompositeSettings() _opacity_hscale.set_draw_value(false); _opacity_adjustment.signal_value_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_opacityValueChanged)); - _sel_changed = g_signal_connect ( G_OBJECT (INKSCAPE), "change_selection", G_CALLBACK (on_selection_changed), this ); - _subsel_changed = g_signal_connect ( G_OBJECT (INKSCAPE), "change_subselection", G_CALLBACK (on_selection_changed), this ); - _sel_modified = g_signal_connect ( G_OBJECT (INKSCAPE), "modify_selection", G_CALLBACK (on_selection_modified), this ); - _desktop_activated = 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(); + + _desktop_activated = g_signal_connect ( G_OBJECT (INKSCAPE), "activate_desktop", G_CALLBACK (&ObjectCompositeSettings::_on_desktop_switch), this ); + _subject.connectChanged(sigc::mem_fun(*this, &ObjectCompositeSettings::_subjectChanged)); + _subject.setDesktop(SP_ACTIVE_DESKTOP); } ObjectCompositeSettings::~ObjectCompositeSettings() { - g_signal_handler_disconnect(G_OBJECT(INKSCAPE), _sel_changed); - g_signal_handler_disconnect(G_OBJECT(INKSCAPE), _subsel_changed); - g_signal_handler_disconnect(G_OBJECT(INKSCAPE), _sel_modified); g_signal_handler_disconnect(G_OBJECT(INKSCAPE), _desktop_activated); } void ObjectCompositeSettings::_blendBlurValueChanged() { - if (_blocked) - return; - _blocked = true; - - //get desktop - SPDesktop *desktop = SP_ACTIVE_DESKTOP; + SPDesktop *desktop = _subject.getDesktop(); if (!desktop) { return; } + if (_blocked) + return; + _blocked = true; + // 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(); + NR::Maybe bbox = _subject.getBounds(); 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); @@ -130,13 +107,18 @@ ObjectCompositeSettings::_blendBlurValueChanged() const bool remfilter = (blendmode == "normal" && radius == 0) || (blendmode == "filter" && !filter); if(blendmode != "filter" || filter) { + SPDocument *document = sp_desktop_document (desktop); + //apply created filter to every selected item - for (GSList const *i = items; i != NULL; i = i->next) { - SPItem * item = SP_ITEM(i->data); + for (StyleSubject::iterator i = _subject.begin() ; i != _subject.end() ; ++i ) { + if (!SP_IS_ITEM(*i)) { + continue; + } + + SPItem * item = SP_ITEM(*i); SPStyle *style = SP_OBJECT_STYLE(item); g_assert(style != NULL); - if(remfilter) { remove_filter (item, false); } @@ -163,12 +145,15 @@ ObjectCompositeSettings::_blendBlurValueChanged() void ObjectCompositeSettings::_opacityValueChanged() { + SPDesktop *desktop = _subject.getDesktop(); + if (!desktop) { + return; + } + if (_blocked) return; _blocked = true; - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - // 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) @@ -180,7 +165,7 @@ ObjectCompositeSettings::_opacityValueChanged() 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 (desktop, css); + _subject.setCSS(css); sp_repr_css_attr_unref (css); @@ -194,19 +179,18 @@ ObjectCompositeSettings::_opacityValueChanged() } void -ObjectCompositeSettings::selectionChanged(Inkscape::Application */*inkscape*/, - Inkscape::Selection */*selection*/) -{ +ObjectCompositeSettings::_subjectChanged() { + SPDesktop *desktop = _subject.getDesktop(); + if (!desktop) { + return; + } + if (_blocked) return; _blocked = true; - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - - // create temporary style SPStyle *query = sp_style_new (sp_desktop_document(desktop)); - // 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 (desktop, query, QUERY_STYLE_PROPERTY_MASTEROPACITY); + int result = _subject.queryStyle(query, QUERY_STYLE_PROPERTY_MASTEROPACITY); switch (result) { case QUERY_STYLE_NOTHING: @@ -222,7 +206,7 @@ ObjectCompositeSettings::selectionChanged(Inkscape::Application */*inkscape*/, } //query now for current filter mode and average blurring of selection - const int blend_result = sp_desktop_query_style (desktop, query, QUERY_STYLE_PROPERTY_BLEND); + const int blend_result = _subject.queryStyle(query, QUERY_STYLE_PROPERTY_BLEND); switch(blend_result) { case QUERY_STYLE_NOTHING: _fe_cb.set_sensitive(false); @@ -239,7 +223,7 @@ ObjectCompositeSettings::selectionChanged(Inkscape::Application */*inkscape*/, } if(blend_result == QUERY_STYLE_SINGLE || blend_result == QUERY_STYLE_MULTIPLE_SAME) { - int blur_result = sp_desktop_query_style (desktop, query, QUERY_STYLE_PROPERTY_BLUR); + int blur_result = _subject.queryStyle(query, QUERY_STYLE_PROPERTY_BLUR); switch (blur_result) { case QUERY_STYLE_NOTHING: //no blurring _fe_cb.set_blur_sensitive(false); @@ -247,7 +231,7 @@ ObjectCompositeSettings::selectionChanged(Inkscape::Application */*inkscape*/, case QUERY_STYLE_SINGLE: case QUERY_STYLE_MULTIPLE_AVERAGED: case QUERY_STYLE_MULTIPLE_SAME: - NR::Maybe bbox = sp_desktop_selection(desktop)->bounds(); + NR::Maybe bbox = _subject.getBounds(); if (bbox) { double perimeter = bbox->extent(NR::X) + bbox->extent(NR::Y); _fe_cb.set_blur_sensitive(true); diff --git a/src/ui/widget/object-composite-settings.h b/src/ui/widget/object-composite-settings.h index fa007685b..6cbcc82af 100644 --- a/src/ui/widget/object-composite-settings.h +++ b/src/ui/widget/object-composite-settings.h @@ -21,6 +21,7 @@ #include #include "ui/widget/filter-effect-chooser.h" +#include "ui/widget/style-subject.h" namespace Inkscape { namespace UI { @@ -40,30 +41,20 @@ private: Gtk::HScale _opacity_hscale; Gtk::SpinButton _opacity_spin_button; + StyleSubject::Selection _subject; + SimpleFilterModifier _fe_cb; Gtk::VBox _fe_vbox; Gtk::Alignment _fe_alignment; - void selectionChanged(Inkscape::Application *inkscape, - Inkscape::Selection *selection); - - static void on_selection_changed(Inkscape::Application *inkscape, - Inkscape::Selection *selection, - ObjectCompositeSettings *w); - - static void on_selection_modified(Inkscape::Application *inkscape, - Inkscape::Selection *selection, - guint flags, - ObjectCompositeSettings *w); + static void _on_desktop_switch(Inkscape::Application *application, SPDesktop *desktop, ObjectCompositeSettings *w); + void _subjectChanged(); void _blendBlurValueChanged(); void _opacityValueChanged(); bool _blocked; - gulong _sel_changed; - gulong _subsel_changed; - gulong _sel_modified; gulong _desktop_activated; }; diff --git a/src/ui/widget/style-subject.cpp b/src/ui/widget/style-subject.cpp new file mode 100644 index 000000000..f7864acc3 --- /dev/null +++ b/src/ui/widget/style-subject.cpp @@ -0,0 +1,193 @@ +/** + * \brief Abstraction for different style widget operands + * + * Copyright (C) 2007 MenTaLguY + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#include "ui/widget/style-subject.h" + +#include "desktop.h" +#include "sp-object.h" +#include "xml/sp-css-attr.h" +#include "desktop-style.h" +#include "desktop-handles.h" +#include "selection.h" +#include "style.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +StyleSubject::StyleSubject() : _desktop(NULL) { +} + +StyleSubject::~StyleSubject() { + setDesktop(NULL); +} + +void StyleSubject::setDesktop(SPDesktop *desktop) { + if (desktop != _desktop) { + if (desktop) { + GC::anchor(desktop); + } + if (_desktop) { + GC::release(_desktop); + } + _desktop = desktop; + _afterDesktopSwitch(desktop); + _emitChanged(); + } +} + +StyleSubject::Selection::Selection() { +} + +StyleSubject::Selection::~Selection() { +} + +Inkscape::Selection *StyleSubject::Selection::_getSelection() const { + SPDesktop *desktop = getDesktop(); + if (desktop) { + return sp_desktop_selection(desktop); + } else { + return NULL; + } +} + +StyleSubject::iterator StyleSubject::Selection::begin() { + Inkscape::Selection *selection = _getSelection(); + if (selection) { + return iterator(selection->list()); + } else { + return iterator(NULL); + } +} + +NR::Maybe StyleSubject::Selection::getBounds(SPItem::BBoxType type) { + Inkscape::Selection *selection = _getSelection(); + if (selection) { + return selection->bounds(type); + } else { + return NR::Nothing(); + } +} + +int StyleSubject::Selection::queryStyle(SPStyle *query, int property) { + SPDesktop *desktop = getDesktop(); + if (desktop) { + return sp_desktop_query_style(desktop, query, property); + } else { + return QUERY_STYLE_NOTHING; + } +} + +void StyleSubject::Selection::_afterDesktopSwitch(SPDesktop *desktop) { + _sel_changed.disconnect(); + _subsel_changed.disconnect(); + _sel_modified.disconnect(); + if (desktop) { + _subsel_changed = desktop->connectToolSubselectionChanged(sigc::hide(sigc::mem_fun(*this, &Selection::_emitChanged))); + Inkscape::Selection *selection = sp_desktop_selection(desktop); + if (selection) { + _sel_changed = selection->connectChanged(sigc::hide(sigc::mem_fun(*this, &Selection::_emitChanged))); + _sel_modified = selection->connectModified(sigc::hide(sigc::hide(sigc::mem_fun(*this, &Selection::_emitChanged)))); + } + } +} + +void StyleSubject::Selection::setCSS(SPCSSAttr *css) { + SPDesktop *desktop = getDesktop(); + if (desktop) { + sp_desktop_set_style(desktop, css); + } +} + +StyleSubject::CurrentLayer::CurrentLayer() { + _element.data = NULL; + _element.next = NULL; +} + +StyleSubject::CurrentLayer::~CurrentLayer() { +} + +void StyleSubject::CurrentLayer::_setLayer(SPObject *layer) { + _layer_release.disconnect(); + _layer_modified.disconnect(); + if (_element.data) { + sp_object_unref(static_cast(_element.data), NULL); + } + _element.data = layer; + if (layer) { + sp_object_ref(layer, NULL); + _layer_release = layer->connectRelease(sigc::hide(sigc::bind(sigc::mem_fun(*this, &CurrentLayer::_setLayer), (SPObject *)NULL))); + _layer_modified = layer->connectModified(sigc::hide(sigc::hide(sigc::mem_fun(*this, &CurrentLayer::_emitChanged)))); + } +} + +SPObject *StyleSubject::CurrentLayer::_getLayer() const { + return static_cast(_element.data); +} + +GSList *StyleSubject::CurrentLayer::_getLayerSList() const { + if (_element.data) { + return &_element; + } else { + return NULL; + } +} + +StyleSubject::iterator StyleSubject::CurrentLayer::begin() { + return iterator(_getLayerSList()); +} + +NR::Maybe StyleSubject::CurrentLayer::getBounds(SPItem::BBoxType type) { + SPObject *layer = _getLayer(); + if (layer && SP_IS_ITEM(layer)) { + return sp_item_bbox_desktop(SP_ITEM(layer), type); + } else { + return NR::Nothing(); + } +} + +int StyleSubject::CurrentLayer::queryStyle(SPStyle *query, int property) { + GSList *list = _getLayerSList(); + if (list) { + return sp_desktop_query_style_from_list(list, query, property); + } else { + return QUERY_STYLE_NOTHING; + } +} + +void StyleSubject::CurrentLayer::setCSS(SPCSSAttr *css) { + SPObject *layer = _getLayer(); + if (layer) { + sp_desktop_apply_css_recursive(layer, css, true); + } +} + +void StyleSubject::CurrentLayer::_afterDesktopSwitch(SPDesktop *desktop) { + _layer_switched.disconnect(); + if (desktop) { + _layer_switched = desktop->connectCurrentLayerChanged(sigc::mem_fun(*this, &CurrentLayer::_setLayer)); + _setLayer(desktop->currentLayer()); + } else { + _setLayer(NULL); + } +} + +} +} +} + +/* + 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:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/style-subject.h b/src/ui/widget/style-subject.h new file mode 100644 index 000000000..07ab64ab6 --- /dev/null +++ b/src/ui/widget/style-subject.h @@ -0,0 +1,123 @@ +/** + * \brief Abstraction for different style widget operands + * + * Copyright (C) 2007 MenTaLguY + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef SEEN_INKSCAPE_UI_WIDGET_STYLE_SUBJECT_H +#define SEEN_INKSCAPE_UI_WIDGET_STYLE_SUBJECT_H + +#include "util/glib-list-iterators.h" +#include "libnr/nr-maybe.h" +#include "libnr/nr-rect.h" +#include "sp-item.h" +#include + +class SPDesktop; +class SPObject; +class SPCSSAttr; +class SPStyle; + +namespace Inkscape { +class Selection; +} + +namespace Inkscape { +namespace UI { +namespace Widget { + +class StyleSubject { +public: + class Selection; + class CurrentLayer; + + typedef Util::GSListConstIterator iterator; + + StyleSubject(); + virtual ~StyleSubject(); + + void setDesktop(SPDesktop *desktop); + SPDesktop *getDesktop() const { return _desktop; } + + virtual iterator begin() = 0; + virtual iterator end() { return iterator(NULL); } + virtual NR::Maybe getBounds(SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) = 0; + virtual int queryStyle(SPStyle *query, int property) = 0; + virtual void setCSS(SPCSSAttr *css) = 0; + + sigc::connection connectChanged(sigc::signal::slot_type slot) { + return _changed_signal.connect(slot); + } + +protected: + virtual void _afterDesktopSwitch(SPDesktop *desktop) {} + void _emitChanged() { _changed_signal.emit(); } + +private: + sigc::signal _changed_signal; + SPDesktop *_desktop; +}; + +class StyleSubject::Selection : public StyleSubject { +public: + Selection(); + ~Selection(); + + virtual iterator begin(); + virtual NR::Maybe getBounds(SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX); + virtual int queryStyle(SPStyle *query, int property); + virtual void setCSS(SPCSSAttr *css); + +protected: + virtual void _afterDesktopSwitch(SPDesktop *desktop); + +private: + Inkscape::Selection *_getSelection() const; + + sigc::connection _sel_changed; + sigc::connection _subsel_changed; + sigc::connection _sel_modified; +}; + +class StyleSubject::CurrentLayer : public StyleSubject { +public: + CurrentLayer(); + ~CurrentLayer(); + + virtual iterator begin(); + virtual NR::Maybe getBounds(SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX); + virtual int queryStyle(SPStyle *query, int property); + virtual void setCSS(SPCSSAttr *css); + +protected: + virtual void _afterDesktopSwitch(SPDesktop *desktop); + +private: + SPObject *_getLayer() const; + void _setLayer(SPObject *layer); + GSList *_getLayerSList() const; + + sigc::connection _layer_switched; + sigc::connection _layer_release; + sigc::connection _layer_modified; + mutable GSList _element; +}; + +} +} +} + +#endif + +/* + 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:encoding=utf-8:textwidth=99 : -- 2.30.2