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