Code

Infrastructure in class LivePathEffect::Effect to put Inkscape into 'wait for paramet...
authorcilix42 <cilix42@users.sourceforge.net>
Thu, 12 Jun 2008 13:23:17 +0000 (13:23 +0000)
committercilix42 <cilix42@users.sourceforge.net>
Thu, 12 Jun 2008 13:23:17 +0000 (13:23 +0000)
src/live_effects/effect.cpp
src/live_effects/effect.h
src/live_effects/lpe-mirror_reflect.cpp
src/live_effects/lpe-mirror_reflect.h
src/pen-context.cpp
src/pen-context.h
src/sp-lpe-item.cpp

index 0aaedab0a642a1233d8b56acab177e5b03df4c97..18d05fe672e189c0a8d2e59f3e0fc7e7ee578741 100644 (file)
 #include "document-private.h"
 #include "xml/document.h"
 #include <glibmm/i18n.h>
+#include "pen-context.h"
+#include "tools-switch.h"
+#include "message-stack.h"
+#include "desktop.h"
 
 #include "live_effects/lpeobject.h"
 #include "live_effects/parameter/parameter.h"
@@ -183,6 +187,7 @@ Effect::createAndApply(EffectType type, SPDocument *doc, SPItem *item)
 Effect::Effect(LivePathEffectObject *lpeobject)
     : oncanvasedit_it(0),
       is_visible(_("Is visible?"), _("If unchecked, the effect remains applied to the object but is temporarily disabled on canvas"), "is_visible", &wr, this, true),
+      done_pathparam_set(false),
       lpeobj(lpeobject),
       concatenate_before_pwd2(false)
 {
@@ -207,18 +212,48 @@ Effect::effectType() {
     return lpeobj->effecttype;
 }
 
+/**
+ * Is performed a single time when the effect is freshly applied to a path
+ */
 void
 Effect::doOnApply (SPLPEItem */*lpeitem*/)
 {
-    // This is performed once when the effect is freshly applied to a path
 }
 
+/**
+ * Is performed each time before the effect is updated.
+ */
 void
 Effect::doBeforeEffect (SPLPEItem */*lpeitem*/)
 {
     //Do nothing for simple effects
 }
 
+/**
+ * Effects have a parameter path set before they are applied by accepting a nonzero number of mouse
+ * clicks. This method activates the pen context, which waits for the specified number of clicks.
+ * Override Effect::acceptsNumParams() to set the number of expected mouse clicks.
+ */
+void
+Effect::doAcceptPathPreparations(SPLPEItem *lpeitem)
+{
+    // switch to pen context
+    SPDesktop *desktop = inkscape_active_desktop(); // TODO: Is there a better method to find the item's desktop?
+    if (!tools_isactive(desktop, TOOLS_FREEHAND_PEN)) {
+        tools_switch(desktop, TOOLS_FREEHAND_PEN);
+    }
+
+    SPEventContext *ec = desktop->event_context;
+    SPPenContext *pc = SP_PEN_CONTEXT(ec);
+    pc->expecting_clicks_for_LPE = this->acceptsNumParams();
+    pc->waiting_LPE = this;
+    pc->waiting_item = lpeitem;
+    pc->polylines_only = true;
+
+    ec->desktop->messageStack()->flash(Inkscape::INFORMATION_MESSAGE,
+        g_strdup_printf(_("Please specify a parameter path for the LPE '%s' with %d mouse clicks"),
+                        getName().c_str(), acceptsNumParams()));
+}
 
 void
 Effect::writeParamsToSVG() {
@@ -228,6 +263,16 @@ Effect::writeParamsToSVG() {
     }
 }
 
+/**
+ * If the effect expects a path parameter (specified by a number of mouse clicks) before it is
+ * applied, this is the method that processes the resulting path. Override it to customize it for
+ * your LPE. But don't forget to call the parent method so that done_pathparam_set is set to true!
+ */
+void
+Effect::acceptParamPath (SPPath *param_path) {
+    done_pathparam_set = true;
+}
+
 /*
  *  Here be the doEffect function chain:
  */
index 665509fd118e048df75a8ec0d43e9bd189821755..f1241c54b8a79ff305913a30138b2031af4e3de5 100644 (file)
@@ -95,10 +95,16 @@ public:
     EffectType effectType ();
 
     virtual void doOnApply (SPLPEItem *lpeitem);
-
     virtual void doBeforeEffect (SPLPEItem *lpeitem);
+
     void writeParamsToSVG();
 
+    virtual void acceptParamPath (SPPath *param_path);
+    virtual int acceptsNumParams() { return 0; }
+    void doAcceptPathPreparations(SPLPEItem *lpeitem);
+
+    inline bool pathParamAccepted() { return done_pathparam_set; }
+
     virtual void doEffect (SPCurve * curve);
 
     virtual Gtk::Widget * newWidget(Gtk::Tooltips * tooltips);
@@ -148,6 +154,7 @@ protected:
     std::vector<std::pair<KnotHolderEntity*, const char*> > kh_entity_vector;
     int oncanvasedit_it;
     BoolParam is_visible;
+    bool done_pathparam_set;
 
     Inkscape::UI::Widget::Registry wr;
 
index 438d012dbc827d53eb66a4db7591f709767be601..093841c8d61101b547c496edd77282b0f7026b51 100644 (file)
@@ -38,22 +38,20 @@ LPEMirrorReflect::~LPEMirrorReflect()
 }
 
 void
