Mercurial > projects > doodle
view doodle/tk/pixel_model.d @ 77:15ca7d5cd1ed
The rulers are broken
author | "David Bryant <bagnose@gmail.com>" |
---|---|
date | Sun, 15 Aug 2010 01:36:22 +0930 |
parents | 5cc2de64f6d0 |
children | 024a5608087f |
line wrap: on
line source
module doodle.tk.screen_model; public { import doodle.tk.geometry; } private { import doodle.core.misc; } // This class manages the relationship between screen space and model space. // It provides convenient high-level operations. // // x and y run right and up respectively for screen and model space class ScreenModel { this(in double zoom, in Rectangle canvasBoundsModel, in Rectangle viewBoundsScreen) { _zoom = zoom; _viewBoundsScreen = viewBoundsScreen; _canvasBoundsModel = canvasBoundsModel; // Choose the centre of the canvas as the centre of the view _viewCentreModel = _canvasBoundsModel.centre; } void consolidateCanvasBounds(in Rectangle requiredCanvasBounds) { _canvasBoundsModel = screenToModel(_viewBoundsScreen) | requiredCanvasBounds; } void canvasAccommodate(in Rectangle bounds) { _canvasBoundsModel = _canvasBoundsModel | bounds; } void zoomRelative(in double factor, in Point screenDatum) { // Work out screen distance from current centre to datum, // Do the zoom, then work out the new centre that keeps the // screen distance the same Point oldModelDatum = screenToModel(screenDatum); Vector screenDistance = modelToScreen(oldModelDatum - _viewCentreModel); _zoom = clampZoom(zoom * factor); _viewCentreModel = oldModelDatum - screenToModel(screenDistance); } void panRelativeScreen(in Vector screenDisplacement) { _viewCentreModel = _viewCentreModel + screenToModel(screenDisplacement); } void panRelativeModel(in Vector modelDisplacement) { _viewCentreModel = _viewCentreModel + modelDisplacement; } // For userZoom 1.0 -> 100% means the presentation on the screen is // one-to-one with real-life double userZoom(in double screensPerMillimetre) const { return _zoom / screensPerMillimetre; } double zoom() const { return _zoom; } Rectangle viewBoundsScreen() const { return _viewBoundsScreen; } Rectangle canvasBoundsModel() const { return _canvasBoundsModel; } Point modelToScreen(in Point model) const { return _viewBoundsScreen.centre + _zoom * (model - _viewCentreModel); } Point screenToModel(in Point screen) const { return _viewCentreModel + (screen - _viewBoundsScreen.centre) / _zoom; } Vector modelToScreen(in Vector model) const { return _zoom * model; } Vector screenToModel(in Vector screen) const { return screen / _zoom; } Rectangle modelToScreen(in Rectangle model) const { return Rectangle(modelToScreen(model.position), modelToScreen(model.size)); } Rectangle screenToModel(in Rectangle model) const { return Rectangle(screenToModel(model.position), screenToModel(model.size)); } private { static double clampZoom(in double zoom) { return clamp(zoom, 0.1, 10.0); } // Screen units are screens // Model units are millimetres double _zoom; // screens-per-millimetre Rectangle _viewBoundsScreen; // bounds of the viewport in screens Point _viewCentreModel; // where in the model is the centre of our view Rectangle _canvasBoundsModel; // the bounds of the canvas in millimetres } }