Code

add touchpath mode
authorbuliabyak <buliabyak@users.sourceforge.net>
Thu, 12 Apr 2007 07:20:37 +0000 (07:20 +0000)
committerbuliabyak <buliabyak@users.sourceforge.net>
Thu, 12 Apr 2007 07:20:37 +0000 (07:20 +0000)
src/rubberband.cpp
src/rubberband.h

index 0de3cd763a7dd99b8a98b49014b2947b060b2c80..a1621237980e38c64807f7856c919bdd936472ea 100644 (file)
 #include "inkscape.h"
 #include "desktop-handles.h"
 #include "rubberband.h"
+#include "display/canvas-bpath.h"
+#include "display/curve.h"
+#include "libnr/nr-point.h"
 
 Inkscape::Rubberband *Inkscape::Rubberband::_instance = NULL;
 
 Inkscape::Rubberband::Rubberband()
-    : _desktop(SP_ACTIVE_DESKTOP), _canvas(NULL), _started(false)
+    : _desktop(SP_ACTIVE_DESKTOP), _rect(NULL), _touchpath(NULL), _started(false)
 {
+    _points.clear();
+    _mode = RUBBERBAND_MODE_RECT;
+    _touchpath_curve = sp_curve_new_sized(2000);
+}
 
+void Inkscape::Rubberband::delete_canvas_items()
+{
+    if (_rect) {
+        GtkObject *temp = _rect;
+        _rect = NULL;
+        gtk_object_destroy(temp);
+    }
+    if (_touchpath) {
+        GtkObject *temp = _touchpath;
+        _touchpath = NULL;
+        gtk_object_destroy(temp);
+    }
 }
 
+
 void Inkscape::Rubberband::start(SPDesktop *d, NR::Point const &p)
 {
-    stop();
+    _points.clear();
+    sp_curve_reset(_touchpath_curve);
+    delete_canvas_items();
     _desktop = d;
     _start = p;
     _started = true;
+    _points.push_back(_desktop->d2w(p));
+    sp_curve_moveto(_touchpath_curve, p);
 
     sp_canvas_force_full_redraw_after_interruptions(_desktop->canvas, 5);
 }
@@ -39,30 +63,71 @@ void Inkscape::Rubberband::start(SPDesktop *d, NR::Point const &p)
 void Inkscape::Rubberband::stop()
 {
     _started = false;
+    _mode = RUBBERBAND_MODE_RECT; // restore the default
 
-    if (_canvas) {
-        GtkObject *temp = _canvas;
-        _canvas = NULL;
-        gtk_object_destroy(temp);
-        sp_canvas_end_forced_full_redraws(_desktop->canvas);
-    }
+    _points.clear();
+    sp_curve_reset(_touchpath_curve);
+
+    delete_canvas_items();
+
+    sp_canvas_end_forced_full_redraws(_desktop->canvas);
 }
 
 void Inkscape::Rubberband::move(NR::Point const &p)
 {
-    if (_canvas == NULL) {
-        _canvas = static_cast<CtrlRect *>(sp_canvas_item_new(sp_desktop_controls(_desktop), SP_TYPE_CTRLRECT, NULL));
-    }
+    if (!_started) 
+        return;
 
-    _desktop->scroll_to_point(&p);
     _end = p;
+    _desktop->scroll_to_point(&p);
+    sp_curve_lineto (_touchpath_curve, p);
+
+    NR::Point next = _desktop->d2w(p);
+    // we want the points to be at most 0.5 screen pixels apart,
+    // so that we don't lose anything small;
+    // if they are farther apart, we interpolate more points
+    if (_points.size() > 0 && NR::L2(next-_points.back()) > 0.5) {
+        NR::Point prev = _points.back();
+        int subdiv = 2 * (int) round(NR::L2(next-prev) + 0.5);
+        for (int i = 1; i <= subdiv; i ++) {
+            _points.push_back(prev + ((double)i/subdiv) * (next - prev));
+        }
+    } else {
+        _points.push_back(next);
+    }
 
-    _canvas->setRectangle(NR::Rect(_start, _end));
+    if (_mode == RUBBERBAND_MODE_RECT) {
+        if (_rect == NULL) {
+            _rect = static_cast<CtrlRect *>(sp_canvas_item_new(sp_desktop_controls(_desktop), SP_TYPE_CTRLRECT, NULL));
+        }
+        _rect->setRectangle(NR::Rect(_start, _end));
+
+        sp_canvas_item_show(_rect);
+        if (_touchpath)
+            sp_canvas_item_hide(_touchpath);
+
+    } else if (_mode == RUBBERBAND_MODE_TOUCHPATH) {
+        if (_touchpath == NULL) {
+            _touchpath = sp_canvas_bpath_new(sp_desktop_sketch(_desktop), NULL);
+            sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(_touchpath), 0xff0000ff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
+            sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(_touchpath), 0, SP_WIND_RULE_NONZERO);
+        }
+        sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(_touchpath), _touchpath_curve);
+
+        sp_canvas_item_show(_touchpath);
+        if (_rect)
+            sp_canvas_item_hide(_rect);
+    }
+}
+
+void Inkscape::Rubberband::setMode(int mode) 
+{
+    _mode = mode;
 }
 
 NR::Maybe<NR::Rect> Inkscape::Rubberband::getRectangle() const
 {
-    if (_canvas == NULL) {
+    if (!_started) {
         return NR::Nothing();
     }
 
index 36e9c4d8ec6e89e62c23525ae53769160cf3d4bd..b6ef1984eec6a32fb5efe9d8a1211fb02d3e51aa 100644 (file)
 #include "libnr/nr-forward.h"
 #include "libnr/nr-point.h"
 #include "libnr/nr-maybe.h"
+#include <vector>
 
 /* fixme: do multidocument safe */
 
 class CtrlRect;
+class SPCanvasItem;
+class SPCurve;
+
+enum {
+    RUBBERBAND_MODE_RECT,
+    RUBBERBAND_MODE_TOUCHPATH
+};
 
 namespace Inkscape
 {
@@ -36,6 +44,11 @@ public:
     void stop();
     bool is_started();
 
+    inline int getMode() {return _mode;}
+    inline std::vector<NR::Point> getPoints() {return _points;}
+
+    void setMode(int mode);
+
     static Rubberband* get();
 
 private:
@@ -46,8 +59,17 @@ private:
     SPDesktop *_desktop;
     NR::Point _start;
     NR::Point _end;
-    CtrlRect *_canvas;
+
+    std::vector<NR::Point> _points;
+
+    CtrlRect *_rect;
+    SPCanvasItem *_touchpath;
+    SPCurve *_touchpath_curve;
+
+    void delete_canvas_items();
+
     bool _started;
+    int _mode;
 };
 
 }