diff doodle/gtk/canvas.d @ 70:0e61702c6ea6

Checkpoint
author "David Bryant <bagnose@gmail.com>"
date Sat, 14 Aug 2010 20:05:55 +0930
parents d540f7e4af9e
children 0f7cf6c6f206
line wrap: on
line diff
--- a/doodle/gtk/canvas.d	Sat Aug 14 19:39:58 2010 +0930
+++ b/doodle/gtk/canvas.d	Sat Aug 14 20:05:55 2010 +0930
@@ -37,18 +37,6 @@
 }
 
 // x and y run right and up respectively
-//
-// Model units are millimetres.
-//
-// _zoom         -> pixels-per-model-unit
-// _viewSize     -> size of view window in pixels
-// _viewCentre   -> location in model corresponding to centre of view
-// _canvasBounds -> 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
 
 final class Canvas : Table, private IViewport {
     this(in Layer[] layers, IEventHandler eventHandler, IGrid grid, in double pixelsPerMillimetre) {
@@ -213,21 +201,23 @@
 
     private {
 
-        void initialiseBounds() {
-            Rectangle layerBounds = Rectangle.DEFAULT;
+        Rectangle layerBounds() {
+            Rectangle bounds = Rectangle.DEFAULT;
+            foreach (layer; _layers) { bounds = bounds | layer.bounds; }
+            assert(bounds.valid);
+            return bounds;
+        }
 
-            foreach (layer; _layers) {
-                layerBounds = layerBounds | layer.bounds;
-            }
-
-            assert(layerBounds.valid);
+        void initialiseBounds() {
+            Rectangle lb = layerBounds;
 
             // FIXME use a function that grows a rectangle about its centre
             // and change 2.0 to a class-level constant
-            Rectangle paddedLayerBounds = expand(move(layerBounds, - layerBounds.size), 2.0 * layerBounds.size);
+            Rectangle paddedLayerBounds = expand(move(lb, - lb.size), 2.0 * lb.size);
 
             //
 
+            // FIXME 0.25
             _zoom = 0.25 * _pixelsPerMillimetre;       // ie 0.25 pixels represents a millimetre
 
             _canvasBounds = paddedLayerBounds;
@@ -240,18 +230,12 @@
         }
 
         void consolidateBounds() {
-            Rectangle layerBounds = Rectangle.DEFAULT;
-
-            foreach (layer; _layers) {
-                layerBounds = layerBounds | layer.bounds;
-            }
+            Rectangle lb = layerBounds;
 
-            assert(layerBounds.valid);
+            // FIXME likewise as above
+            Rectangle paddedLayerBounds = expand(move(lb, - lb.size), 2.0 * lb.size);
 
-            Rectangle paddedLayerBounds = expand(move(layerBounds, - layerBounds.size), 2.0 * layerBounds.size);
-
-            Vector z = _viewSize / _zoom;
-            Rectangle r = Rectangle(_viewCentre - z / 2.0, z);
+            Rectangle r = pixelToModel(_viewBounds);
             _canvasBounds = r | paddedLayerBounds;
 
             updateAdjustments;
@@ -261,7 +245,7 @@
         bool onConfigure(GdkEventConfigure * event, Widget widget) {
             assert(widget is _drawingArea);
 
-            _viewSize = Vector(cast(double)event.width, cast(double)event.height);
+            _viewBounds = Rectangle(Point(0.0, 0.0), Vector(cast(double)event.width, cast(double)event.height));
 
             if (!_boundsValid) {
                 initialiseBounds;
@@ -288,8 +272,8 @@
 
             Rectangle pixelDamage =
                 event is null ?
-                Rectangle(Point(0.0, 0.0), _viewSize) :
-                Rectangle(Point(cast(double)event.area.x, _viewSize.y - cast(double)(event.area.y + event.area.height)),
+                _viewBounds :       // XXX can we do something nice with the next line?
+                Rectangle(_viewBounds.position + Vector(cast(double)event.area.x, _viewBounds.h - cast(double)(event.area.y + event.area.height)),
                           Vector(cast(double)event.area.width, cast(double)event.area.height));
 
             Rectangle modelDamage = pixelToModel(pixelDamage);
@@ -299,10 +283,11 @@
             modelCr.save; pixelCr.save; {
                 {
                     // Setup model context and clip
-                    modelCr.translate(0.0, _viewSize.y);
+                    modelCr.translate(0.0, _viewBounds.h);
                     modelCr.scale(_zoom, -_zoom);
 
-                    immutable Vector modelSize = pixelToModel(_viewSize);
+                    // XXX revisit
+                    immutable Vector modelSize = pixelToModel(_viewBounds.size);
                     immutable Point viewLeftBottom = _viewCentre - modelSize / 2.0;
                     modelCr.translate(-viewLeftBottom.x, -viewLeftBottom.y);
 
@@ -312,7 +297,7 @@
 
                 {
                     // Setup pixel context and clip
-                    pixelCr.translate(0.0, _viewSize.y);
+                    pixelCr.translate(0.0, _viewBounds.h);
                     pixelCr.scale(1.0, -1.0);
 
                     rectangle(pixelCr, pixelDamage);
@@ -339,7 +324,7 @@
             assert(widget is _drawingArea);
             //trace("Got button event\n");
 
-            Point pixelPoint = Point(event.x + 0.5, _viewSize.y - (event.y + 0.5));
+            Point pixelPoint = Point(event.x + 0.5, _viewBounds.h - (event.y + 0.5));
             Point modelPoint = pixelToModel(pixelPoint);
 
             auto buttonEvent = new ButtonEvent(gtk2tkButtonAction(event.type),
@@ -358,7 +343,7 @@
         bool onButtonRelease(GdkEventButton * event, Widget widget) {
             assert(widget is _drawingArea);
 
-            Point pixelPoint = Point(event.x + 0.5, _viewSize.y - (event.y + 0.5));
+            Point pixelPoint = Point(event.x + 0.5, _viewBounds.h - (event.y + 0.5));
             Point modelPoint = pixelToModel(pixelPoint);
 
             auto buttonEvent = new ButtonEvent(gtk2tkButtonAction(event.type),
@@ -424,7 +409,7 @@
             gtk_widget_event(_hRuler.getWidgetStruct(), cast(GdkEvent *)event);
             gtk_widget_event(_vRuler.getWidgetStruct(), cast(GdkEvent *)event);
 
-            Point pixelPoint = Point(event.x + 0.5, _viewSize.y - (event.y + 0.5));
+            Point pixelPoint = Point(event.x + 0.5, _viewBounds.h - (event.y + 0.5));
             Point modelPoint = pixelToModel(pixelPoint);
 
             auto motionEvent = new MotionEvent(pixelPoint,
@@ -442,7 +427,7 @@
             assert(widget is _drawingArea);
             //writefln("Got scroll\n");
 
-            Point pixelPoint = Point(event.x + 0.5, _viewSize.y - (event.y + 0.5));
+            Point pixelPoint = Point(event.x + 0.5, _viewBounds.h - (event.y + 0.5));
             Point modelPoint = pixelToModel(pixelPoint);
 
             auto scrollEvent = new ScrollEvent(gtk2tkDirection(event.direction),
@@ -487,7 +472,7 @@
         bool onEnterNotify(GdkEventCrossing * event, Widget widget) {
             assert(widget is _drawingArea);
 
-            Point pixelPoint = Point(event.x + 0.5, _viewSize.y - (event.y + 0.5));
+            Point pixelPoint = Point(event.x + 0.5, _viewBounds.h - (event.y + 0.5));
             Point modelPoint = pixelToModel(pixelPoint);
 
             auto crossingEvent = new CrossingEvent(gtk2tkCrossingMode(event.mode),
@@ -507,7 +492,7 @@
         bool onLeaveNotify(GdkEventCrossing * event, Widget widget) {
             assert(widget is _drawingArea);
 
-            Point pixelPoint = Point(event.x + 0.5, _viewSize.y - (event.y + 0.5));
+            Point pixelPoint = Point(event.x + 0.5, _viewBounds.h - (event.y + 0.5));
             Point modelPoint = pixelToModel(pixelPoint);
 
             auto crossingEvent = new CrossingEvent(gtk2tkCrossingMode(event.mode),
@@ -566,7 +551,7 @@
             Point viewLeftBottom = Point(gtk_adjustment_get_value(hGtkAdjustment),
                                          gtk_adjustment_get_value(vGtkAdjustment));
 
-            Vector modelSize = pixelToModel(_viewSize);
+            Vector modelSize = pixelToModel(_viewBounds.size);      // XXX
 
             _viewCentre = viewLeftBottom + modelSize / 2.0;
 
@@ -575,7 +560,7 @@
         }
 
         void updateRulers() {
-            immutable Vector modelSize = pixelToModel(_viewSize);
+            immutable Vector modelSize = pixelToModel(_viewBounds.size);        // XXX
             immutable Point viewLeftBottom = _viewCentre - modelSize / 2.0;
             immutable Point viewRightTop = _viewCentre + modelSize / 2.0;
 
@@ -597,28 +582,28 @@
         }
 
         void updateAdjustments() {
-            immutable Vector modelSize = pixelToModel(_viewSize);
+            immutable Vector modelSize = pixelToModel(_viewBounds.size);        // XXX
             immutable Point viewLeftBottom = _viewCentre - modelSize / 2.0;
             immutable Point viewRightTop = _viewCentre + modelSize / 2.0;
 
             // Adjust the canvas size if necessary
-            _canvasBounds = Rectangle(minExtents(_canvasBounds.minCorner, viewLeftBottom),
-                                      maxExtents(_canvasBounds.maxCorner, viewRightTop));
+            _canvasBounds = Rectangle(minExtents(_canvasBounds.corner0, viewLeftBottom),
+                                      maxExtents(_canvasBounds.corner1, viewRightTop));
 
             // Update the adjustments
 
             GtkAdjustment * hGtkAdjustment = _hAdjustment.getAdjustmentStruct;
             GtkAdjustment * vGtkAdjustment = _vAdjustment.getAdjustmentStruct;
 
-            gtk_adjustment_set_lower(hGtkAdjustment, _canvasBounds.minCorner.x);
-            gtk_adjustment_set_upper(hGtkAdjustment, _canvasBounds.maxCorner.x);
+            gtk_adjustment_set_lower(hGtkAdjustment, _canvasBounds.corner0.x);
+            gtk_adjustment_set_upper(hGtkAdjustment, _canvasBounds.corner1.x);
             gtk_adjustment_set_value(hGtkAdjustment, viewLeftBottom.x);
             gtk_adjustment_set_step_increment(hGtkAdjustment, _canvasBounds.size.x / 16.0);
             gtk_adjustment_set_page_increment(hGtkAdjustment, _canvasBounds.size.x / 4.0);
             gtk_adjustment_set_page_size(hGtkAdjustment, modelSize.x);
 
-            gtk_adjustment_set_lower(vGtkAdjustment, _canvasBounds.minCorner.y);
-            gtk_adjustment_set_upper(vGtkAdjustment, _canvasBounds.maxCorner.y);
+            gtk_adjustment_set_lower(vGtkAdjustment, _canvasBounds.corner0.y);
+            gtk_adjustment_set_upper(vGtkAdjustment, _canvasBounds.corner1.y);
             gtk_adjustment_set_value(vGtkAdjustment, viewLeftBottom.y);
             gtk_adjustment_set_step_increment(vGtkAdjustment, _canvasBounds.size.y / 16.0);
             gtk_adjustment_set_page_increment(vGtkAdjustment, _canvasBounds.size.y / 4.0);
@@ -634,7 +619,7 @@
             if (_damage.valid) {
                 int x, y, w, h;
                 _damage.getQuantised(x, y, w, h);
-                _drawingArea.queueDrawArea(x, cast(int)_viewSize.y - (y + h), w, h);
+                _drawingArea.queueDrawArea(x, cast(int)_viewBounds.h - (y + h), w, h);
                 _damage = Rectangle.DEFAULT;
             }
         }
@@ -642,11 +627,11 @@
         static double clampZoom(in double zoom) { return clamp(zoom, 0.2, 10.0); }
 
         Point modelToPixel(in Point model) const {
-            return Point.DEFAULT + _viewSize / 2.0 + _zoom * (model - _viewCentre);
+            return _viewBounds.centre + _zoom * (model - _viewCentre);
         }
 
         Point pixelToModel(in Point pixel) const {
-            return _viewCentre + (pixel - _viewSize / 2.0 - Point.DEFAULT) / _zoom;
+            return _viewCentre + (pixel - _viewBounds.centre) / _zoom;
         }
 
         Vector modelToPixel(in Vector model) const {
@@ -677,9 +662,9 @@
         // Model units are millimetres
         // Screen units are pixels
         double _zoom;               // pixels-per-model-unit
-        Vector _viewSize;           // pixel: size of view window in pixels
+        Rectangle _viewBounds;      // pixel: bounds of the viewport in pixels
         Point _viewCentre;          // model: where in the model is the centre of our view
-        Rectangle _canvasBounds;    // model:
+        Rectangle _canvasBounds;    // model: bounds of the canvas in millimetres
 
         // Child widgets:
         HRuler _hRuler;