diff canvas.d @ 11:fb571a3b1f0d

Checkpoint
author "David Bryant <bagnose@gmail.com>"
date Sat, 11 Jul 2009 23:32:22 +0930
parents 71ca82e0eb76
children a093c4fbdd43
line wrap: on
line diff
--- a/canvas.d	Sat Jul 11 22:49:41 2009 +0930
+++ b/canvas.d	Sat Jul 11 23:32:22 2009 +0930
@@ -33,26 +33,24 @@
 // x and y run right and up respectively
 
 class Canvas : Table, Viewport {
-    static this() {
-        ORIGIN = Point(0.0, 0.0);
-        INITIAL_PAGE_SIZE = Vector(210.0, 297.0);       // A4
-    }
-
-    this(EventHandler event_handler) {
+    this(in Layer[] layers, EventHandler event_handler, in double ppi) {
         super(3, 3, 0);
 
+        mLayers = layers.dup;
         mEventHandler = event_handler;
 
-        const double PPI = 120.0;
         const double MM_PER_INCH = 25.4;
-        mZoom = 0.25 * PPI / MM_PER_INCH;
+        mZoom = 0.25 * ppi / MM_PER_INCH;
+
+        Rectangle total_layer_bounds;
 
-        mPageLeftBottom = ORIGIN;
-        mPageRightTop = ORIGIN + INITIAL_PAGE_SIZE;
-        mViewCentre = ORIGIN + INITIAL_PAGE_SIZE / 2.0;
+        foreach (ref layer; mLayers) {
+            total_layer_bounds = total_layer_bounds | layer.bounds;
+        }
 
-        mCanvasLeftBottom = mPageLeftBottom - 3.0 * INITIAL_PAGE_SIZE;
-        mCanvasRightTop = mPageRightTop + 3.0 * INITIAL_PAGE_SIZE;
+        mCanvasLeftBottom = total_layer_bounds.min_corner - total_layer_bounds.size;
+        mCanvasRightTop = total_layer_bounds.max_corner + total_layer_bounds.size;
+        mViewCentre = mCanvasLeftBottom + (mCanvasRightTop - mCanvasLeftBottom) / 2.0;
 
         mHRuler = new HRuler();
         attach(mHRuler,
@@ -134,12 +132,15 @@
         queueDraw();
     }
 
-    override Point model_to_screen(Point model) const { return ORIGIN + mViewSize / 2.0 + mZoom * (model - mViewCentre); }
-    override Point screen_to_model(Point screen) const { return mViewCentre + (screen - mViewSize / 2.0 - ORIGIN) / mZoom; }
+    override double zoom() const { return mZoom; }
+    override Point model_to_screen(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 Vector model_to_screen(Vector model) const { return mZoom * model; }
     override Vector screen_to_model(Vector screen) const { return screen / mZoom; }
     override double model_to_screen(double model) const { return mZoom * model; }
     override double screen_to_model(double screen) const { return screen / mZoom; }
+    override Rectangle model_to_screen(Rectangle model) const { return Rectangle(model_to_screen(model.position), model_to_screen(model.size)); }
+    override Rectangle screen_to_model(Rectangle model) const { return Rectangle(screen_to_model(model.position), screen_to_model(model.size)); }
 
     private {
 
@@ -169,36 +170,27 @@
             //writefln("Got expose %dx%d\n", width, height);
 
             scope cr = new Context(dr);
+            Rectangle damage =
+                event is null ?
+                Rectangle(Point(0.0, 0.0), Vector(cast(double)width, cast(double)height)) :
+                Rectangle(Point(cast(double)event.area.x, cast(double)event.area.y),
+                          Vector(cast(double)event.area.width, cast(double)event.area.height));
 
-            if (event) {
-                cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height);
+            cr.save(); {
+                rectangle(cr, damage);
                 cr.clip();
-            }
 
-            // Make the window light grey
-            cr.setSourceRgba(1.0, 1.0, 1.0, 0.7);
-            if (event) {
-                cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height);
-            }
-            else {
-                cr.rectangle(0.0, 0.0, width, height);
-            }
-            cr.fill();
+                cr.save(); {
+                    // Make the window light grey
+                    cr.setSourceRgba(1.0, 1.0, 1.0, 0.7);
+                    rectangle(cr, damage);
+                    cr.fill();
+                } cr.restore();
 
-            {
-                // Make the paper white, with a border
-
-                Point screen_page_left_bottom = model_to_screen(mPageLeftBottom);
-                Point screen_page_right_top = model_to_screen(mPageRightTop);
-
-                cr.setSourceRgba(1.0, 1.0, 1.0, 1.0);
-                draw_rectangle(cr, Rectangle(screen_page_left_bottom, screen_page_right_top));
-                cr.fill();
-
-                cr.setSourceRgba(0.0, 0.0, 0.0, 1.0);
-                draw_rectangle(cr, Rectangle(screen_page_left_bottom, screen_page_right_top));
-                cr.stroke();
-            }
+                foreach(ref layer; mLayers) {
+                    layer.draw(this, damage, cr);
+                }
+            } cr.restore();
 
             return true;
         }
@@ -355,15 +347,12 @@
 
         double clamp_zoom(double zoom) { return clamp(zoom, 0.02, 50.0); }
 
-        static const Point ORIGIN;
-        static const Vector INITIAL_PAGE_SIZE;
-
         EventHandler mEventHandler;
 
         // Model units are in millimetres
         // Screen units are in pixels
 
-        double mZoom;               // pixels-per-mm
+        double mZoom;               // pixels-per-model-unit (mm)
         Point mViewCentre;          // model: where in the model is the centre of our view
 
         Point mCanvasLeftBottom;    // model: bottom left corner of canvas
@@ -381,5 +370,8 @@
         HScrollbar mHScrollbar;
         Adjustment mVAdjustment;
         VScrollbar mVScrollbar;
+
+        // Layers:
+        Layer[] mLayers;
     }
 }