Mercurial > projects > doodle
view 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 |
line wrap: on
line source
module doodle.tk.pixel_model; public { import doodle.tk.geometry; } private { import doodle.core.misc; } // FIXME consider using the term Screen instead of Pixel... // This class manages the relationship between pixel space and model space. // It provides convenient high-level operations. // // x and y run right and up respectively for pixel and model space class PixelModel { this(in double zoom, in Rectangle canvasBounds, in Rectangle viewBounds) { _zoom = zoom; _viewBounds = viewBounds; _canvasBounds = canvasBounds; // Choose the centre of the canvas as the centre of the view _viewCentre = _canvasBounds.centre; } void consolidateCanvasBounds(in Rectangle requiredCanvasBounds) { Rectangle r = pixelToModel(_viewBounds); _canvasBounds = r | requiredCanvasBounds; } void canvasAccommodate(in Rectangle bounds) { _canvasBounds = _canvasBounds | bounds; } void zoomRelative(in double factor, in Point pixelDatum) { // Work out pixel distance from current centre to datum, // Do the zoom, then work out the new centre that keeps the // pixel distance the same Point oldModelDatum = pixelToModel(pixelDatum); Vector pixelDistance = modelToPixel(oldModelDatum - _viewCentre); _zoom = clampZoom(zoom * factor); _viewCentre = oldModelDatum - pixelToModel(pixelDistance); } void panRelativePixel(in Vector pixelDisplacement) { _viewCentre = _viewCentre + pixelToModel(pixelDisplacement); } void panRelativeModel(in Vector modelDisplacement) { _viewCentre = _viewCentre + modelDisplacement; } // For normalZoom 1.0 -> 100% means the presentation on the screen is // one-to-one with real-life double normalZoom(in double pixelsPerMillimetre) const { return _zoom / pixelsPerMillimetre; } double zoom() const { return _zoom; } Rectangle viewBounds() const { return _viewBounds; } Rectangle canvasBounds() const { return _canvasBounds; } Point modelToPixel(in Point model) const { return _viewBounds.centre + _zoom * (model - _viewCentre); } Point pixelToModel(in Point pixel) const { return _viewCentre + (pixel - _viewBounds.centre) / _zoom; } Vector modelToPixel(in Vector model) const { return _zoom * model; } Vector pixelToModel(in Vector pixel) const { return pixel / _zoom; } Rectangle modelToPixel(in Rectangle model) const { return Rectangle(modelToPixel(model.position), modelToPixel(model.size)); } Rectangle pixelToModel(in Rectangle model) const { return Rectangle(pixelToModel(model.position), pixelToModel(model.size)); } private { static double clampZoom(in double zoom) { return clamp(zoom, 0.1, 10.0); } // Screen units are pixels // Model units are millimetres double _zoom; // pixels-per-millimetre 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: the bounds of the canvas in millimetres } }