view doodle/dia/standard_tools.d @ 56:b190a9d9352e

Checkpoint
author "David Bryant <bagnose@gmail.com>"
date Sun, 08 Aug 2010 21:56:54 +0930
parents 1b4c9ba58673
children 9960c4fbd0dd
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 handleButtonPress(scope Viewport viewport, in ButtonEvent event) {
        if (event.button_name == ButtonName.MIDDLE) {
            mLastPosition = event.pixelPoint;
            return true;
        }
        else {
            return false;
        }
    }

    override bool handleMotion(scope Viewport viewport, in MotionEvent event) {
        if (event.mask.isSet(Modifier.MIDDLE_BUTTON)) {
            viewport.panRelative(mLastPosition - event.pixelPoint);
            mLastPosition = event.pixelPoint;

            return true;
        }
        else {
            return false;
        }
    }

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

            switch (event.scrollDirection) {
            case ScrollDirection.UP:
                delta = event.mask.isSet(Modifier.SHIFT) ? Vector(-AMOUNT, 0.0) : Vector(0.0, AMOUNT);
                break;
            case ScrollDirection.DOWN:
                delta = event.mask.isSet(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;
            default:
                assert(0);
            }

            viewport.panRelative(delta);
        }

        return true;
    }

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

final class ZoomTool : Tool {
    override bool handleScroll(scope Viewport viewport, in ScrollEvent event) {
        if (event.mask.isSet(Modifier.CONTROL)) {
            if (event.scrollDirection == ScrollDirection.DOWN) {
                viewport.zoomRelative(event.pixelPoint, 1.0 / ZOOM);
                return true;
            }
            else if (event.scrollDirection == ScrollDirection.UP) {
                viewport.zoomRelative(event.pixelPoint, ZOOM);
                return true;
            }
            else {
                return false;
            }
        }
        else {
            return false;
        }
    }

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

final class SelectTool : Tool {
    override bool handleButtonPress(scope Viewport viewport, in ButtonEvent event) {
        if (event.button_name == ButtonName.LEFT) {
            _active = true;
            _anchorPoint = _currentPoint = event.pixelPoint;
            viewport.setCursor(Cursor.HAND);
            return true;
        }
        else {
            return false;
        }
    }

    override bool handleButtonRelease(scope Viewport viewport, in ButtonEvent event) {
        if (event.button_name == ButtonName.LEFT && _active) {
            _active = false;
            viewport.damagePixel(feather(Rectangle(_anchorPoint, _currentPoint), LINE_WIDTH / 2.0));
            viewport.setCursor(Cursor.DEFAULT);
            return true;
        }
        else {
            return false;
        }
    }

    override bool handleMotion(scope Viewport viewport, in MotionEvent event) {
        if (_active) {
            viewport.damagePixel(feather(Rectangle(_anchorPoint, _currentPoint), LINE_WIDTH / 2.0));
            _currentPoint = event.pixelPoint;
            viewport.damagePixel(feather(Rectangle(_anchorPoint, _currentPoint), LINE_WIDTH / 2.0));
        }

        return false;
    }

    override void draw(in Viewport viewport,
                       in Rectangle pixelDamage, scope Context pixelCr) const {
        if (_active) {
            /*
            pixelCr.save; {
                pixelCr.setSourceRgba(0.0, 0.0, 0.8, 0.3);
                rectangle(pixelCr, Rectangle(_currentPoint, _anchorPoint));
                pixelCr.fill();
            } pixelCr.restore();
            */

            pixelCr.save(); {
                double[] dashes = [ 4.0, 4.0 ];
                pixelCr.setDash(dashes, 0.0);
                pixelCr.setSourceRgba(0.0, 0.0, 0.5, 1.0);
                pixelCr.setLineWidth(LINE_WIDTH);
                rectangle(pixelCr, Rectangle(_currentPoint, _anchorPoint));
                pixelCr.stroke;
            } pixelCr.restore;
        }
    }

    private {
        bool _active;
        Point _currentPoint;
        Point _anchorPoint;      // Pixel
        static invariant double LINE_WIDTH = 1.0;
    }
}