changeset 41:f2e4e1d29b98

Bah
author daveb
date Tue, 01 Jun 2010 17:21:01 +0930
parents 1f97022e5c6d
children 3c1b0c4d5847
files doodle/dia/grid_layer.d doodle/dia/icanvas.d doodle/dia/page_layer.d doodle/gtk/canvas.d doodle/tk/geometry.d
diffstat 5 files changed, 87 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/doodle/dia/grid_layer.d	Mon Apr 12 14:01:54 2010 +0930
+++ b/doodle/dia/grid_layer.d	Tue Jun 01 17:21:01 2010 +0930
@@ -47,11 +47,9 @@
             {
                 // vertical grid lines
                 double x = start(model_damage.min_corner.x, mSpacing);
-                double y0 = model_damage.min_corner.y;
-                double y1 = model_damage.max_corner.y;
 
                 for (;;) {
-                    vline(model_cr, x, y0, y1);
+                    vline(model_cr, x, model_damage.min_corner.y, model_damage.max_corner.y);
 
                     // Ensure 1 pixel wide FIXME is this naughty? We are sneaking
                     // through cairo to mix model and pixel coordinates...
@@ -71,12 +69,11 @@
             {
                 // horizontal grid lines
                 double y = start(model_damage.min_corner.y, mSpacing);
-                double x0 = model_damage.min_corner.x;
-                double x1 = model_damage.max_corner.x;
 
                 for (;;) {
-                    hline(model_cr, y, x0, x1);
+                    hline(model_cr, y, model_damage.min_corner.x, model_damage.max_corner.x);
 
+                    // FIXME?
                     model_cr.save(); {
                         model_cr.scale(1.0 / xx, 1.0 / yy);
                         model_cr.stroke();
@@ -99,7 +96,7 @@
         mZoomValid = true;
 
         // FIXME compute spacing properly
-        mSpacing = 10.0 / mZoom;        // mm
+        mSpacing = 20.0 / mZoom;        // mm
     }
 
     // FIXME use inout parameter?
--- a/doodle/dia/icanvas.d	Mon Apr 12 14:01:54 2010 +0930
+++ b/doodle/dia/icanvas.d	Tue Jun 01 17:21:01 2010 +0930
@@ -62,7 +62,7 @@
 
 abstract class Layer {
     this(in string name) {
-        mName = name;
+        mName = name.idup;
     }
 
     string name() const { return mName; }
--- a/doodle/dia/page_layer.d	Mon Apr 12 14:01:54 2010 +0930
+++ b/doodle/dia/page_layer.d	Tue Jun 01 17:21:01 2010 +0930
@@ -27,16 +27,16 @@
         // Make the paper white, with a border
 
         model_cr.save; {
+            model_cr.setSourceRgba(0.0, 0.0, 0.0, 1.0);
+            rectangle(model_cr, mPageGeometry);
+            model_cr.stroke;
+        } model_cr.restore;
+
+        model_cr.save; {
             model_cr.setSourceRgba(1.0, 1.0, 1.0, 1.0);
             rectangle(model_cr, mPageGeometry);
             model_cr.fill;
         } model_cr.restore;
-
-        model_cr.save; {
-            model_cr.setSourceRgba(0.0, 0.0, 0.0, 1.0);
-            rectangle(model_cr, mPageGeometry);
-            model_cr.stroke;
-        } model_cr.restore;
     }
 
     // Page overrides:
--- a/doodle/gtk/canvas.d	Mon Apr 12 14:01:54 2010 +0930
+++ b/doodle/gtk/canvas.d	Tue Jun 01 17:21:01 2010 +0930
@@ -33,6 +33,18 @@
 }
 
 // x and y run right and up respectively
+//
+// Model units are millimetres.
+//
+// mZoom         -> pixels-per-model-unit
+// mViewSize     -> size of view window in pixels
+// mViewCentre   -> location in model corresponding to centre of view
+// mCanvasBounds -> size of the virtual canvas in model coordinates
+//
+// User operations:
+//   pan (middle click and drag)
+//   zoom about a point (hold control and move scroll wheel)
+//   resize the widget
 
 class Canvas : Table, Viewport {
     this(in Layer[] layers, EventHandler event_handler, Grid grid, in double ppi) {
@@ -184,33 +196,46 @@
 
     private {
 
+        void update_bounds() {
+        }
+
+
         bool on_configure(GdkEventConfigure * event, Widget widget) {
             assert(widget is mDrawingArea);
 
+            mViewSize = Vector(cast(double)event.width, cast(double)event.height);
+
+            Rectangle layer_bounds = Rectangle.DEFAULT;
+
+            foreach (ref layer; mLayers) {
+                layer_bounds = layer_bounds | layer.bounds;
+            }
+
+            assert(layer_bounds.valid);
+
+            Rectangle padded_layer_bounds = expand(move(layer_bounds, - layer_bounds.size), 2.0 * layer_bounds.size);
+
             if (!mHadConfigure) {
+                info("1");
                 const double MM_PER_INCH = 25.4;
                 mZoom = 0.25 * mPPI / MM_PER_INCH;
 
-                // Take the union of the bounds of each layer to
-                // determine the canvas size
-
-                Rectangle layer_bounds = Rectangle.DEFAULT;
-
-                foreach (ref layer; mLayers) {
-                    layer_bounds = layer_bounds | layer.bounds;
-                }
-
-                assert(layer_bounds.valid);
-
-                mCanvasBounds = expand(move(layer_bounds, -layer_bounds.size), 2.0 * layer_bounds.size);
+                mCanvasBounds = padded_layer_bounds;
                 mViewCentre = mCanvasBounds.centre;
 
                 mGrid.zoom_changed(mZoom);
 
                 mHadConfigure = true;
             }
+            else {
+                // Use configure events as an opportunity
+                // to consolidate the canvas-bounds
+                // XXX nasty code.
+                Vector z = mViewSize / mZoom;
+                Rectangle r = Rectangle(mViewCentre - z / 2.0, z);
+                mCanvasBounds = r | padded_layer_bounds;
+            }
 
-            mViewSize = Vector(cast(double)event.width, cast(double)event.height);
             update_adjustments;
             update_rulers;
 
@@ -267,7 +292,7 @@
 
                 pixel_cr.save; {
                     // Make the window light grey
-                    pixel_cr.setSourceRgba(0.6, 0.6, 0.6, 1.0);
+                    pixel_cr.setSourceRgba(0.9, 0.9, 0.9, 1.0);
                     rectangle(pixel_cr, pixel_damage);
                     pixel_cr.fill;
                 } pixel_cr.restore;
@@ -299,7 +324,7 @@
 
             mEventHandler.handle_button_press(this, button_event);
 
-            process_damage;
+            fix_damage;
 
             return true;
         }
@@ -319,7 +344,7 @@
 
             mEventHandler.handle_button_release(this, button_event);
 
-            process_damage;
+            fix_damage;
 
             return true;
         }
@@ -331,7 +356,7 @@
             //auto key_event = new KeyEvent("",
             // mEventHandle.handle_key(key_event);
 
-            process_damage;
+            fix_damage;
 
             return true;
         }
@@ -351,7 +376,7 @@
 
             mEventHandler.handle_motion(this, motion_event);
 
-            process_damage;
+            fix_damage;
 
             return true;
         }
@@ -370,7 +395,7 @@
 
             mEventHandler.handle_scroll(this, scroll_event);
 
-            process_damage;
+            fix_damage;
 
             return true;
         }
@@ -492,7 +517,7 @@
             mVAdjustment.valueChanged;
         }
 
-        void process_damage() {
+        void fix_damage() {
             if (mDamage.valid) {
                 //writefln("Damage: %s", mDamage);
                 int x, y, w, h;
@@ -541,7 +566,7 @@
 
         // Model units are in millimetres
         // Screen units are in pixels
-        double mZoom;               // pixels-per-model-unit (mm)
+        double mZoom;               // pixels-per-model-unit
         Vector mViewSize;           // pixel: size of view window in pixels
         Point mViewCentre;          // model: where in the model is the centre of our view
         Rectangle mCanvasBounds;    // model:
--- a/doodle/tk/geometry.d	Mon Apr 12 14:01:54 2010 +0930
+++ b/doodle/tk/geometry.d	Tue Jun 01 17:21:01 2010 +0930
@@ -4,6 +4,7 @@
     import std.stdio;
     import std.math;
     import doodle.tk.misc;
+    import doodle.core.logging;
 }
 
 // In doodle x and y increase right/east and up/north respectively.
@@ -30,6 +31,8 @@
     }
 
     this(in double x, in double y) {
+        assert(!isnan(x));
+        assert(!isnan(y));
         _x = x;
         _y = y;
     }
@@ -78,6 +81,8 @@
     }
 
     this(in double x, in double y) {
+        assert(!isnan(x));
+        assert(!isnan(y));
         _x = x;
         _y = y;
     }
@@ -95,10 +100,12 @@
     }
 
     Vector opMul_r(in double d) const {
+        assert(!isnan(d));
         return Vector(d * _x, d * _y);
     }
 
     Vector opDiv(in double d) const {
+        assert(!isnan(d));
         return Vector(_x / d, _y / d);
     }
 
