#define INKSCAPE_LPE_POINTPARAM_KNOTHOLDER_C /* * Container for PointParamKnotHolder visual handles * * Authors: * Johan Engelen * * Copyright (C) 2008 authors * * Released under GNU GPL, read the file 'COPYING' for more information */ #include "live_effects/parameter/pointparam-knotholder.h" #include "live_effects/lpeobject.h" #include "document.h" #include "sp-shape.h" #include "knot.h" #include "knotholder.h" #include "knot-holder-entity.h" #include #include #include <2geom/point.h> #include <2geom/matrix.h> #include "svg/stringstream.h" #include "xml/repr.h" class SPDesktop; namespace Inkscape { static void pointparam_knot_clicked_handler (SPKnot *knot, guint state, PointParamKnotHolder *kh); static void pointparam_knot_moved_handler(SPKnot *knot, NR::Point const *p, guint state, PointParamKnotHolder *kh); static void pointparam_knot_ungrabbed_handler (SPKnot *knot, unsigned int state, PointParamKnotHolder *kh); static void pointparam_knot_holder_class_init(PointParamKnotHolderClass *klass); void pointparam_knot_holder_dispose(GObject *object); static SPKnotHolderClass *parent_class; /** * Registers PointParamKnotHolder class and returns its type number. */ GType pointparam_knot_holder_get_type() { static GType type = 0; if (!type) { GTypeInfo info = { sizeof(PointParamKnotHolderClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) pointparam_knot_holder_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (PointParamKnotHolder), 16, /* n_preallocs */ NULL, NULL }; type = g_type_register_static (G_TYPE_OBJECT, "InkscapePointParamKnotHolder", &info, (GTypeFlags) 0); } return type; } /** * PointParamKnotHolder vtable initialization. */ static void pointparam_knot_holder_class_init(PointParamKnotHolderClass *klass) { GObjectClass *gobject_class; gobject_class = (GObjectClass *) klass; parent_class = (SPKnotHolderClass*) g_type_class_peek_parent(klass); gobject_class->dispose = pointparam_knot_holder_dispose; } PointParamKnotHolder *pointparam_knot_holder_new(SPDesktop *desktop, SPObject *lpeobject, const gchar * key, SPItem *item) { g_return_val_if_fail(desktop != NULL, NULL); g_return_val_if_fail(item != NULL, NULL); g_return_val_if_fail(SP_IS_ITEM(item), NULL); PointParamKnotHolder *knot_holder = (PointParamKnotHolder*)g_object_new (INKSCAPE_TYPE_POINTPARAM_KNOT_HOLDER, 0); knot_holder->desktop = desktop; knot_holder->item = item; knot_holder->lpeobject = LIVEPATHEFFECT(lpeobject); g_object_ref(G_OBJECT(item)); g_object_ref(G_OBJECT(lpeobject)); knot_holder->entity = NULL; knot_holder->released = NULL; knot_holder->repr = lpeobject->repr; knot_holder->repr_key = key; knot_holder->local_change = FALSE; return knot_holder; } void pointparam_knot_holder_dispose(GObject *object) { PointParamKnotHolder *kh = G_TYPE_CHECK_INSTANCE_CAST((object), INKSCAPE_TYPE_POINTPARAM_KNOT_HOLDER, PointParamKnotHolder); g_object_unref(G_OBJECT(kh->item)); g_object_unref(G_OBJECT(kh->lpeobject)); while (kh->entity) { SPKnotHolderEntity *e = (SPKnotHolderEntity *) kh->entity->data; g_signal_handler_disconnect(e->knot, e->_click_handler_id); g_signal_handler_disconnect(e->knot, e->_ungrab_handler_id); /* unref should call destroy */ g_object_unref(e->knot); g_free(e); kh->entity = g_slist_remove(kh->entity, e); } } void PointParamKnotHolder::add_knot ( Geom::Point & p, PointParamKnotHolderClickedFunc knot_click, SPKnotShapeType shape, SPKnotModeType mode, guint32 color, const gchar *tip ) { /* create new SPKnotHolderEntry */ SPKnotHolderEntity *e = g_new(SPKnotHolderEntity, 1); e->knot = sp_knot_new(desktop, tip); e->knot_set = NULL; e->knot_get = NULL; if (knot_click) { e->knot_click = knot_click; } else { e->knot_click = NULL; } g_object_set(G_OBJECT (e->knot->item), "shape", shape, NULL); g_object_set(G_OBJECT (e->knot->item), "mode", mode, NULL); e->knot->fill [SP_KNOT_STATE_NORMAL] = color; g_object_set (G_OBJECT (e->knot->item), "fill_color", color, NULL); entity = g_slist_append(entity, e); /* Move to current point. */ NR::Point dp = p * sp_item_i2d_affine(item); sp_knot_set_position(e->knot, &dp, SP_KNOT_STATE_NORMAL); e->handler_id = g_signal_connect(e->knot, "moved", G_CALLBACK(pointparam_knot_moved_handler), this); e->_click_handler_id = g_signal_connect(e->knot, "clicked", G_CALLBACK(pointparam_knot_clicked_handler), this); e->_ungrab_handler_id = g_signal_connect(e->knot, "ungrabbed", G_CALLBACK(pointparam_knot_ungrabbed_handler), this); sp_knot_show(e->knot); } static void pointparam_knot_clicked_handler(SPKnot */*knot*/, guint /*state*/, PointParamKnotHolder */*kh*/) { } /** * \param p In desktop coordinates. * This function does not write to XML, but tries to write directly to the PointParam to quickly live update the effect */ static void pointparam_knot_moved_handler(SPKnot */*knot*/, NR::Point const *p, guint /*state*/, PointParamKnotHolder *kh) { NR::Matrix const i2d(sp_item_i2d_affine(kh->item)); NR::Point pos = (*p) / i2d; Inkscape::SVGOStringStream os; os << pos.to_2geom(); kh->lpeobject->lpe->setParameter(kh->repr_key, os.str().c_str()); } static void pointparam_knot_ungrabbed_handler(SPKnot *knot, unsigned int /*state*/, PointParamKnotHolder *kh) { NR::Matrix const i2d(sp_item_i2d_affine(kh->item)); NR::Point pos = sp_knot_position(knot) / i2d; Inkscape::SVGOStringStream os; os << pos.to_2geom(); kh->repr->setAttribute(kh->repr_key , os.str().c_str()); sp_document_done(SP_OBJECT_DOCUMENT (kh->lpeobject), SP_VERB_CONTEXT_LPE, _("Change LPE point parameter")); } } // namespace Inkscape /* Local Variables: mode:c++ c-file-style:"stroustrup" c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :