comparison doodle/tk/pixel_model.d @ 71:0f7cf6c6f206

Reimplemented gtk.canvas in terms of tk.pixel_model but needs a lot of consolidation.
author "David Bryant <bagnose@gmail.com>"
date Sat, 14 Aug 2010 20:48:41 +0930
parents 0e61702c6ea6
children 5cc2de64f6d0
comparison
equal deleted inserted replaced
70:0e61702c6ea6 71:0f7cf6c6f206
2 2
3 public { 3 public {
4 import doodle.tk.geometry; 4 import doodle.tk.geometry;
5 } 5 }
6 6
7 private {
8 import doodle.core.misc;
9 }
10
7 // FIXME consider using the term Screen instead of Pixel... 11 // FIXME consider using the term Screen instead of Pixel...
12
13 // This class manages the relationship between pixel space and model space.
14 // It provides convenient high-level operations.
15 //
16 // x and y run right and up respectively for pixel and model space
8 17
9 class PixelModel { 18 class PixelModel {
10 this(in double zoom, in Rectangle canvasBounds, in Rectangle viewBounds) { 19 this(in double zoom, in Rectangle canvasBounds, in Rectangle viewBounds) {
11 _zoom = zoom; 20 _zoom = zoom;
12 _viewBounds = viewBounds; 21 _viewBounds = viewBounds;
13 _canvasBounds = canvasBounds; 22 _canvasBounds = canvasBounds;
14 23
24 // Choose the centre of the canvas as the centre of the view
15 _viewCentre = _canvasBounds.centre; 25 _viewCentre = _canvasBounds.centre;
16 } 26 }
17 27
18 void consolidateCanvasBounds(in Rectangle requiredCanvasBounds) { 28 void consolidateCanvasBounds(in Rectangle requiredCanvasBounds) {
19 Rectangle r = pixelToModel(_viewBounds); 29 Rectangle r = pixelToModel(_viewBounds);
20 _canvasBounds = r | requiredCanvasBounds; 30 _canvasBounds = r | requiredCanvasBounds;
21 } 31 }
22 32
33 void canvasAccommodate(in Rectangle bounds) {
34 _canvasBounds = _canvasBounds | bounds;
35 }
36
37 void zoomRelative(in double factor, in Point pixelDatum) {
38 // Work out pixel distance from current centre to datum,
39 // Do the zoom, then work out the new centre that keeps the
40 // pixel distance the same
41
42 Point oldModelDatum = pixelToModel(pixelDatum);
43 Vector pixelDistance = modelToPixel(oldModelDatum - _viewCentre);
44 _zoom = clampZoom(zoom * factor);
45 _viewCentre = oldModelDatum - pixelToModel(pixelDistance);
46 }
47
48 void panRelativePixel(in Vector pixelDisplacement) {
49 _viewCentre = _viewCentre + pixelToModel(pixelDisplacement);
50 }
51
52 void panRelativeModel(in Vector modelDisplacement) {
53 _viewCentre = _viewCentre + modelDisplacement;
54 }
55
23 // For normalZoom 1.0 -> 100% means the presentation on the screen is 56 // For normalZoom 1.0 -> 100% means the presentation on the screen is
24 // one-to-one with real-life 57 // one-to-one with real-life
25 double normalZoom(in double pixelsPerMillimetre) { return _zoom / pixelsPerMillimetre; } 58 double normalZoom(in double pixelsPerMillimetre) const { return _zoom / pixelsPerMillimetre; }
59 double zoom() const { return _zoom; }
60 Rectangle viewBounds() const { return _viewBounds; }
61 Rectangle canvasBounds() const { return _canvasBounds; }
26 62
27 Point modelToPixel(in Point model) const { return _viewBounds.centre + _zoom * (model - _viewCentre); } 63 Point modelToPixel(in Point model) const { return _viewBounds.centre + _zoom * (model - _viewCentre); }
28 Point pixelToModel(in Point pixel) const { return _viewCentre + (pixel - _viewBounds.centre) / _zoom; } 64 Point pixelToModel(in Point pixel) const { return _viewCentre + (pixel - _viewBounds.centre) / _zoom; }
29 Vector modelToPixel(in Vector model) const { return _zoom * model; } 65 Vector modelToPixel(in Vector model) const { return _zoom * model; }
30 Vector pixelToModel(in Vector pixel) const { return pixel / _zoom; } 66 Vector pixelToModel(in Vector pixel) const { return pixel / _zoom; }
31 Rectangle modelToPixel(in Rectangle model) const { return Rectangle(modelToPixel(model.position), modelToPixel(model.size)); } 67 Rectangle modelToPixel(in Rectangle model) const { return Rectangle(modelToPixel(model.position), modelToPixel(model.size)); }
32 Rectangle pixelToModel(in Rectangle model) const { return Rectangle(pixelToModel(model.position), pixelToModel(model.size)); } 68 Rectangle pixelToModel(in Rectangle model) const { return Rectangle(pixelToModel(model.position), pixelToModel(model.size)); }
33 69
34 private { 70 private {
71 static double clampZoom(in double zoom) { return clamp(zoom, 0.1, 10.0); }
72
35 // Screen units are pixels 73 // Screen units are pixels
36 // Model units are millimetres 74 // Model units are millimetres
37 double _zoom; // pixels-per-millimetre 75 double _zoom; // pixels-per-millimetre
38 Rectangle _viewBounds; // pixel: bounds of the viewport in pixels 76 Rectangle _viewBounds; // pixel: bounds of the viewport in pixels
39 Point _viewCentre; // model: where in the model is the centre of our view 77 Point _viewCentre; // model: where in the model is the centre of our view