@@ -164,7 +171,7 @@
 
     Point max_corner() const { return _position + _size; }
 
-    bool valid() const { return _size.x > 0.0 & _size.y > 0.0; }
+    bool valid() const { return _size.x > 0.0 && _size.y > 0.0; }
 
     bool invalid() const { return !valid(); }
 
@@ -245,6 +252,10 @@
     return Rectangle(new_position, r.size);
 }
 
+Rectangle resize(in Rectangle r, in Vector new_size) {
+    return Rectangle(r.position, new_size);
+}
+
 // Operations about the bottom left corner
 
 Rectangle expand(in Rectangle r, in Vector expand_amount) {
@@ -259,19 +270,23 @@
 
 Rectangle feather(in Rectangle r, double amount) {
     assert(amount >= 0.0);
+    assert(!isnan(amount));
     return Rectangle(Point(r.position.x - amount, r.position.y - amount),
                      Vector(r.size.x + 2.0 * amount, r.size.y + 2.0 * amount));
 }
 
-Rectangle resize(in Rectangle r, in Vector new_size) {
-    return Rectangle(r.position, new_size);
-}
-
 private {
-    // This is a commmon building block for intersection of lines and segments
-    // Two lines "a" and "b" are defined by two points each .
-    // "ua" and "ub" define the intersection as a fraction along
-    // the two respective line segments (FIXME this comment sucks)
+    // This function computes the intersection of two lines.
+    // The lines are defined by a start point and an end point, however they
+    // notionally extend infinitely in each direction.
+    // The out parameters specify the fraction along the line-segment at which
+    // intersection occurred.
+    //
+    // This is a commmon building block for computing intersection between lines, segments,
+    // rectangles, etc.
+    //
+    // The function returns false if the lines are parallel or nearly so.
+    //
     // Influenced by http://ozviz.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
     bool compute_intersection(in Point pa1, in Point pa2, out double ua,
                               in Point pb1, in Point pb2, out double ub) {
@@ -279,7 +294,7 @@
 
         if (abs(den) < 1e-9) {          // TODO consolidate constants used for numerical stability
             // Lines are parallel or nearly so
-            writefln("Warning, parallel lines!");
+            warning("Warning, parallel lines!");
             return false;
         }
         else {
@@ -293,6 +308,11 @@
             return true;
         }
     }
+
+    /+
+    double compute_angle(in Point p1, in Point p2) {
+    }
+    +/
 }
 
 //