comparison doodle/gtk/canvas.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
8 private { 8 private {
9 import doodle.core.misc; 9 import doodle.core.misc;
10 import doodle.core.logging; 10 import doodle.core.logging;
11 import doodle.cairo.routines; 11 import doodle.cairo.routines;
12 import doodle.gtk.conversions; 12 import doodle.gtk.conversions;
13 import doodle.tk.pixel_model;
13 14
14 import cairo.Surface; 15 import cairo.Surface;
15 16
16 import gtk.Widget; 17 import gtk.Widget;
17 import gtk.Toolbar; 18 import gtk.Toolbar;
33 import std.math; 34 import std.math;
34 import std.stdio; 35 import std.stdio;
35 36
36 import core.stdc.string : strlen; 37 import core.stdc.string : strlen;
37 } 38 }
38
39 // x and y run right and up respectively
40 39
41 final class Canvas : Table, private IViewport { 40 final class Canvas : Table, private IViewport {
42 this(in Layer[] layers, IEventHandler eventHandler, IGrid grid, in double pixelsPerMillimetre) { 41 this(in Layer[] layers, IEventHandler eventHandler, IGrid grid, in double pixelsPerMillimetre) {
43 super(3, 3, 0); 42 super(3, 3, 0);
44 43
138 protected { // XXX the compiler complains about unimplemented methods if this is private 137 protected { // XXX the compiler complains about unimplemented methods if this is private
139 138
140 // IViewport overrides: 139 // IViewport overrides:
141 140
142 void zoomRelative(in Point pixelDatum, in double factor) { 141 void zoomRelative(in Point pixelDatum, in double factor) {
143 // Work out pixel distance from current centre to datum, 142 _pixelModel.zoomRelative(factor, pixelDatum);
144 // Do the zoom, then work out the new centre that keeps the
145 // pixel distance the same
146
147 Point oldModelDatum = pixelToModel(pixelDatum);
148 Vector pixelDistance = modelToPixel(oldModelDatum - _viewCentre);
149 _zoom = clampZoom(factor * _zoom);
150 _viewCentre = oldModelDatum - pixelToModel(pixelDistance);
151 143
152 consolidateBounds; 144 consolidateBounds;
153 145
154 updateAdjustments; 146 updateAdjustments;
155 updateRulers; 147 updateRulers;
156 _grid.zoomChanged(_zoom); 148 _grid.zoomChanged(_pixelModel.zoom);
157 queueDraw; 149 queueDraw;
158 } 150 }
159 151
160 void panRelative(in Vector pixelDisplacement) { 152 void panRelative(in Vector pixelDisplacement) {
161 _viewCentre = _viewCentre + pixelToModel(pixelDisplacement); 153 _pixelModel.panRelativePixel(pixelDisplacement);
162 154
163 consolidateBounds; 155 consolidateBounds;
164 156
165 updateAdjustments; 157 updateAdjustments;
166 updateRulers; 158 updateRulers;
189 181
190 _drawingArea.setCursor(new gdk.Cursor.Cursor(cursorType)); 182 _drawingArea.setCursor(new gdk.Cursor.Cursor(cursorType));
191 } 183 }
192 184
193 void damageModel(in Rectangle area) { 185 void damageModel(in Rectangle area) {
194 _damage = _damage | modelToPixel(area); 186 _damage = _damage | _pixelModel.modelToPixel(area);
195 } 187 }
196 188
197 void damagePixel(in Rectangle area) { 189 void damagePixel(in Rectangle area) {
198 _damage = _damage | area; 190 _damage = _damage | area;
199 } 191 }
206 foreach (layer; _layers) { bounds = bounds | layer.bounds; } 198 foreach (layer; _layers) { bounds = bounds | layer.bounds; }
207 assert(bounds.valid); 199 assert(bounds.valid);
208 return bounds; 200 return bounds;
209 } 201 }
210 202
211 void initialiseBounds() { 203 void initialiseBounds(in Rectangle viewBounds) {
212 Rectangle lb = layerBounds; 204 Rectangle lb = layerBounds;
213 205
214 // FIXME use a function that grows a rectangle about its centre 206 // FIXME use a function that grows a rectangle about its centre
215 // and change 2.0 to a class-level constant 207 // and change 2.0 to a class-level constant
216 Rectangle paddedLayerBounds = expand(move(lb, - lb.size), 2.0 * lb.size); 208 Rectangle paddedLayerBounds = expand(move(lb, - lb.size), 2.0 * lb.size);
217 209
218 // 210 _pixelModel = new PixelModel(0.25 * _pixelsPerMillimetre, paddedLayerBounds, viewBounds);
219 211
220 // FIXME 0.25 212 _grid.zoomChanged(_pixelModel.zoom);
221 _zoom = 0.25 * _pixelsPerMillimetre; // ie 0.25 pixels represents a millimetre
222
223 _canvasBounds = paddedLayerBounds;
224 _viewCentre = _canvasBounds.centre;
225
226 _grid.zoomChanged(_zoom);
227 213
228 updateAdjustments; 214 updateAdjustments;
229 updateRulers; 215 updateRulers;
230 } 216 }
231 217
233 Rectangle lb = layerBounds; 219 Rectangle lb = layerBounds;
234 220
235 // FIXME likewise as above 221 // FIXME likewise as above
236 Rectangle paddedLayerBounds = expand(move(lb, - lb.size), 2.0 * lb.size); 222 Rectangle paddedLayerBounds = expand(move(lb, - lb.size), 2.0 * lb.size);
237 223
238 Rectangle r = pixelToModel(_viewBounds); 224 _pixelModel.consolidateCanvasBounds(paddedLayerBounds);
239 _canvasBounds = r | paddedLayerBounds;
240 225
241 updateAdjustments; 226 updateAdjustments;
242 updateRulers; 227 updateRulers;
243 } 228 }
244 229
245 bool onConfigure(GdkEventConfigure * event, Widget widget) { 230 bool onConfigure(GdkEventConfigure * event, Widget widget) {
246 assert(widget is _drawingArea); 231 assert(widget is _drawingArea);
247 232
248 _viewBounds = Rectangle(Point(0.0, 0.0), Vector(cast(double)event.width, cast(double)event.height)); 233 Rectangle viewBounds = Rectangle(Point(0.0, 0.0), Vector(cast(double)event.width, cast(double)event.height));
249 234
250 if (!_boundsValid) { 235 if (_pixelModel is null) {
251 initialiseBounds; 236 initialiseBounds(viewBounds);
252 _boundsValid = true;
253 } 237 }
254 else { 238 else {
255 consolidateBounds; 239 consolidateBounds;
256 } 240 }
257 241
269 253
270 scope modelCr = new Context(dr); 254 scope modelCr = new Context(dr);
271 scope pixelCr = new Context(dr); 255 scope pixelCr = new Context(dr);
272 256
273 Rectangle pixelDamage = 257 Rectangle pixelDamage =
274 event is null ? 258 event is null ? _pixelModel.viewBounds :
275 _viewBounds : // XXX can we do something nice with the next line? 259 // FIXME next line sucks
276 Rectangle(_viewBounds.position + Vector(cast(double)event.area.x, _viewBounds.h - cast(double)(event.area.y + event.area.height)), 260 Rectangle(_pixelModel.viewBounds.position + Vector(cast(double)event.area.x, _pixelModel.viewBounds.h - cast(double)(event.area.y + event.area.height)),
277 Vector(cast(double)event.area.width, cast(double)event.area.height)); 261 Vector(cast(double)event.area.width, cast(double)event.area.height));
278 262
279 Rectangle modelDamage = pixelToModel(pixelDamage); 263 Rectangle modelDamage = _pixelModel.pixelToModel(pixelDamage);
280 264
281 //trace("Pixel damage: %s, model damage: %s", pixelDamage, modelDamage); 265 //trace("Pixel damage: %s, model damage: %s", pixelDamage, modelDamage);
282 266
283 modelCr.save; pixelCr.save; { 267 modelCr.save; pixelCr.save; {
284 { 268 {
285 // Setup model context and clip 269 // Setup model context and clip
286 modelCr.translate(0.0, _viewBounds.h); 270 modelCr.translate(0.0, _pixelModel.viewBounds.h);
287 modelCr.scale(_zoom, -_zoom); 271 modelCr.scale(_pixelModel.zoom, -_pixelModel.zoom);
288 272
289 // XXX revisit 273 immutable Point viewLeftBottom = _pixelModel.pixelToModel(Point(0.0, 0.0));
290 immutable Vector modelSize = pixelToModel(_viewBounds.size);
291 immutable Point viewLeftBottom = _viewCentre - modelSize / 2.0;
292 modelCr.translate(-viewLeftBottom.x, -viewLeftBottom.y); 274 modelCr.translate(-viewLeftBottom.x, -viewLeftBottom.y);
293 275
294 rectangle(modelCr, modelDamage); 276 rectangle(modelCr, modelDamage);
295 modelCr.clip; 277 modelCr.clip;
296 } 278 }
297 279
298 { 280 {
299 // Setup pixel context and clip 281 // Setup pixel context and clip
300 pixelCr.translate(0.0, _viewBounds.h); 282 pixelCr.translate(0.0, _pixelModel.viewBounds.h);
301 pixelCr.scale(1.0, -1.0); 283 pixelCr.scale(1.0, -1.0);
302 284
303 rectangle(pixelCr, pixelDamage); 285 rectangle(pixelCr, pixelDamage);
304 pixelCr.clip; 286 pixelCr.clip;
305 } 287 }
322 304
323 bool onButtonPress(GdkEventButton * event, Widget widget) { 305 bool onButtonPress(GdkEventButton * event, Widget widget) {
324 assert(widget is _drawingArea); 306 assert(widget is _drawingArea);
325 //trace("Got button event\n"); 307 //trace("Got button event\n");
326 308
327 Point pixelPoint = Point(event.x + 0.5, _viewBounds.h - (event.y + 0.5)); 309 Point pixelPoint = Point(event.x + 0.5, _pixelModel.viewBounds.h - (event.y + 0.5));
328 Point modelPoint = pixelToModel(pixelPoint); 310 Point modelPoint = _pixelModel.pixelToModel(pixelPoint);
329 311
330 auto buttonEvent = new ButtonEvent(gtk2tkButtonAction(event.type), 312 auto buttonEvent = new ButtonEvent(gtk2tkButtonAction(event.type),
331 gtk2tkButtonName(event.button), 313 gtk2tkButtonName(event.button),
332 pixelPoint, 314 pixelPoint,
333 modelPoint, 315 modelPoint,
341 } 323 }
342 324
343 bool onButtonRelease(GdkEventButton * event, Widget widget) { 325 bool onButtonRelease(GdkEventButton * event, Widget widget) {
344 assert(widget is _drawingArea); 326 assert(widget is _drawingArea);
345 327
346 Point pixelPoint = Point(event.x + 0.5, _viewBounds.h - (event.y + 0.5)); 328 Point pixelPoint = Point(event.x + 0.5, _pixelModel.viewBounds.h - (event.y + 0.5));
347 Point modelPoint = pixelToModel(pixelPoint); 329 Point modelPoint = _pixelModel.pixelToModel(pixelPoint);
348 330
349 auto buttonEvent = new ButtonEvent(gtk2tkButtonAction(event.type), 331 auto buttonEvent = new ButtonEvent(gtk2tkButtonAction(event.type),
350 gtk2tkButtonName(event.button), 332 gtk2tkButtonName(event.button),
351 pixelPoint, 333 pixelPoint,
352 modelPoint, 334 modelPoint,
407 assert(widget is _drawingArea); 389 assert(widget is _drawingArea);
408 //writefln("Got motion notify\n"); 390 //writefln("Got motion notify\n");
409 gtk_widget_event(_hRuler.getWidgetStruct(), cast(GdkEvent *)event); 391 gtk_widget_event(_hRuler.getWidgetStruct(), cast(GdkEvent *)event);
410 gtk_widget_event(_vRuler.getWidgetStruct(), cast(GdkEvent *)event); 392 gtk_widget_event(_vRuler.getWidgetStruct(), cast(GdkEvent *)event);
411 393
412 Point pixelPoint = Point(event.x + 0.5, _viewBounds.h - (event.y + 0.5)); 394 Point pixelPoint = Point(event.x + 0.5, _pixelModel.viewBounds.h - (event.y + 0.5));
413 Point modelPoint = pixelToModel(pixelPoint); 395 Point modelPoint = _pixelModel.pixelToModel(pixelPoint);
414 396
415 auto motionEvent = new MotionEvent(pixelPoint, 397 auto motionEvent = new MotionEvent(pixelPoint,
416 modelPoint, 398 modelPoint,
417 gtk2tkMask(event.state)); 399 gtk2tkMask(event.state));
418 400
425 407
426 bool onScroll(GdkEventScroll * event, Widget widget) { 408 bool onScroll(GdkEventScroll * event, Widget widget) {
427 assert(widget is _drawingArea); 409 assert(widget is _drawingArea);
428 //writefln("Got scroll\n"); 410 //writefln("Got scroll\n");
429 411
430 Point pixelPoint = Point(event.x + 0.5, _viewBounds.h - (event.y + 0.5)); 412 Point pixelPoint = Point(event.x + 0.5, _pixelModel.viewBounds.h - (event.y + 0.5));
431 Point modelPoint = pixelToModel(pixelPoint); 413 Point modelPoint = _pixelModel.pixelToModel(pixelPoint);
432 414
433 auto scrollEvent = new ScrollEvent(gtk2tkDirection(event.direction), 415 auto scrollEvent = new ScrollEvent(gtk2tkDirection(event.direction),
434 pixelPoint, 416 pixelPoint,
435 modelPoint, 417 modelPoint,
436 gtk2tkMask(event.state)); 418 gtk2tkMask(event.state));
470 */ 452 */
471 453
472 bool onEnterNotify(GdkEventCrossing * event, Widget widget) { 454 bool onEnterNotify(GdkEventCrossing * event, Widget widget) {
473 assert(widget is _drawingArea); 455 assert(widget is _drawingArea);
474 456
475 Point pixelPoint = Point(event.x + 0.5, _viewBounds.h - (event.y + 0.5)); 457 Point pixelPoint = Point(event.x + 0.5, _pixelModel.viewBounds.h - (event.y + 0.5));
476 Point modelPoint = pixelToModel(pixelPoint); 458 Point modelPoint = _pixelModel.pixelToModel(pixelPoint);
477 459
478 auto crossingEvent = new CrossingEvent(gtk2tkCrossingMode(event.mode), 460 auto crossingEvent = new CrossingEvent(gtk2tkCrossingMode(event.mode),
479 pixelPoint, 461 pixelPoint,
480 modelPoint, 462 modelPoint,
481 gtk2tkMask(event.state)); 463 gtk2tkMask(event.state));
490 } 472 }
491 473
492 bool onLeaveNotify(GdkEventCrossing * event, Widget widget) { 474 bool onLeaveNotify(GdkEventCrossing * event, Widget widget) {
493 assert(widget is _drawingArea); 475 assert(widget is _drawingArea);
494 476
495 Point pixelPoint = Point(event.x + 0.5, _viewBounds.h - (event.y + 0.5)); 477 Point pixelPoint = Point(event.x + 0.5, _pixelModel.viewBounds.h - (event.y + 0.5));
496 Point modelPoint = pixelToModel(pixelPoint); 478 Point modelPoint = _pixelModel.pixelToModel(pixelPoint);
497 479
498 auto crossingEvent = new CrossingEvent(gtk2tkCrossingMode(event.mode), 480 auto crossingEvent = new CrossingEvent(gtk2tkCrossingMode(event.mode),
499 pixelPoint, 481 pixelPoint,
500 modelPoint, 482 modelPoint,
501 gtk2tkMask(event.state)); 483 gtk2tkMask(event.state));
546 528
547 void onAdjustmentValueChanged(Adjustment adjustment) { 529 void onAdjustmentValueChanged(Adjustment adjustment) {
548 GtkAdjustment * hGtkAdjustment = _hAdjustment.getAdjustmentStruct; 530 GtkAdjustment * hGtkAdjustment = _hAdjustment.getAdjustmentStruct;
549 GtkAdjustment * vGtkAdjustment = _vAdjustment.getAdjustmentStruct; 531 GtkAdjustment * vGtkAdjustment = _vAdjustment.getAdjustmentStruct;
550 532
551 Point viewLeftBottom = Point(gtk_adjustment_get_value(hGtkAdjustment), 533 Point oldViewLeftBottom = _pixelModel.pixelToModel(Point(0.0, 0.0));
552 gtk_adjustment_get_value(vGtkAdjustment)); 534 Point newViewLeftBottom = Point(gtk_adjustment_get_value(hGtkAdjustment),
553 535 gtk_adjustment_get_value(vGtkAdjustment));
554 Vector modelSize = pixelToModel(_viewBounds.size); // XXX 536
555 537 _pixelModel.panRelativeModel(newViewLeftBottom - oldViewLeftBottom);
556 _viewCentre = viewLeftBottom + modelSize / 2.0;
557 538
558 updateRulers; 539 updateRulers;
559 queueDraw; 540 queueDraw;
560 } 541 }
561 542
562 void updateRulers() { 543 void updateRulers() {
563 immutable Vector modelSize = pixelToModel(_viewBounds.size); // XXX 544 immutable Point viewLeftBottom = _pixelModel.pixelToModel(Point(0.0, 0.0));
564 immutable Point viewLeftBottom = _viewCentre - modelSize / 2.0; 545 immutable Point viewRightTop = _pixelModel.pixelToModel(_pixelModel.viewBounds.corner1);
565 immutable Point viewRightTop = _viewCentre + modelSize / 2.0;
566 546
567 // Define these just to obtain the position 547 // Define these just to obtain the position
568 // below and we can preserve it 548 // below and we can preserve it
569 double lower, upper, position, maxSize; 549 double lower, upper, position, maxSize;
570 550
571 _hRuler.getRange(lower, upper, position, maxSize); 551 _hRuler.getRange(lower, upper, position, maxSize);
572 _hRuler.setRange(viewLeftBottom.x, 552 _hRuler.setRange(viewLeftBottom.x,
573 viewRightTop.x, 553 viewRightTop.x,
574 position, 554 position,
575 _zoom * 50.0); 555 _pixelModel.zoom * 50.0);
576 556
577 _vRuler.getRange(lower, upper, position, maxSize); 557 _vRuler.getRange(lower, upper, position, maxSize);
578 _vRuler.setRange(viewRightTop.y, 558 _vRuler.setRange(viewRightTop.y,
579 viewLeftBottom.y, 559 viewLeftBottom.y,
580 position, 560 position,
581 _zoom * 50.0); 561 _pixelModel.zoom * 50.0);
582 } 562 }
583 563
584 void updateAdjustments() { 564 void updateAdjustments() {
585 immutable Vector modelSize = pixelToModel(_viewBounds.size); // XXX 565 immutable Point viewLeftBottom = _pixelModel.pixelToModel(Point(0.0, 0.0));
586 immutable Point viewLeftBottom = _viewCentre - modelSize / 2.0; 566 immutable Point viewRightTop = _pixelModel.pixelToModel(_pixelModel.viewBounds.corner1);
587 immutable Point viewRightTop = _viewCentre + modelSize / 2.0; 567
588 568 // Adjust the canvas size if necessary FIXME is this required??
589 // Adjust the canvas size if necessary 569 _pixelModel.canvasAccommodate(Rectangle(viewLeftBottom, viewRightTop));
590 _canvasBounds = Rectangle(minExtents(_canvasBounds.corner0, viewLeftBottom), 570
591 maxExtents(_canvasBounds.corner1, viewRightTop)); 571 // FIXME
572 Rectangle modelSize = _pixelModel.pixelToModel(_pixelModel.viewBounds);
592 573
593 // Update the adjustments 574 // Update the adjustments
594 575
595 GtkAdjustment * hGtkAdjustment = _hAdjustment.getAdjustmentStruct; 576 GtkAdjustment * hGtkAdjustment = _hAdjustment.getAdjustmentStruct;
596 GtkAdjustment * vGtkAdjustment = _vAdjustment.getAdjustmentStruct; 577 GtkAdjustment * vGtkAdjustment = _vAdjustment.getAdjustmentStruct;
597 578
598 gtk_adjustment_set_lower(hGtkAdjustment, _canvasBounds.corner0.x); 579 gtk_adjustment_set_lower(hGtkAdjustment, _pixelModel.canvasBounds.x0);
599 gtk_adjustment_set_upper(hGtkAdjustment, _canvasBounds.corner1.x); 580 gtk_adjustment_set_upper(hGtkAdjustment, _pixelModel.canvasBounds.x1);
600 gtk_adjustment_set_value(hGtkAdjustment, viewLeftBottom.x); 581 gtk_adjustment_set_value(hGtkAdjustment, viewLeftBottom.x);
601 gtk_adjustment_set_step_increment(hGtkAdjustment, _canvasBounds.size.x / 16.0); 582 gtk_adjustment_set_step_increment(hGtkAdjustment, _pixelModel.canvasBounds.w / 16.0);
602 gtk_adjustment_set_page_increment(hGtkAdjustment, _canvasBounds.size.x / 4.0); 583 gtk_adjustment_set_page_increment(hGtkAdjustment, _pixelModel.canvasBounds.w / 4.0);
603 gtk_adjustment_set_page_size(hGtkAdjustment, modelSize.x); 584 gtk_adjustment_set_page_size(hGtkAdjustment, modelSize.w);
604 585
605 gtk_adjustment_set_lower(vGtkAdjustment, _canvasBounds.corner0.y); 586 gtk_adjustment_set_lower(vGtkAdjustment, _pixelModel.canvasBounds.y0);
606 gtk_adjustment_set_upper(vGtkAdjustment, _canvasBounds.corner1.y); 587 gtk_adjustment_set_upper(vGtkAdjustment, _pixelModel.canvasBounds.y1);
607 gtk_adjustment_set_value(vGtkAdjustment, viewLeftBottom.y); 588 gtk_adjustment_set_value(vGtkAdjustment, viewLeftBottom.y);
608 gtk_adjustment_set_step_increment(vGtkAdjustment, _canvasBounds.size.y / 16.0); 589 gtk_adjustment_set_step_increment(vGtkAdjustment, _pixelModel.canvasBounds.h / 16.0);
609 gtk_adjustment_set_page_increment(vGtkAdjustment, _canvasBounds.size.y / 4.0); 590 gtk_adjustment_set_page_increment(vGtkAdjustment, _pixelModel.canvasBounds.h / 4.0);
610 gtk_adjustment_set_page_size(vGtkAdjustment, modelSize.y); 591 gtk_adjustment_set_page_size(vGtkAdjustment, modelSize.h);
611 592
612 _hAdjustment.changed; 593 _hAdjustment.changed;
613 _hAdjustment.valueChanged; 594 _hAdjustment.valueChanged;
614 _vAdjustment.changed; 595 _vAdjustment.changed;
615 _vAdjustment.valueChanged; 596 _vAdjustment.valueChanged;
617 598
618 void fixDamage() { 599 void fixDamage() {
619 if (_damage.valid) { 600 if (_damage.valid) {
620 int x, y, w, h; 601 int x, y, w, h;
621 _damage.getQuantised(x, y, w, h); 602 _damage.getQuantised(x, y, w, h);
622 _drawingArea.queueDrawArea(x, cast(int)_viewBounds.h - (y + h), w, h); 603 _drawingArea.queueDrawArea(x, cast(int)_pixelModel.viewBounds.h - (y + h), w, h);
623 _damage = Rectangle.DEFAULT; 604 _damage = Rectangle.DEFAULT;
624 } 605 }
625 } 606 }
626 607
627 static double clampZoom(in double zoom) { return clamp(zoom, 0.2, 10.0); }
628
629 Point modelToPixel(in Point model) const {
630 return _viewBounds.centre + _zoom * (model - _viewCentre);
631 }
632
633 Point pixelToModel(in Point pixel) const {
634 return _viewCentre + (pixel - _viewBounds.centre) / _zoom;
635 }
636
637 Vector modelToPixel(in Vector model) const {
638 return _zoom * model;
639 }
640
641 Vector pixelToModel(in Vector pixel) const {
642 return pixel / _zoom;
643 }
644
645 Rectangle modelToPixel(in Rectangle model) const {
646 return Rectangle(modelToPixel(model.position), modelToPixel(model.size));
647 }
648
649 Rectangle pixelToModel(in Rectangle model) const {
650 return Rectangle(pixelToModel(model.position), pixelToModel(model.size));
651 }
652
653 void onRealize(Widget widget) { 608 void onRealize(Widget widget) {
654 assert(widget is _drawingArea); 609 assert(widget is _drawingArea);
655 //writefln("Got realize\n"); 610 //writefln("Got realize\n");
656 _drawingArea.grabFocus(); 611 _drawingArea.grabFocus();
657 } 612 }
658 613
659 bool _boundsValid;
660 Rectangle _damage; // pixels 614 Rectangle _damage; // pixels
661 615 PixelModel _pixelModel;
662 // Model units are millimetres
663 // Screen units are pixels
664 double _zoom; // pixels-per-model-unit
665 Rectangle _viewBounds; // pixel: bounds of the viewport in pixels
666 Point _viewCentre; // model: where in the model is the centre of our view
667 Rectangle _canvasBounds; // model: bounds of the canvas in millimetres
668 616
669 // Child widgets: 617 // Child widgets:
670 HRuler _hRuler; 618 HRuler _hRuler;
671 VRuler _vRuler; 619 VRuler _vRuler;
672 DrawingArea _drawingArea; 620 DrawingArea _drawingArea;