-LPEMirrorReflect::doOnApply (SPLPEItem *lpeitem)
-{
+LPEMirrorReflect::acceptParamPath (SPPath *param_path) {
     using namespace Geom;
 
-    SPCurve *curve = sp_path_get_curve_for_edit (SP_PATH(lpeitem));
-    Point A(curve->first_point().to_2geom());
-    Point B(curve->last_point().to_2geom());
-
-    Point M = (2*A + B)/3; // some point between A and B (a bit closer to A)
-    Point perp_dir = unit_vector((B - A).ccw());
+    SPCurve* curve = sp_path_get_curve_for_edit (param_path);
+    Geom::Point A(curve->first_point().to_2geom());
+    Geom::Point B(curve->last_point().to_2geom());
     
-    Point C(M[X], M[Y] + 150);
-    Point D(M[X], M[Y] - 150);
-
-    Piecewise<D2<SBasis> > rline = Piecewise<D2<SBasis> >(D2<SBasis>(Linear(C[X], D[X]), Linear(C[Y], D[Y])));
+    Piecewise<D2<SBasis> > rline = Piecewise<D2<SBasis> >(D2<SBasis>(Linear(A[X], B[X]), Linear(A[Y], B[Y])));
     reflection_line.param_set_and_write_new_value(rline);
+
+    SP_OBJECT(param_path)->deleteObject(true);
+
+    // don't remove this; needed for cleanup tasks
+    Effect::acceptParamPath(param_path);
 }
 
 std::vector<Geom::Path>
index 79b1854f83adc0b2812a29817ff5564ab83c32ef..a19aafb891101f640426b1f4d7497875615d9c69 100644 (file)
@@ -28,7 +28,8 @@ public:
     LPEMirrorReflect(LivePathEffectObject *lpeobject);
     virtual ~LPEMirrorReflect();
 
-    virtual void doOnApply (SPLPEItem *lpeitem);
+    virtual void acceptParamPath (SPPath *param_path);
+    virtual int acceptsNumParams() { return 2; }
 
     virtual LPEPathFlashType pathFlashType() { return PERMANENT_FLASH; }
 
index dd9688f02745a39b7ea99da1373c69ed54f534cf..4616c04ae9735eb5c3d586464918a6d2e93a3f6d 100644 (file)
@@ -181,7 +181,7 @@ sp_pen_context_dispose(GObject *object)
     pc->polylines_only = false;
     if (pc->expecting_clicks_for_LPE > 0) {
         // we received too few clicks to sanely set the parameter path so we remove the LPE from the item
-        //sp_lpe_item_remove_current_path_effect(SP_LPE_ITEM(pc->waiting_item), false);
+        sp_lpe_item_remove_current_path_effect(pc->waiting_item, false);
     }
 }
 
