# HG changeset patch # User David Bryant # Date 1247204727 -34200 # Node ID d6f44347373dc48cdfb6389791012e63f1e4b69b # Parent c18e3f93d114bfbcf6f76dbee7c75e1f9065cb63 * Switched over to geometry done with structs instead of classes. * Removed direct access to gtk structs * Refactoring diff -r c18e3f93d114 -r d6f44347373d build.sh --- a/build.sh Wed May 13 17:50:25 2009 +0930 +++ b/build.sh Fri Jul 10 15:15:27 2009 +0930 @@ -2,9 +2,9 @@ dmd \ -ofgui \ - gui.d handler.d icanvas.d canvas.d \ + gui.d tool_stack.d tool.d icanvas.d canvas.d \ tk/geometry.d tk/gtk_support.d tk/misc.d tk/types.d tk/events.d \ - tk/geometry2.d \ + tk/geometry2.d cairo_support.d \ -od.obj \ -I"${DMD_BASE}/include/d" \ -L-lgtkd -L-ldl diff -r c18e3f93d114 -r d6f44347373d cairo_support.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cairo_support.d Fri Jul 10 15:15:27 2009 +0930 @@ -0,0 +1,20 @@ +module cairo_support; + +import tk.geometry2; + +import cairo.Context; + +void rectangle(Context cr, Point2 corner1, Point2 corner2) { + double x = corner1.x; + double y = corner1.y; + double w = corner2.x - corner1.x; + double h = corner2.y - corner1.y; + + if (w < 0.0) { x += w; w = -w; } + if (h < 0.0) { y += h; h = -h; } + + //writefln("Rect: %f %f %f %f\n", x, y, w, h); + + cr.rectangle(x, y, w, h); +} + diff -r c18e3f93d114 -r d6f44347373d canvas.d --- a/canvas.d Wed May 13 17:50:25 2009 +0930 +++ b/canvas.d Fri Jul 10 15:15:27 2009 +0930 @@ -20,7 +20,7 @@ import gtk.Adjustment; import tk.misc; -import tk.geometry; +import tk.geometry2; import tk.types; import tk.events; import tk.gtk_support; @@ -28,27 +28,14 @@ private import gtkc.gtk; import icanvas; +import cairo_support; // x and y run right and up respectively -void rectangle(Context cr, Point corner1, Point corner2) { - double x = corner1.x; - double y = corner1.y; - double w = corner2.x - corner1.x; - double h = corner2.y - corner1.y; - - if (w < 0.0) { x += w; w = -w; } - if (h < 0.0) { y += h; h = -h; } - - //writefln("Rect: %f %f %f %f\n", x, y, w, h); - - cr.rectangle(x, y, w, h); -} - class Canvas : Table, ICanvas { static this() { - ORIGIN = new Point(0.0, 0.0); - INITIAL_PAGE_SIZE = new Vector(210.0, 297.0); // A4 + ORIGIN = Point2(0.0, 0.0); + INITIAL_PAGE_SIZE = Vector2(210.0, 297.0); // A4 } this(ICanvasEventHandler event_handler) { @@ -60,7 +47,7 @@ const double MM_PER_INCH = 25.4; mZoom = 0.25 * PPI / MM_PER_INCH; - mPageLeftBottom = ORIGIN.clone(); + mPageLeftBottom = ORIGIN; mPageRightTop = ORIGIN + INITIAL_PAGE_SIZE; mViewCentre = ORIGIN + INITIAL_PAGE_SIZE / 2.0; @@ -101,7 +88,7 @@ // value, lower, upper, step-inc, page-inc, page-size // Give the adjustments dummy values until we receive a configure - mHAdjustment = new Adjustment(0.0, 0.0, 1.0, 0.2, 0.5, 1.0); + mHAdjustment = new Adjustment(0.25, 0.0, 1.0, 0.2, 0.5, 0.5); mHAdjustment.addOnValueChanged(&onValueChanged); mHScrollbar = new HScrollbar(mHAdjustment); attach(mHScrollbar, @@ -110,7 +97,7 @@ AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.SHRINK, 0, 0); - mVAdjustment = new Adjustment(0.0, 0.0, 1.0, 0.2, 0.5, 0.4); + mVAdjustment = new Adjustment(0.0, 0.0, 1.0, 0.2, 0.5, 0.5); mVAdjustment.addOnValueChanged(&onValueChanged); mVScrollbar = new VScrollbar(mVAdjustment); attach(mVScrollbar, @@ -121,17 +108,17 @@ 0, 0); } - override void rel_zoom(Point screen_datum, double factor) { + override void rel_zoom(Point2 screen_datum, double factor) { // 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 old_model_datum = screen_to_model(screen_datum); - Vector pixel_distance = model_to_screen(old_model_datum - mViewCentre); + Point2 old_model_datum = screen_to_model(screen_datum); + Vector2 pixel_distance = model_to_screen(old_model_datum - mViewCentre); mZoom = clamp_zoom(factor * mZoom); mViewCentre = old_model_datum - screen_to_model(pixel_distance); - Point new_model_datum = screen_to_model(screen_datum); + Point2 new_model_datum = screen_to_model(screen_datum); update_adjustments(); //update_rulers(new_model_datum); @@ -139,7 +126,7 @@ queueDraw(); } - override void rel_pan(Vector screen_displacement) { + override void rel_pan(Vector2 screen_displacement) { mViewCentre = mViewCentre + screen_to_model(screen_displacement); update_adjustments(); @@ -157,12 +144,12 @@ bool onConfigure(GdkEventConfigure * event, Widget widget) { assert(widget is mDrawingArea); - mViewSize = new Vector(cast(double)event.width, cast(double)event.height); + mViewSize = Vector2(cast(double)event.width, cast(double)event.height); update_adjustments(); update_rulers(); - return 1; + return true; } bool onExpose(GdkEventExpose * event, Widget widget) { @@ -194,8 +181,8 @@ { // Make the paper white, with a border - Point screen_page_left_bottom = model_to_screen(mPageLeftBottom); - Point screen_page_right_top = model_to_screen(mPageRightTop); + Point2 screen_page_left_bottom = model_to_screen(mPageLeftBottom); + Point2 screen_page_right_top = model_to_screen(mPageRightTop); cr.setSourceRgba(1.0, 1.0, 1.0, 1.0); rectangle(cr, screen_page_left_bottom, screen_page_right_top); @@ -206,15 +193,15 @@ cr.stroke(); } - return 1; + return true; } bool onButtonEvent(GdkEventButton * event, Widget widget) { assert(widget is mDrawingArea); //writefln("Got button event\n"); - Point screen_point = new Point(event.x + 0.5, event.y + 0.5); - Point model_point = screen_to_model(screen_point); + Point2 screen_point = Point2(event.x + 0.5, event.y + 0.5); + Point2 model_point = screen_to_model(screen_point); auto button_event = new ButtonEvent(gtk2tk_click(event.type), gtk2tk_button(event.button), @@ -224,7 +211,7 @@ //mEventHandle.handle_button_press - return 1; + return true; } bool onKeyEvent(GdkEventKey * event, Widget widget) { @@ -234,7 +221,7 @@ //auto key_event = new KeyEvent("", // mEventHandle.handle_key(key_event); - return 1; + return true; } bool onMotionNotify(GdkEventMotion * event, Widget widget) { @@ -243,8 +230,8 @@ gtk_widget_event(mHRuler.getWidgetStruct(), cast(GdkEvent *)event); gtk_widget_event(mVRuler.getWidgetStruct(), cast(GdkEvent *)event); - Point screen_point = new Point(event.x + 0.5, event.y + 0.5); - Point model_point = screen_to_model(screen_point); + Point2 screen_point = Point2(event.x + 0.5, event.y + 0.5); + Point2 model_point = screen_to_model(screen_point); auto motion_event = new MotionEvent(screen_point, model_point, @@ -252,15 +239,15 @@ mEventHandler.handle_motion(this, motion_event); - return 1; + return true; } bool onScroll(GdkEventScroll * event, Widget widget) { assert(widget is mDrawingArea); //writefln("Got scroll\n"); - Point screen_point = new Point(event.x + 0.5, event.y + 0.5); - Point model_point = screen_to_model(screen_point); + Point2 screen_point = Point2(event.x + 0.5, event.y + 0.5); + Point2 model_point = screen_to_model(screen_point); auto scroll_event = new ScrollEvent(gtk2tk_direction(event.direction), screen_point, @@ -269,16 +256,17 @@ mEventHandler.handle_scroll(this, scroll_event); - return 1; + return true; } void onValueChanged(Adjustment adjustment) { GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct(); GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct(); - Point view_left_bottom = new Point(h_gtkAdjustment.value, v_gtkAdjustment.value); + Point2 view_left_bottom = Point2(gtk_adjustment_get_value(h_gtkAdjustment), + gtk_adjustment_get_value(v_gtkAdjustment)); writefln("%s", view_left_bottom); - Vector model_size = screen_to_model(mViewSize); + Vector2 model_size = screen_to_model(mViewSize); mViewCentre = view_left_bottom + model_size / 2.0; update_rulers(); @@ -287,10 +275,10 @@ } void update_rulers() { - Vector model_size = screen_to_model(mViewSize); + Vector2 model_size = screen_to_model(mViewSize); - Point view_left_bottom = mViewCentre - model_size / 2.0; - Point view_right_top = mViewCentre + model_size / 2.0; + Point2 view_left_bottom = mViewCentre - model_size / 2.0; + Point2 view_right_top = mViewCentre + model_size / 2.0; mHRuler.setRange(view_left_bottom.x, view_right_top.x, @@ -303,36 +291,36 @@ } void update_adjustments() { - Vector model_size = screen_to_model(mViewSize); + Vector2 model_size = screen_to_model(mViewSize); - Point view_left_bottom = mViewCentre - model_size / 2.0; - Point view_right_top = mViewCentre + model_size / 2.0; + Point2 view_left_bottom = mViewCentre - model_size / 2.0; + Point2 view_right_top = mViewCentre + model_size / 2.0; // Adjust the canvas size if necessary mCanvasLeftBottom = min_extents(mCanvasLeftBottom, view_left_bottom); mCanvasRightTop = max_extents(mCanvasRightTop, view_right_top); - Vector canvas_size = mCanvasRightTop - mCanvasLeftBottom; - Vector page_size = mPageRightTop - mPageLeftBottom; + Vector2 canvas_size = mCanvasRightTop - mCanvasLeftBottom; + Vector2 page_size = mPageRightTop - mPageLeftBottom; // Update the adjustments GtkAdjustment * h_gtkAdjustment = mHAdjustment.getAdjustmentStruct(); GtkAdjustment * v_gtkAdjustment = mVAdjustment.getAdjustmentStruct(); - h_gtkAdjustment.lower = mCanvasLeftBottom.x; - h_gtkAdjustment.upper = mCanvasRightTop.x; - h_gtkAdjustment.value = view_left_bottom.x; - h_gtkAdjustment.step_increment = canvas_size.x / 10.0; - h_gtkAdjustment.page_increment = canvas_size.x / 5.0; - h_gtkAdjustment.page_size = model_size.x; + gtk_adjustment_set_lower(h_gtkAdjustment, mCanvasLeftBottom.x); + gtk_adjustment_set_upper(h_gtkAdjustment, mCanvasRightTop.x); + gtk_adjustment_set_value(h_gtkAdjustment, view_left_bottom.x); + gtk_adjustment_set_step_increment(h_gtkAdjustment, canvas_size.x / 10.0); + gtk_adjustment_set_page_increment(h_gtkAdjustment, canvas_size.x / 5.0); + gtk_adjustment_set_page_size(h_gtkAdjustment, model_size.x); - v_gtkAdjustment.lower = mCanvasLeftBottom.y; - v_gtkAdjustment.upper = mCanvasRightTop.y; - v_gtkAdjustment.value = view_left_bottom.y; - v_gtkAdjustment.step_increment = canvas_size.y / 10.0; - v_gtkAdjustment.page_increment = canvas_size.y / 5.0; - v_gtkAdjustment.page_size = model_size.y; + gtk_adjustment_set_lower(v_gtkAdjustment, mCanvasLeftBottom.y); + gtk_adjustment_set_upper(v_gtkAdjustment, mCanvasRightTop.y); + gtk_adjustment_set_value(v_gtkAdjustment, view_left_bottom.y); + gtk_adjustment_set_step_increment(v_gtkAdjustment, canvas_size.y / 10.0); + gtk_adjustment_set_page_increment(v_gtkAdjustment, canvas_size.y / 5.0); + gtk_adjustment_set_page_size(v_gtkAdjustment, model_size.y); mHAdjustment.changed(); mHAdjustment.valueChanged(); @@ -340,32 +328,32 @@ mVAdjustment.valueChanged(); } - Point model_to_screen(Point model) { return ORIGIN + mViewSize / 2.0 + mZoom * (model - mViewCentre); } - Point screen_to_model(Point screen) { return mViewCentre + (screen - mViewSize / 2.0 - ORIGIN) / mZoom; } - Vector model_to_screen(Vector model) { return mZoom * model; } - Vector screen_to_model(Vector screen) { return screen / mZoom; } + Point2 model_to_screen(Point2 model) { return ORIGIN + mViewSize / 2.0 + mZoom * (model - mViewCentre); } + Point2 screen_to_model(Point2 screen) { return mViewCentre + (screen - mViewSize / 2.0 - ORIGIN) / mZoom; } + Vector2 model_to_screen(Vector2 model) { return mZoom * model; } + Vector2 screen_to_model(Vector2 screen) { return screen / mZoom; } double model_to_screen(double model) { return mZoom * model; } double screen_to_model(double screen) { return screen / mZoom; } double clamp_zoom(double zoom) { return clamp(zoom, 0.1, 10.0); } - static const Point ORIGIN; - static const Vector INITIAL_PAGE_SIZE; + static const Point2 ORIGIN; + static const Vector2 INITIAL_PAGE_SIZE; ICanvasEventHandler mEventHandler; // Model units are in millimetres // Screen units are in pixels - double mZoom; // pixels-per-mm - Point mViewCentre; // model: where in the model is the centre of our view + double mZoom; // pixels-per-mm + Point2 mViewCentre; // model: where in the model is the centre of our view - Point mCanvasLeftBottom; // model: bottom left corner of canvas - Point mCanvasRightTop; // model: top right corner of canvas - Point mPageLeftBottom; // model: bottom left corner of page - Point mPageRightTop; // model: top right corner of page + Point2 mCanvasLeftBottom; // model: bottom left corner of canvas + Point2 mCanvasRightTop; // model: top right corner of canvas + Point2 mPageLeftBottom; // model: bottom left corner of page + Point2 mPageRightTop; // model: top right corner of page - Vector mViewSize; // screen: size of view window in pixels + Vector2 mViewSize; // screen: size of view window in pixels HRuler mHRuler; VRuler mVRuler; diff -r c18e3f93d114 -r d6f44347373d gui.d --- a/gui.d Wed May 13 17:50:25 2009 +0930 +++ b/gui.d Fri Jul 10 15:15:27 2009 +0930 @@ -1,7 +1,7 @@ module gui; import canvas; -import handler; +import tool_stack; import gtk.Main; import gtk.MainWindow; @@ -14,7 +14,6 @@ import tk.geometry2; void main(string[] args) { - /* Main.init(args); auto window = new MainWindow("Title"); auto event_handler = new ToolStack(); @@ -22,7 +21,9 @@ window.add(canvas); window.showAll(); Main.run(); - */ + + /* + Point2 p3 = Point2.DEFAULT; Point2 p1 = Point2(3.0, 5.0); writefln("%s", p1); @@ -34,4 +35,5 @@ Rectangle2 r = Rectangle2(p1, p2); writefln("%s", r); + */ } diff -r c18e3f93d114 -r d6f44347373d handler.d --- a/handler.d Wed May 13 17:50:25 2009 +0930 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -module handler; - -import std.stdio; - -private import icanvas; -private import tk.types; -private import tk.geometry; -private import tk.events; -//IToolStack -class ToolStack : ICanvasEventHandler { - override bool handle_button_press(ICanvas canvas, ButtonEvent event) { - writefln("%s", event); - return true; - } - - override bool handle_button_release(ICanvas canvas, ButtonEvent event) { - writefln("%s", event); - return true; - } - - override bool handle_key_press(ICanvas canvas, KeyEvent event) { - writefln("%s", event); - return true; - } - - override bool handle_key_release(ICanvas canvas, KeyEvent event) { - writefln("%s", event); - return true; - } - - override bool handle_motion(ICanvas canvas, MotionEvent event) { - writefln("%s", event); - return true; - } - - override bool handle_scroll(ICanvas canvas, ScrollEvent event) { - writefln("%s", event); - - if (event.mask.query(Modifier.CONTROL)) { - // Zoom about the pointer - double zoom = 1.44; - - if (event.scroll_direction == ScrollDirection.DOWN) { - zoom = 1.0 / zoom; - } - - canvas.rel_zoom(event.screen_point(), zoom); - } - else { - // Scroll - - const double AMOUNT = 30.0; - Vector v; - - if (event.mask.query(Modifier.SHIFT)) { - // left to right - v = new Vector(AMOUNT, 0.0); - } - else { - // down to up - v = new Vector(0.0, AMOUNT); - } - - if (event.scroll_direction == ScrollDirection.UP) { - v = -v; - } - - canvas.rel_pan(v); - } - - return true; - } - - /* - override void push(Tool tool) { - } - - override void pop() { - } - - override void replace(Tool tool) { - } - - private { - Tool[] mTools; - } - */ -}; diff -r c18e3f93d114 -r d6f44347373d icanvas.d --- a/icanvas.d Wed May 13 17:50:25 2009 +0930 +++ b/icanvas.d Fri Jul 10 15:15:27 2009 +0930 @@ -1,10 +1,10 @@ module icanvas; -import tk.geometry; +import tk.geometry2; interface ICanvas { - void rel_zoom(Point screen_datum, double factor); - void rel_pan(Vector screen_displacement); + void rel_zoom(Point2 screen_datum, double factor); + void rel_pan(Vector2 screen_displacement); //void damage(); } diff -r c18e3f93d114 -r d6f44347373d itoolstack.d --- a/itoolstack.d Wed May 13 17:50:25 2009 +0930 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -module itoolstack; - -interface IToolStack { - void push(Tool tool); - void pop(); - void replace(Tool tool); -} - -abstract class Tool : ICanvasEventHandler { - /* - abstract bool is_sticky(); - abstract bool is_replaceable(); - */ - - abstract void start(IToolStack tool_stack); - abstract void stop(IToolStack tool_stack); -} - diff -r c18e3f93d114 -r d6f44347373d standard_tools.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/standard_tools.d Fri Jul 10 15:15:27 2009 +0930 @@ -0,0 +1,56 @@ +module standard_tools; + +final class PanTool : Tool { + override bool handle_scroll(ICanvas canvas, ScrollEvent event) { + const double AMOUNT = 30.0; + Vector2 v; + + if (event.mask.query(Modifier.SHIFT)) { + // left to right + v = new Vector2(AMOUNT, 0.0); + } + else { + // down to up + v = new Vector2(0.0, AMOUNT); + } + + if (event.scroll_direction == ScrollDirection.UP) { + v = -v; + } + + canvas.rel_pan(v); + + return true; + } + + bool handle_button_press(ICanvas canvas, ButtonEvent event) { + } + + bool handle_button_release(ICanvas canvas, ButtonEvent event) { + } + + bool handle_motion(ICanvas canvas, MotionEvent event) { + } +} + +final class ZoomTool { + static invariant double ZOOM = 1.44; + + override bool handle_scroll(ICanvas canvas, ScrollEvent event) { + if (event.mask.query(Modifier.CONTROL)) { + // Zoom about the pointer + double zoom = 1.44; + + if (event.scroll_direction == ScrollDirection.DOWN) { + zoom = 1.0 / zoom; + } + + canvas.rel_zoom(event.screen_point(), zoom); + + return true; + } + else { + return false; + } + } +} diff -r c18e3f93d114 -r d6f44347373d tk/events.d --- a/tk/events.d Wed May 13 17:50:25 2009 +0930 +++ b/tk/events.d Fri Jul 10 15:15:27 2009 +0930 @@ -1,7 +1,7 @@ module tk.events; import tk.types; -import tk.geometry; +import tk.geometry2; // // Should we pass the screen and model points into @@ -66,26 +66,26 @@ } abstract class PointerEvent : InputEvent { - this(Point screen_point, Point model_point, Mask mask) { + this(Point2 screen_point, Point2 model_point, Mask mask) { super(mask); - mScreenPoint = screen_point; - mModelPoint = model_point; + mScreenPoint2 = screen_point; + mModelPoint2 = model_point; } - Point screen_point() { return mScreenPoint; } - Point model_point() { return mModelPoint; } + Point2 screen_point() { return mScreenPoint2; } + Point2 model_point() { return mModelPoint2; } private { - Point mScreenPoint; - Point mModelPoint; + Point2 mScreenPoint2; + Point2 mModelPoint2; } } final class ButtonEvent : PointerEvent { this(ButtonPress button_press, ButtonNumber button_number, - Point screen_point, - Point model_point, + Point2 screen_point, + Point2 model_point, Mask mask) { super(screen_point, model_point, mask); mButtonPress = button_press; @@ -93,7 +93,7 @@ } override string toString() { - return std.string.format("Button event: %s, %s, %s, %s, %s", mButtonPress, mButtonNumber, mScreenPoint, mModelPoint, mMask); + return std.string.format("Button event: %s, %s, %s, %s, %s", mButtonPress, mButtonNumber, mScreenPoint2, mModelPoint2, mMask); } ButtonPress button_press() { return mButtonPress; } @@ -106,28 +106,28 @@ } final class MotionEvent : PointerEvent { - this(Point screen_point, - Point model_point, + this(Point2 screen_point, + Point2 model_point, Mask mask) { super(screen_point, model_point, mask); } override string toString() { - return std.string.format("Motion event: %s, %s, %s", mScreenPoint, mModelPoint, mMask); + return std.string.format("Motion event: %s, %s, %s", mScreenPoint2, mModelPoint2, mMask); } } final class ScrollEvent : PointerEvent { this(ScrollDirection scroll_direction, - Point screen_point, - Point model_point, + Point2 screen_point, + Point2 model_point, Mask mask) { super(screen_point, model_point, mask); mScrollDirection = scroll_direction; } override string toString() { - return std.string.format("Scroll event: %s, %s, %s, %s", mScrollDirection, mScreenPoint, mModelPoint, mMask); + return std.string.format("Scroll event: %s, %s, %s, %s", mScrollDirection, mScreenPoint2, mModelPoint2, mMask); } ScrollDirection scroll_direction() { return mScrollDirection; } diff -r c18e3f93d114 -r d6f44347373d tk/geometry2.d --- a/tk/geometry2.d Wed May 13 17:50:25 2009 +0930 +++ b/tk/geometry2.d Fri Jul 10 15:15:27 2009 +0930 @@ -2,8 +2,15 @@ private import std.stdio; private import std.math; +private import tk.misc; struct Point2 { + static immutable Point2 DEFAULT; + + static this() { + DEFAULT = Point2(0.0, 0.0); + } + this(in double x, in double y) { _x = x; _y = y; @@ -33,7 +40,21 @@ } } +Point2 min_extents(in Point2 a, in Point2 b) { + return Point2(min(a.x, b.x), min(a.y, b.y)); +} + +Point2 max_extents(in Point2 a, in Point2 b) { + return Point2(max(a.x, b.x), max(a.y, b.y)); +} + struct Vector2 { + static Vector2 DEFAULT; + + static this() { + DEFAULT = Vector2(0.0, 0.0); + } + this(in double x, in double y) { _x = x; _y = y; @@ -51,11 +72,11 @@ return Vector2(-_x, -_y); } - Vector2 opMul_r(double d) const { + Vector2 opMul_r(in double d) const { return Vector2(d * _x, d * _y); } - Vector2 opDiv(double d) const { + Vector2 opDiv(in double d) const { return Vector2(_x / d, _y / d); } @@ -76,39 +97,102 @@ } struct Rectangle2 { - this(in Point2 position, Vector2 size) { + static Rectangle2 DEFAULT; + + static this() { + DEFAULT = Rectangle2(Point2.DEFAULT, Vector2.DEFAULT); + } + + /* + static Rectangle2 from_arbitrary_corners(in Point2 corner1, in Point2 corner2) { + } + */ + + this(in Point2 position, in Vector2 size) { this(position.x, position.y, size.x, size.y); } - this(Point2 corner1, Point2 corner2) { + this(in Point2 corner1, in Point2 corner2) { this(corner1.x, corner1.y, corner2.x - corner1.x, corner2.y - corner1.y); } + Point2 position() const { + return _position; + } + + alias position min_corner; + + Point2 max_corner() const { + return _position + _size; + } + + bool valid() const { + return _size.x > 0.0 & _size.y > 0.0; + } + + bool invalid() const { + return !valid(); + } + + double area() const { + return _size.x * _size.y; + } + // Intersection Rectangle2 opAnd(in Rectangle2 r) const { - // FIXME - return Rectangle2(3.2, 5.3, 3.2, 2.3); + if (invalid() || r.invalid()) { + return DEFAULT; + } + else { + Point2 max = min_extents(max_corner(), r.max_corner()); + Point2 min = max_extents(min_corner(), r.min_corner()); + + if (max.x < min.x || max.y < min.y) { + return DEFAULT; + } + else { + return Rectangle2(min, max); + } + } } // Union Rectangle2 opOr(in Rectangle2 r) const { - // FIXME - return Rectangle2(3.2, 5.3, 5.8, 2.1); + if (invalid()) { + return r; + } + else if (r.invalid()) { + return this; + } + else { + return Rectangle2(min_extents(min_corner(), r.min_corner()), + max_extents(max_corner(), r.max_corner())); + } } - string toString() { - return std.string.format("{%s, %s}", mPosition, mSize); + /* + Rectangle2 moved(in Vector2 displacement) { + return Rectangle2( + } + Rectangle2 resized(in Vector2 new_size) { + } + Rectangle2 repositioned(in Point2 new_position) { + } + */ + + string toString() /* const */ { + return std.string.format("{%s, %s}", _position, _size); } private { this(double x, double y, double w, double h) { if (w < 0.0) { x += w; w = -w; } if (h < 0.0) { y += h; h = -h; } - mPosition = Point2(x, y); - mSize = Vector2(w, h); + _position = Point2(x, y); + _size = Vector2(w, h); } - Point2 mPosition; - Vector2 mSize; + Point2 _position; + Vector2 _size; } } diff -r c18e3f93d114 -r d6f44347373d tk/types.d --- a/tk/types.d Wed May 13 17:50:25 2009 +0930 +++ b/tk/types.d Fri Jul 10 15:15:27 2009 +0930 @@ -40,10 +40,6 @@ } class Mask { - this() { - //mBits = 0; - } - void add(Modifier modifier) { mBits |= bit(modifier); } void remove(Modifier modifier) { mBits &= ~bit(modifier); } bool query(Modifier modifier) { return cast(bool)(mBits & bit(modifier)); } diff -r c18e3f93d114 -r d6f44347373d tool.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool.d Fri Jul 10 15:15:27 2009 +0930 @@ -0,0 +1,20 @@ +module tool; + +import icanvas; + +interface IToolStack { + void push(Tool tool); + void pop(); + void replace(Tool tool); +} + +abstract class Tool : ICanvasEventHandler { + /* + abstract bool is_sticky(); + abstract bool is_replaceable(); + */ + + abstract void start(IToolStack tool_stack); + abstract void stop(IToolStack tool_stack); +} + diff -r c18e3f93d114 -r d6f44347373d tool_stack.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tool_stack.d Fri Jul 10 15:15:27 2009 +0930 @@ -0,0 +1,91 @@ +module tool_stack; + +import std.stdio; + +private import icanvas; +private import tk.types; +private import tk.geometry2; +private import tk.events; + +//IToolStack + +class ToolStack : ICanvasEventHandler { + override bool handle_button_press(ICanvas canvas, ButtonEvent event) { + writefln("%s", event); + return true; + } + + override bool handle_button_release(ICanvas canvas, ButtonEvent event) { + writefln("%s", event); + return true; + } + + override bool handle_key_press(ICanvas canvas, KeyEvent event) { + writefln("%s", event); + return true; + } + + override bool handle_key_release(ICanvas canvas, KeyEvent event) { + writefln("%s", event); + return true; + } + + override bool handle_motion(ICanvas canvas, MotionEvent event) { + writefln("%s", event); + return true; + } + + override bool handle_scroll(ICanvas canvas, ScrollEvent event) { + writefln("%s", event); + + if (event.mask.query(Modifier.CONTROL)) { + // Zoom about the pointer + double zoom = 1.44; + + if (event.scroll_direction == ScrollDirection.DOWN) { + zoom = 1.0 / zoom; + } + + canvas.rel_zoom(event.screen_point(), zoom); + } + else { + // Scroll + + const double AMOUNT = 30.0; + Vector2 v; + + if (event.mask.query(Modifier.SHIFT)) { + // left to right + v = Vector2(AMOUNT, 0.0); + } + else { + // down to up + v = Vector2(0.0, AMOUNT); + } + + if (event.scroll_direction == ScrollDirection.UP) { + v = -v; + } + + canvas.rel_pan(v); + } + + return true; + } + + /* + override void push(Tool tool) { + } + + override void pop() { + } + + override void replace(Tool tool) { + } + + private { + Tool[] mTools; + int mGrabbedToolIndex; // -1 for none + } + */ +} diff -r c18e3f93d114 -r d6f44347373d tools.d --- a/tools.d Wed May 13 17:50:25 2009 +0930 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -module tools; - -final class PanTool : Tool { - override bool handle_scroll(ICanvas canvas, ScrollEvent event) { - const double AMOUNT = 30.0; - Vector v; - - if (event.mask.query(Modifier.SHIFT)) { - // left to right - v = new Vector(AMOUNT, 0.0); - } - else { - // down to up - v = new Vector(0.0, AMOUNT); - } - - if (event.scroll_direction == ScrollDirection.UP) { - v = -v; - } - - canvas.rel_pan(v); - - return true; - } -} - -final class ZoomTool { - override bool handle_scroll(ICanvas canvas, ScrollEvent event) { - if (event.mask.query(Modifier.CONTROL)) { - // Zoom about the pointer - double zoom = 1.44; - - if (event.scroll_direction == ScrollDirection.DOWN) { - zoom = 1.0 / zoom; - } - - canvas.rel_zoom(event.screen_point(), zoom); - - return true; - } - else { - return false; - } - } -}