# HG changeset patch # User daveb # Date 1275378661 -34200 # Node ID f2e4e1d29b9899b6cf5ab7be1f7a8cb42e1df30f # Parent 1f97022e5c6d0af73b93a29cfc870b0b9564a447 Bah diff -r 1f97022e5c6d -r f2e4e1d29b98 doodle/dia/grid_layer.d --- a/doodle/dia/grid_layer.d Mon Apr 12 14:01:54 2010 +0930 +++ b/doodle/dia/grid_layer.d Tue Jun 01 17:21:01 2010 +0930 @@ -47,11 +47,9 @@ { // vertical grid lines double x = start(model_damage.min_corner.x, mSpacing); - double y0 = model_damage.min_corner.y; - double y1 = model_damage.max_corner.y; for (;;) { - vline(model_cr, x, y0, y1); + vline(model_cr, x, model_damage.min_corner.y, model_damage.max_corner.y); // Ensure 1 pixel wide FIXME is this naughty? We are sneaking // through cairo to mix model and pixel coordinates... @@ -71,12 +69,11 @@ { // horizontal grid lines double y = start(model_damage.min_corner.y, mSpacing); - double x0 = model_damage.min_corner.x; - double x1 = model_damage.max_corner.x; for (;;) { - hline(model_cr, y, x0, x1); + hline(model_cr, y, model_damage.min_corner.x, model_damage.max_corner.x); + // FIXME? model_cr.save(); { model_cr.scale(1.0 / xx, 1.0 / yy); model_cr.stroke(); @@ -99,7 +96,7 @@ mZoomValid = true; // FIXME compute spacing properly - mSpacing = 10.0 / mZoom; // mm + mSpacing = 20.0 / mZoom; // mm } // FIXME use inout parameter? diff -r 1f97022e5c6d -r f2e4e1d29b98 doodle/dia/icanvas.d --- a/doodle/dia/icanvas.d Mon Apr 12 14:01:54 2010 +0930 +++ b/doodle/dia/icanvas.d Tue Jun 01 17:21:01 2010 +0930 @@ -62,7 +62,7 @@ abstract class Layer { this(in string name) { - mName = name; + mName = name.idup; } string name() const { return mName; } diff -r 1f97022e5c6d -r f2e4e1d29b98 doodle/dia/page_layer.d --- a/doodle/dia/page_layer.d Mon Apr 12 14:01:54 2010 +0930 +++ b/doodle/dia/page_layer.d Tue Jun 01 17:21:01 2010 +0930 @@ -27,16 +27,16 @@ // Make the paper white, with a border model_cr.save; { + model_cr.setSourceRgba(0.0, 0.0, 0.0, 1.0); + rectangle(model_cr, mPageGeometry); + model_cr.stroke; + } model_cr.restore; + + model_cr.save; { model_cr.setSourceRgba(1.0, 1.0, 1.0, 1.0); rectangle(model_cr, mPageGeometry); model_cr.fill; } model_cr.restore; - - model_cr.save; { - model_cr.setSourceRgba(0.0, 0.0, 0.0, 1.0); - rectangle(model_cr, mPageGeometry); - model_cr.stroke; - } model_cr.restore; } // Page overrides: diff -r 1f97022e5c6d -r f2e4e1d29b98 doodle/gtk/canvas.d --- a/doodle/gtk/canvas.d Mon Apr 12 14:01:54 2010 +0930 +++ b/doodle/gtk/canvas.d Tue Jun 01 17:21:01 2010 +0930 @@ -33,6 +33,18 @@ } // x and y run right and up respectively +// +// Model units are millimetres. +// +// mZoom -> pixels-per-model-unit +// mViewSize -> size of view window in pixels +// mViewCentre -> location in model corresponding to centre of view +// mCanvasBounds -> size of the virtual canvas in model coordinates +// +// User operations: +// pan (middle click and drag) +// zoom about a point (hold control and move scroll wheel) +// resize the widget class Canvas : Table, Viewport { this(in Layer[] layers, EventHandler event_handler, Grid grid, in double ppi) { @@ -184,33 +196,46 @@ private { + void update_bounds() { + } + + bool on_configure(GdkEventConfigure * event, Widget widget) { assert(widget is mDrawingArea); + mViewSize = Vector(cast(double)event.width, cast(double)event.height); + + Rectangle layer_bounds = Rectangle.DEFAULT; + + foreach (ref layer; mLayers) { + layer_bounds = layer_bounds | layer.bounds; + } + + assert(layer_bounds.valid); + + Rectangle padded_layer_bounds = expand(move(layer_bounds, - layer_bounds.size), 2.0 * layer_bounds.size); + if (!mHadConfigure) { + info("1"); const double MM_PER_INCH = 25.4; mZoom = 0.25 * mPPI / MM_PER_INCH; - // Take the union of the bounds of each layer to - // determine the canvas size - - Rectangle layer_bounds = Rectangle.DEFAULT; - - foreach (ref layer; mLayers) { - layer_bounds = layer_bounds | layer.bounds; - } - - assert(layer_bounds.valid); - - mCanvasBounds = expand(move(layer_bounds, -layer_bounds.size), 2.0 * layer_bounds.size); + mCanvasBounds = padded_layer_bounds; mViewCentre = mCanvasBounds.centre; mGrid.zoom_changed(mZoom); mHadConfigure = true; } + else { + // Use configure events as an opportunity + // to consolidate the canvas-bounds + // XXX nasty code. + Vector z = mViewSize / mZoom; + Rectangle r = Rectangle(mViewCentre - z / 2.0, z); + mCanvasBounds = r | padded_layer_bounds; + } - mViewSize = Vector(cast(double)event.width, cast(double)event.height); update_adjustments; update_rulers; @@ -267,7 +292,7 @@ pixel_cr.save; { // Make the window light grey - pixel_cr.setSourceRgba(0.6, 0.6, 0.6, 1.0); + pixel_cr.setSourceRgba(0.9, 0.9, 0.9, 1.0); rectangle(pixel_cr, pixel_damage); pixel_cr.fill; } pixel_cr.restore; @@ -299,7 +324,7 @@ mEventHandler.handle_button_press(this, button_event); - process_damage; + fix_damage; return true; } @@ -319,7 +344,7 @@ mEventHandler.handle_button_release(this, button_event); - process_damage; + fix_damage; return true; } @@ -331,7 +356,7 @@ //auto key_event = new KeyEvent("", // mEventHandle.handle_key(key_event); - process_damage; + fix_damage; return true; } @@ -351,7 +376,7 @@ mEventHandler.handle_motion(this, motion_event); - process_damage; + fix_damage; return true; } @@ -370,7 +395,7 @@ mEventHandler.handle_scroll(this, scroll_event); - process_damage; + fix_damage; return true; } @@ -492,7 +517,7 @@ mVAdjustment.valueChanged; } - void process_damage() { + void fix_damage() { if (mDamage.valid) { //writefln("Damage: %s", mDamage); int x, y, w, h; @@ -541,7 +566,7 @@ // Model units are in millimetres // Screen units are in pixels - double mZoom; // pixels-per-model-unit (mm) + double mZoom; // pixels-per-model-unit Vector mViewSize; // pixel: size of view window in pixels Point mViewCentre; // model: where in the model is the centre of our view Rectangle mCanvasBounds; // model: diff -r 1f97022e5c6d -r f2e4e1d29b98 doodle/tk/geometry.d --- a/doodle/tk/geometry.d Mon Apr 12 14:01:54 2010 +0930 +++ b/doodle/tk/geometry.d Tue Jun 01 17:21:01 2010 +0930 @@ -4,6 +4,7 @@ import std.stdio; import std.math; import doodle.tk.misc; + import doodle.core.logging; } // In doodle x and y increase right/east and up/north respectively. @@ -30,6 +31,8 @@ } this(in double x, in double y) { + assert(!isnan(x)); + assert(!isnan(y)); _x = x; _y = y; } @@ -78,6 +81,8 @@ } this(in double x, in double y) { + assert(!isnan(x)); + assert(!isnan(y)); _x = x; _y = y; } @@ -95,10 +100,12 @@ } Vector opMul_r(in double d) const { + assert(!isnan(d)); return Vector(d * _x, d * _y); } Vector opDiv(in double d) const { + assert(!isnan(d)); return Vector(_x / d, _y / d); } @@ -164,7 +171,7 @@ Point max_corner() const { return _position + _size; } - bool valid() const { return _size.x > 0.0 & _size.y > 0.0; } + bool valid() const { return _size.x > 0.0 && _size.y > 0.0; } bool invalid() const { return !valid(); } @@ -245,6 +252,10 @@ return Rectangle(new_position, r.size); } +Rectangle resize(in Rectangle r, in Vector new_size) { + return Rectangle(r.position, new_size); +} + // Operations about the bottom left corner Rectangle expand(in Rectangle r, in Vector expand_amount) { @@ -259,19 +270,23 @@ Rectangle feather(in Rectangle r, double amount) { assert(amount >= 0.0); + assert(!isnan(amount)); return Rectangle(Point(r.position.x - amount, r.position.y - amount), Vector(r.size.x + 2.0 * amount, r.size.y + 2.0 * amount)); } -Rectangle resize(in Rectangle r, in Vector new_size) { - return Rectangle(r.position, new_size); -} - private { - // This is a commmon building block for intersection of lines and segments - // Two lines "a" and "b" are defined by two points each . - // "ua" and "ub" define the intersection as a fraction along - // the two respective line segments (FIXME this comment sucks) + // This function computes the intersection of two lines. + // The lines are defined by a start point and an end point, however they + // notionally extend infinitely in each direction. + // The out parameters specify the fraction along the line-segment at which + // intersection occurred. + // + // This is a commmon building block for computing intersection between lines, segments, + // rectangles, etc. + // + // The function returns false if the lines are parallel or nearly so. + // // Influenced by http://ozviz.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ bool compute_intersection(in Point pa1, in Point pa2, out double ua, in Point pb1, in Point pb2, out double ub) { @@ -279,7 +294,7 @@ if (abs(den) < 1e-9) { // TODO consolidate constants used for numerical stability // Lines are parallel or nearly so - writefln("Warning, parallel lines!"); + warning("Warning, parallel lines!"); return false; } else { @@ -293,6 +308,11 @@ return true; } } + + /+ + double compute_angle(in Point p1, in Point p2) { + } + +/ } //