view doodle/dia/standard_tools.d @ 34:c2f11e1d7470

Geometry cleanup and checkpoint.
author David Bryant <bagnose@gmail.com>
date Sun, 30 Aug 2009 15:32:12 +0930
parents 1754cb773d41
children 188397ef9a12
line wrap: on
line source

module doodle.dia.standard_tools;

public {
    import doodle.dia.tool;
}

private {
    import doodle.cairo.routines;
    import std.math;
    import std.stdio;
}

final class PanTool : Tool {
    override bool handle_button_press(scope Viewport viewport, in ButtonEvent event) {
        if (event.button_name == ButtonName.MIDDLE) {
            mLastPosition = event.pixel_point;
            return true;
        }
        else {
            return false;
        }
    }

    override bool handle_motion(scope Viewport viewport, in MotionEvent event) {
        if (event.mask.is_set(Modifier.MIDDLE_BUTTON)) {
            viewport.pan_relative(mLastPosition - event.pixel_point);
            mLastPosition = event.pixel_point;

            return true;
        }
        else {
            return false;
        }
    }

    override bool handle_scroll(scope Viewport viewport, in ScrollEvent event) {
        if (event.mask.is_unset(Modifier.MIDDLE_BUTTON)) {
            Vector delta;

            switch (event.scroll_direction) {
            case ScrollDirection.UP:
                delta = event.mask.is_set(Modifier.SHIFT) ? Vector(AMOUNT, 0.0) : Vector(0.0, AMOUNT);
                break;
            case ScrollDirection.DOWN:
                delta = event.mask.is_set(Modifier.SHIFT) ? Vector(-AMOUNT, 0.0) : Vector(0.0, -AMOUNT);
                break;
            case ScrollDirection.LEFT:
                delta = Vector(-AMOUNT, 0.0);
                break;
            case ScrollDirection.RIGHT:
                delta = Vector(AMOUNT, 0.0);
                break;
            }

            viewport.pan_relative(delta);
        }

        return true;
    }

    private {
        Point mLastPosition;
        static invariant double AMOUNT = 60.0;
    }
}

final class ZoomTool : Tool {
    override bool handle_scroll(scope Viewport viewport, in ScrollEvent event) {
        if (event.mask.is_set(Modifier.CONTROL)) {
            if (event.scroll_direction == ScrollDirection.DOWN) {
                viewport.zoom_relative(event.pixel_point, 1.0 / ZOOM);
                return true;
            }
            else if (event.scroll_direction == ScrollDirection.UP) {
                viewport.zoom_relative(event.pixel_point, ZOOM);
                return true;
            }
            else {
                return false;
            }
        }
        else {
            return false;
        }
    }

    private {
        static invariant double ZOOM = sqrt(2.0);
    }
}

final class LassoTool : Tool {
    override bool handle_button_press(scope Viewport viewport, in ButtonEvent event) {
        if (event.button_name == ButtonName.LEFT) {
            mActive = true;
            mAnchorPoint = mCurrentPoint = event.pixel_point;
            viewport.set_cursor(Cursor.HAND);
            return true;
        }
        else {
            return false;
        }
    }

    override bool handle_button_release(scope Viewport viewport, in ButtonEvent event) {
        if (event.button_name == ButtonName.LEFT && mActive) {
            mActive = false;
            viewport.damage_pixel(feather(Rectangle(mAnchorPoint, mCurrentPoint), LINE_WIDTH / 2.0));
            viewport.set_cursor(Cursor.DEFAULT);
            return true;
        }
        else {
            return false;
        }
    }

    override bool handle_motion(scope Viewport viewport, in MotionEvent event) {
        if (mActive) {
            viewport.damage_pixel(feather(Rectangle(mAnchorPoint, mCurrentPoint), LINE_WIDTH / 2.0));
            mCurrentPoint = event.pixel_point;
            viewport.damage_pixel(feather(Rectangle(mAnchorPoint, mCurrentPoint), LINE_WIDTH / 2.0));
        }

        return false;
    }

    override void draw(in Viewport viewport,
                       in Rectangle pixel_damage, scope Context pixel_cr,
                       in Rectangle model_damage, scope Context model_cr) const {
        if (mActive) {
            pixel_cr.save; {
                pixel_cr.setSourceRgba(0.0, 0.0, 0.8, 0.3);
                rectangle(pixel_cr, Rectangle(mCurrentPoint, mAnchorPoint));
                pixel_cr.fill();
            } pixel_cr.restore();

            pixel_cr.save(); {
                //double[] dashes = [ 4.0, 4.0 ];
                //pixel_cr.setDash(dashes, 0.0);
                pixel_cr.setSourceRgba(0.0, 0.0, 0.5, 1.0);
                pixel_cr.setLineWidth(LINE_WIDTH);
                //writefln("Drawing rectangle: %s", Rectangle(mCurrentPoint, mAnchorPoint));
                rectangle(pixel_cr, Rectangle(mCurrentPoint, mAnchorPoint));
                pixel_cr.stroke;
            } pixel_cr.restore;
        }
    }

    private {
        bool mActive;
        Point mCurrentPoint;
        Point mAnchorPoint;      // Pixel
        static invariant double LINE_WIDTH = 1.0;
    }
}