@@ -785,8 +785,8 @@ pen_handle_button_release(SPPenContext *const pc, GdkEventButton const &revent)
             SPEventContext *ec = SP_EVENT_CONTEXT(pc);
             Inkscape::Selection *selection = sp_desktop_selection (ec->desktop);
 
-            //pc->waiting_LPE->acceptParamPath(SP_PATH(selection->singleItem()));
-            //selection->add(SP_OBJECT(pc->waiting_item));
+            pc->waiting_LPE->acceptParamPath(SP_PATH(selection->singleItem()));
+            selection->add(SP_OBJECT(pc->waiting_item));
         }
     }
 
index 49e77e38914365f40b4453e9504ab8f5f853f8f4..3e4e9092405c059a73eb3565341c4b9f8d7eee9c 100644 (file)
@@ -7,6 +7,11 @@
 
 #include "draw-context.h"
 
+namespace Inkscape {
+namespace LivePathEffect {
+class Effect;
+}
+}
 
 #define SP_TYPE_PEN_CONTEXT (sp_pen_context_get_type())
 #define SP_PEN_CONTEXT(o) (G_TYPE_CHECK_INSTANCE_CAST((o), SP_TYPE_PEN_CONTEXT, SPPenContext))
@@ -41,6 +46,8 @@ struct SPPenContext : public SPDrawContext {
     bool polylines_only;
 
     unsigned int expecting_clicks_for_LPE; // if positive, finish the path after this many clicks
+    Inkscape::LivePathEffect::Effect *waiting_LPE;
+    SPLPEItem *waiting_item;
 
     SPCanvasItem *c0, *c1, *cl0, *cl1;
     
index 3bf5a28ee755ff88ec077be3d8d9c5ba8d46e1bc..9013eb863f56a92854688ee950e0a914ec67f7d2 100644 (file)
@@ -286,13 +286,20 @@ void sp_lpe_item_perform_path_effect(SPLPEItem *lpeitem, SPCurve *curve) {
                 return;
             }
 
-            if (lpeobj->lpe->isVisible()) {
+            Inkscape::LivePathEffect::Effect *lpe = lpeobj->lpe;
+            if (lpe->isVisible()) {
+                if (lpe->acceptsNumParams() > 0 && !lpe->pathParamAccepted()) {
+                    // if the effect expects mouse input before being applied and the input is not finished
+                    // yet, we don't alter the path
+                    return;
+                }
+
                 // Groups have their doBeforeEffect called elsewhere
                 if (!SP_IS_GROUP(lpeitem)) {
-                    lpeobj->lpe->doBeforeEffect(lpeitem);
+                    lpe->doBeforeEffect(lpeitem);
                 }
 
-                lpeobj->lpe->doEffect(curve);
+                lpe->doEffect(curve);
             }
         }
     }
@@ -430,13 +437,21 @@ void sp_lpe_item_add_path_effect(SPLPEItem *lpeitem, gchar *value, bool reset)
 
         LivePathEffectObject *lpeobj = lpeitem->path_effect_list->back()->lpeobject;
         if (lpeobj && lpeobj->lpe) {
+            Inkscape::LivePathEffect::Effect *lpe = lpeobj->lpe;
             // Ask the path effect to reset itself if it doesn't have parameters yet
             if (reset) {
                 // has to be called when all the subitems have their lpes applied
-                lpeobj->lpe->resetDefaults(lpeitem);
+                lpe->resetDefaults(lpeitem);
+            }
+
+            // perform this once when the effect is applied 
+            lpe->doOnApply(SP_LPE_ITEM(lpeitem));
+
+            // if the effect expects a number of mouse clicks to set a parameter path, perform the
+            // necessary preparations
+            if (lpe->acceptsNumParams() > 0) {
+                lpe->doAcceptPathPreparations(lpeitem);
             }
-            /* perform this once when the effect is applied */
-            lpeobj->lpe->doOnApply(SP_LPE_ITEM(lpeitem));
         }
 
         //Enable the path effects now that everything is ready to apply the new path effect