diff canvas.d @ 16:9e63308b749c

* Fix up public/private includes * Make Mask a struct
author David Bryant <daveb@acres.com.au>
date Mon, 13 Jul 2009 16:16:17 +0930
parents 2f79aab4d385
children c643c04e3f5e
line wrap: on
line diff
--- a/canvas.d	Sun Jul 12 13:23:06 2009 +0930
+++ b/canvas.d	Mon Jul 13 16:16:17 2009 +0930
@@ -1,34 +1,36 @@
 module canvas;
 
-import std.stdio;
-import std.math;
+public {
+    import icanvas;
+    import tk.geometry;
+    import tk.events;
+}
 
-import cairo.Context;
-import cairo.Surface;
+private {
+    import tk.gtk_support;
+    import tk.misc;
 
-import gdk.Drawable;
+    import cairo.Surface;
+    import cairo_support;
+
+    import std.math;
+    import std.stdio;
 
-import gtk.Widget;
-import gtk.Toolbar;
-import gtk.Table;
-import gtk.HRuler;
-import gtk.VRuler;
-import gtk.Range;
-import gtk.HScrollbar;
-import gtk.VScrollbar;
-import gtk.DrawingArea;
-import gtk.Adjustment;
+    import gtk.Widget;
+    import gtk.Toolbar;
+    import gtk.Table;
+    import gtk.HRuler;
+    import gtk.VRuler;
+    import gtk.Range;
+    import gtk.HScrollbar;
+    import gtk.VScrollbar;
+    import gtk.DrawingArea;
+    import gtk.Adjustment;
 
-import tk.misc;
-import tk.geometry;
-import tk.types;
-import tk.events;
-import tk.gtk_support;
+    import gdk.Drawable;
 
-private import gtkc.gtk;
-
-import icanvas;
-import cairo_support;
+    import gtkc.gtk;
+}
 
 // x and y run right and up respectively
 
@@ -40,22 +42,11 @@
         mEventHandler = event_handler;
         mPPI = ppi;
 
-        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 = layer_bounds.moved(-layer_bounds.size).expanded(2.0 * layer_bounds.size);
-        mViewCentre = mCanvasBounds.centre;
+        /*
+        writefln("Layer bounds: %s", layer_bounds);
+        writefln("Canvas bounds: %s", mCanvasBounds);
+        writefln("View centre: %s", mViewCentre);
+        */
 
         // Create our child widgets and register callbacks
 
@@ -65,7 +56,7 @@
                0, 1,
                AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.SHRINK,
                0, 0);
-        mHRuler.setMetric(GtkMetricType.CENTIMETERS);
+        mHRuler.setMetric(GtkMetricType.PIXELS);
 
         mVRuler = new VRuler;
         attach(mVRuler,
@@ -73,7 +64,7 @@
                1, 2,
                AttachOptions.SHRINK, AttachOptions.FILL | AttachOptions.EXPAND,
                0, 0);
-        mVRuler.setMetric(GtkMetricType.CENTIMETERS);
+        mVRuler.setMetric(GtkMetricType.PIXELS);
 
         mDrawingArea = new DrawingArea;
         mDrawingArea.addOnRealize(&onRealize);
@@ -96,6 +87,7 @@
         mHAdjustment = new Adjustment(0.0, 0.0, 1.0, 0.2, 0.5, 0.5);
         mHAdjustment.addOnValueChanged(&onValueChanged);
         mHScrollbar = new HScrollbar(mHAdjustment);
+        mHScrollbar.setInverted(false);
         attach(mHScrollbar,
                1, 2,
                2, 3,
@@ -105,6 +97,7 @@
         mVAdjustment = new Adjustment(0.0, 0.0, 1.0, 0.2, 0.5, 0.5);
         mVAdjustment.addOnValueChanged(&onValueChanged);
         mVScrollbar = new VScrollbar(mVAdjustment);
+        mVScrollbar.setInverted(true);
         attach(mVScrollbar,
                2, 3,
                1, 2,
@@ -113,26 +106,23 @@
                0, 0);
     }
 
-    override void rel_zoom(Point screen_datum, double factor) {
+    override void rel_zoom(Point pixel_datum, double factor) {
         // Work out pixel distance from current centre to datum,
         // Do the zoom, then work out the new centre that keeps the
         // pixel distance the same
 
-        Point old_model_datum = screen_to_model(screen_datum);
-        Vector pixel_distance = model_to_screen(old_model_datum - mViewCentre);
+        Point old_model_datum = pixel_to_model(pixel_datum);
+        Vector pixel_distance = model_to_pixel(old_model_datum - mViewCentre);
         mZoom = clamp_zoom(factor * mZoom);
-        mViewCentre = old_model_datum - screen_to_model(pixel_distance);
-
-        //Point new_model_datum = screen_to_model(screen_datum);
+        mViewCentre = old_model_datum - pixel_to_model(pixel_distance);
 
         update_adjustments;
-        //update_rulers(new_model_datum);
         update_rulers;
         queueDraw;
     }
 
-    override void rel_pan(Vector screen_displacement) {
-        mViewCentre = mViewCentre + screen_to_model(screen_displacement);
+    override void rel_pan(Vector pixel_displacement) {
+        mViewCentre = mViewCentre + pixel_to_model(pixel_displacement);
 
         update_adjustments;
         update_rulers;
@@ -143,36 +133,36 @@
         return mZoom;
     }
 
-    override Point model_to_screen(Point model) const {
+    override Point model_to_pixel(Point model) const {
         return Point.DEFAULT + mViewSize / 2.0 + mZoom * (model - mViewCentre);
     }
 
-    override Point screen_to_model(Point screen) const {
-        return mViewCentre + (screen - mViewSize / 2.0 - Point.DEFAULT) / mZoom;
+    override Point pixel_to_model(Point pixel) const {
+        return mViewCentre + (pixel - mViewSize / 2.0 - Point.DEFAULT) / mZoom;
     }
 
-    override Vector model_to_screen(Vector model) const {
+    override Vector model_to_pixel(Vector model) const {
         return mZoom * model;
     }
 
-    override Vector screen_to_model(Vector screen) const {
-        return screen / mZoom;
+    override Vector pixel_to_model(Vector pixel) const {
+        return pixel / mZoom;
     }
 
-    override double model_to_screen(double model) const {
+    override double model_to_pixel(double model) const {
         return mZoom * model;
     }
 
-    override double screen_to_model(double screen) const {
-        return screen / mZoom;
+    override double pixel_to_model(double pixel) const {
+        return pixel / mZoom;
     }
 
-    override Rectangle model_to_screen(Rectangle model) const {
-        return Rectangle(model_to_screen(model.position), model_to_screen(model.size));
+    override Rectangle model_to_pixel(Rectangle model) const {
+        return Rectangle(model_to_pixel(model.position), model_to_pixel(model.size));
     }
 
-    override Rectangle screen_to_model(Rectangle model) const {
-        return Rectangle(screen_to_model(model.position), screen_to_model(model.size));
+    override Rectangle pixel_to_model(Rectangle model) const {
+        return Rectangle(pixel_to_model(model.position), pixel_to_model(model.size));
     }
 
     private {
@@ -185,10 +175,34 @@
         bool onConfigure(GdkEventConfigure * event, Widget widget) {
             assert(widget is mDrawingArea);
 
+            if (!mHadConfigure) {
+                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 = layer_bounds.moved(-layer_bounds.size).expanded(2.0 * layer_bounds.size);
+                mViewCentre = mCanvasBounds.centre;
+
+                mHadConfigure = true;
+            }
+
             mViewSize = Vector(cast(double)event.width, cast(double)event.height);
             update_adjustments;
             update_rulers;
 
+            //writefln("Canvas bounds: %s", mCanvasBounds);
+            //writefln("View centre: %s", mViewCentre);
+
             return true;
         }
 
@@ -202,7 +216,7 @@
             //writefln("Got expose %dx%d\n", width, height);
 
             scope model_cr = new Context(dr);
-            scope screen_cr = new Context(dr);
+            scope pixel_cr = new Context(dr);
 
             Rectangle damage =
                 event is null ?
@@ -210,43 +224,43 @@
                 Rectangle(Point(cast(double)event.area.x, cast(double)event.area.y),
                           Vector(cast(double)event.area.width, cast(double)event.area.height));
 
-            model_cr.save; screen_cr.save; {
+            model_cr.save; pixel_cr.save; {
                 // Setup model context
 
                 rectangle(model_cr, damage);
                 model_cr.clip;
 
-                GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct();
-                GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct();
+                GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct;
+                GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct;
 
-                model_cr.translate(mCanvasBounds.min_corner.x - gtk_adjustment_get_value(h_gtkAdjustment),
-                                   mCanvasBounds.min_corner.y - gtk_adjustment_get_value(v_gtkAdjustment));
                 model_cr.scale(mZoom, -mZoom);
+                model_cr.translate(-gtk_adjustment_get_value(h_gtkAdjustment),
+                                   -gtk_adjustment_get_value(v_gtkAdjustment) - gtk_adjustment_get_page_size(v_gtkAdjustment));
 
-                // Setup screen context
+                // Setup pixel context
 
-                screen_cr.translate(0.0, mViewSize.y);
-                screen_cr.scale(1.0, -1.0);
-                rectangle(screen_cr, damage);
-                screen_cr.clip;
+                pixel_cr.translate(0.0, mViewSize.y);
+                pixel_cr.scale(1.0, -1.0);
+                rectangle(pixel_cr, damage);
+                pixel_cr.clip;
 
                 // Fill the background
 
-                screen_cr.save; {
+                pixel_cr.save; {
                     // Make the window light grey
-                    screen_cr.setSourceRgba(1.0, 1.0, 1.0, 0.7);
-                    rectangle(screen_cr, damage);
-                    screen_cr.fill;
-                } screen_cr.restore;
+                    pixel_cr.setSourceRgba(1.0, 1.0, 1.0, 0.7);
+                    rectangle(pixel_cr, damage);
+                    pixel_cr.fill;
+                } pixel_cr.restore;
 
                 // Draw each layer
 
                 foreach(ref layer; mLayers) {
-                    model_cr.save; screen_cr.save; {
-                        layer.draw(this, damage, model_cr, screen_cr);
-                    } screen_cr.restore; model_cr.restore;
+                    model_cr.save; pixel_cr.save; {
+                        layer.draw(this, damage, model_cr, pixel_cr);
+                    } pixel_cr.restore; model_cr.restore;
                 }
-            } screen_cr.restore; model_cr.restore;
+            } pixel_cr.restore; model_cr.restore;
 
             return true;
         }
@@ -255,12 +269,12 @@
             assert(widget is mDrawingArea);
             //writefln("Got button event\n");
 
-            Point screen_point = Point(event.x + 0.5, event.y + 0.5);
-            Point model_point = screen_to_model(screen_point);
+            Point pixel_point = Point(event.x + 0.5, mViewSize.y - (event.y + 0.5));
+            Point model_point = pixel_to_model(pixel_point);
 
             auto button_event = new ButtonEvent(gtk2tk_button_action(event.type),
                                                 gtk2tk_button_name(event.button),
-                                                screen_point,
+                                                pixel_point,
                                                 model_point,
                                                 gtk2tk_mask(event.state));
 
@@ -273,12 +287,12 @@
             assert(widget is mDrawingArea);
             //writefln("Got button event\n");
 
-            Point screen_point = Point(event.x + 0.5, event.y + 0.5);
-            Point model_point = screen_to_model(screen_point);
+            Point pixel_point = Point(event.x + 0.5, mViewSize.y - (event.y + 0.5));
+            Point model_point = pixel_to_model(pixel_point);
 
             auto button_event = new ButtonEvent(gtk2tk_button_action(event.type),
                                                 gtk2tk_button_name(event.button),
-                                                screen_point,
+                                                pixel_point,
                                                 model_point,
                                                 gtk2tk_mask(event.state));
 
@@ -303,10 +317,10 @@
             gtk_widget_event(mHRuler.getWidgetStruct(), cast(GdkEvent *)event);
             gtk_widget_event(mVRuler.getWidgetStruct(), cast(GdkEvent *)event);
 
-            Point screen_point = Point(event.x + 0.5, event.y + 0.5);
-            Point model_point = screen_to_model(screen_point);
+            Point pixel_point = Point(event.x + 0.5, mViewSize.y - (event.y + 0.5));
+            Point model_point = pixel_to_model(pixel_point);
 
-            auto motion_event = new MotionEvent(screen_point,
+            auto motion_event = new MotionEvent(pixel_point,
                                                 model_point,
                                                 gtk2tk_mask(event.state));
 
@@ -319,11 +333,11 @@
             assert(widget is mDrawingArea);
             //writefln("Got scroll\n");
 
-            Point screen_point = Point(event.x + 0.5, event.y + 0.5);
-            Point model_point = screen_to_model(screen_point);
+            Point pixel_point = Point(event.x + 0.5, mViewSize.y - (event.y + 0.5));
+            Point model_point = pixel_to_model(pixel_point);
 
             auto scroll_event = new ScrollEvent(gtk2tk_direction(event.direction),
-                                                screen_point,
+                                                pixel_point,
                                                 model_point,
                                                 gtk2tk_mask(event.state));
 
@@ -336,11 +350,14 @@
             GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct;
             GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct;
 
-            Point view_left_bottom = Point(gtk_adjustment_get_value(h_gtkAdjustment),
-                                           gtk_adjustment_get_value(v_gtkAdjustment));
+            Point view_left_top = Point(gtk_adjustment_get_value(h_gtkAdjustment),
+                                        gtk_adjustment_get_value(v_gtkAdjustment));
+
+            Vector model_size = pixel_to_model(mViewSize);
+
             //writefln("%s", view_left_bottom);
-            Vector model_size = screen_to_model(mViewSize);
-            mViewCentre = view_left_bottom + model_size / 2.0;
+            mViewCentre = view_left_top + model_size / 2.0;
+            writefln("onValueChanged mViewCentre: %s", mViewCentre);
 
             update_rulers;
 
@@ -348,28 +365,32 @@
         }
 
         void update_rulers() {
-            Vector model_size = screen_to_model(mViewSize);
+            Vector model_size = pixel_to_model(mViewSize);
 
             Point view_left_bottom = mViewCentre - model_size / 2.0;
             Point view_right_top = mViewCentre + model_size / 2.0;
 
+            // Define these just to obtain the position
+            // below and we can preserve it
             double lower, upper, position, max_size;
 
+
             mHRuler.getRange(lower, upper, position, max_size);
+            writefln("HRuler: %f %f %f", view_left_bottom.x, view_right_top.x, position);
             mHRuler.setRange(view_left_bottom.x,
                              view_right_top.x,
                              position,
-                             mZoom * 10.0);
+                             mZoom * 50.0);
 
             mVRuler.getRange(lower, upper, position, max_size);
             mVRuler.setRange(view_right_top.y,
                              view_left_bottom.y,
                              position,
-                             mZoom * 10.0);
+                             mZoom * 50.0);
         }
 
         void update_adjustments() {
-            Vector model_size = screen_to_model(mViewSize);
+            Vector model_size = pixel_to_model(mViewSize);
 
             Point view_left_bottom = mViewCentre - model_size / 2.0;
             Point view_right_top = mViewCentre + model_size / 2.0;
@@ -380,11 +401,11 @@
 
             // Update the adjustments
 
-            GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct();
-            GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct();
+            GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct;
+            GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct;
 
             gtk_adjustment_set_lower(h_gtkAdjustment, mCanvasBounds.min_corner.x);
-            gtk_adjustment_set_upper(h_gtkAdjustment, mCanvasBounds.max_corner.y);
+            gtk_adjustment_set_upper(h_gtkAdjustment, mCanvasBounds.max_corner.x);
             gtk_adjustment_set_value(h_gtkAdjustment, view_left_bottom.x);
             gtk_adjustment_set_step_increment(h_gtkAdjustment, mCanvasBounds.size.x / 16.0);
             gtk_adjustment_set_page_increment(h_gtkAdjustment, mCanvasBounds.size.x / 4.0);
@@ -403,15 +424,16 @@
             mVAdjustment.valueChanged;
         }
 
-        double clamp_zoom(double zoom) { return clamp(zoom, 0.02, 50.0); }
+        double clamp_zoom(double zoom) { return clamp(zoom, 0.2, 10.0); }
+
+        bool mHadConfigure;
 
         // Model units are in millimetres
         // Screen units are in pixels
-
         double mZoom;               // pixels-per-model-unit (mm)
+        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:
-        Vector mViewSize;           // screen: size of view window in pixels
 
         // Child widgets:
         HRuler mHRuler;