Mercurial > projects > doodle
diff doodle/gtk/canvas.d @ 63:20d6327c4a75
Event progress. Got key press/release working and panning via keyboard.
author | daveb |
---|---|
date | Thu, 12 Aug 2010 16:35:24 +0930 |
parents | 6c3993f4c3eb |
children | eb5436b47d13 |
line wrap: on
line diff
--- a/doodle/gtk/canvas.d Thu Aug 12 11:48:55 2010 +0930 +++ b/doodle/gtk/canvas.d Thu Aug 12 16:35:24 2010 +0930 @@ -13,9 +13,6 @@ import cairo.Surface; - import std.math; - import std.stdio; - import gtk.Widget; import gtk.Toolbar; import gtk.Table; @@ -30,6 +27,13 @@ import gdk.Drawable; import gtkc.gtk; + import gtkc.gtktypes; + //import gtkc.gdktypes; + + import std.math; + import std.stdio; + + import core.stdc.string : strlen; } // x and y run right and up respectively @@ -46,7 +50,7 @@ // zoom about a point (hold control and move scroll wheel) // resize the widget -class Canvas : Table, IViewport { +final class Canvas : Table, IViewport { this(in Layer[] layers, IEventHandler eventHandler, IGrid grid, in double ppi) { super(3, 3, 0); @@ -85,14 +89,26 @@ _drawingArea.addOnRealize(&onRealize); _drawingArea.addOnConfigure(&onConfigure); _drawingArea.addOnExpose(&onExpose); - _drawingArea.addOnButtonPress(&onButtonPress); + _drawingArea.addOnButtonPress(&onButtonPress); // FIXME merge delegate with next _drawingArea.addOnButtonRelease(&onButtonRelease); - _drawingArea.addOnKeyPress(&onKeyEvent); - _drawingArea.addOnKeyRelease(&onKeyEvent); + _drawingArea.addOnKeyPress(&onKeyPressEvent); // FIXME merge delegate with next + _drawingArea.addOnKeyRelease(&onKeyReleaseEvent); _drawingArea.addOnMotionNotify(&onMotionNotify); _drawingArea.addOnScroll(&onScroll); - _drawingArea.addOnEnterNotify(&onEnterNotify); + _drawingArea.addOnEnterNotify(&onEnterNotify); // FIXME merge delegate with next _drawingArea.addOnLeaveNotify(&onLeaveNotify); + + _drawingArea.addOnFocusIn(&onFocusIn); + _drawingArea.addOnFocusOut(&onFocusOut); + _drawingArea.addOnMoveFocus(&onMoveFocus); + /* + _drawingArea.addOnGrabBroken(&onGrabBroken); + */ + _drawingArea.addOnGrabFocus(&onGrabFocus); + _drawingArea.addOnGrabNotify(&onGrabNotify); + // addOnPopupMenu + // addOnQueryTooltip + // addOnSelection* _drawingArea.setEvents(EventMask.EXPOSURE_MASK | EventMask.POINTER_MOTION_MASK | EventMask.POINTER_MOTION_HINT_MASK | @@ -106,6 +122,8 @@ EventMask.FOCUS_CHANGE_MASK | EventMask.SCROLL_MASK); + _drawingArea.setCanFocus(true); + attach(_drawingArea, 1, 2, 1, 2, @@ -121,7 +139,8 @@ attach(_hScrollbar, 1, 2, 2, 3, - AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.SHRINK, + AttachOptions.FILL | AttachOptions.EXPAND, + AttachOptions.SHRINK, 0, 0); _vAdjustment = new Adjustment(0.0, 0.0, 1.0, 0.2, 0.5, 0.5); @@ -138,7 +157,7 @@ // IViewport overrides: - override void zoomRelative(in Point pixelDatum, in double factor) { + void zoomRelative(in Point pixelDatum, in 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 @@ -148,51 +167,58 @@ _zoom = clampZoom(factor * _zoom); _viewCentre = oldModelDatum - pixelToModel(pixelDistance); + consolidateBounds; + updateAdjustments; updateRulers; _grid.zoomChanged(_zoom); queueDraw; } - override void panRelative(in Vector pixelDisplacement) { + void panRelative(in Vector pixelDisplacement) { _viewCentre = _viewCentre + pixelToModel(pixelDisplacement); + consolidateBounds; + updateAdjustments; updateRulers; queueDraw; } - override void setCursor(in Cursor cursor) { - CursorType cursor_type; + void setCursor(in Cursor cursor) { + CursorType cursorType; switch (cursor) { case Cursor.DEFAULT: - cursor_type = CursorType.ARROW; + cursorType = CursorType.ARROW; break; case Cursor.HAND: - cursor_type = CursorType.HAND1; + cursorType = CursorType.HAND1; break; case Cursor.CROSSHAIR: - cursor_type = CursorType.CROSSHAIR; + cursorType = CursorType.CROSSHAIR; + break; + case Cursor.PENCIL: + cursorType = CursorType.PENCIL; break; default: assert(0); } - _drawingArea.setCursor(new gdk.Cursor.Cursor(cursor_type)); + _drawingArea.setCursor(new gdk.Cursor.Cursor(cursorType)); } - override void damageModel(in Rectangle area) { + void damageModel(in Rectangle area) { _damage = _damage | modelToPixel(area); } - override void damagePixel(in Rectangle area) { + void damagePixel(in Rectangle area) { _damage = _damage | area; } private { - void initialise() { + void initialiseBounds() { Rectangle layerBounds = Rectangle.DEFAULT; foreach (ref layer; _layers) { @@ -201,11 +227,12 @@ assert(layerBounds.valid); + // FIXME use a function that grows a rectangle about its centre + // and change 2.0 to a class-level constant Rectangle paddedLayerBounds = expand(move(layerBounds, - layerBounds.size), 2.0 * layerBounds.size); // - const double MM_PER_INCH = 25.4; _zoom = 0.25 * _ppi / MM_PER_INCH; _canvasBounds = paddedLayerBounds; @@ -241,10 +268,9 @@ _viewSize = Vector(cast(double)event.width, cast(double)event.height); - - if (!_hadConfigure) { - initialise; - _hadConfigure = true; + if (!_boundsValid) { + initialiseBounds; + _boundsValid = true; } else { consolidateBounds; @@ -260,32 +286,32 @@ int width, height; dr.getSize(width, height); - trace("Got expose %dx%d\n", width, height); + //trace("Got expose %dx%d\n", width, height); scope modelCr = new Context(dr); scope pixelCr = new Context(dr); - Rectangle pixel_damage = + Rectangle pixelDamage = event is null ? Rectangle(Point(0.0, 0.0), _viewSize) : Rectangle(Point(cast(double)event.area.x, _viewSize.y - cast(double)(event.area.y + event.area.height)), Vector(cast(double)event.area.width, cast(double)event.area.height)); - Rectangle model_damage = pixelToModel(pixel_damage); + Rectangle modelDamage = pixelToModel(pixelDamage); - //trace("Pixel damage: %s, model damage: %s", pixel_damage, model_damage); + //trace("Pixel damage: %s, model damage: %s", pixelDamage, modelDamage); modelCr.save; pixelCr.save; { // Setup model context and clip - GtkAdjustment * h_gtkAdjustment = _hAdjustment.getAdjustmentStruct; - GtkAdjustment * v_gtkAdjustment = _vAdjustment.getAdjustmentStruct; + GtkAdjustment * hGtkAdjustment = _hAdjustment.getAdjustmentStruct; + GtkAdjustment * vGtkAdjustment = _vAdjustment.getAdjustmentStruct; modelCr.scale(_zoom, -_zoom); - modelCr.translate(-gtk_adjustment_get_value(h_gtkAdjustment), - -gtk_adjustment_get_value(v_gtkAdjustment) - gtk_adjustment_get_page_size(v_gtkAdjustment)); + modelCr.translate(-gtk_adjustment_get_value(hGtkAdjustment), + -gtk_adjustment_get_value(vGtkAdjustment) - gtk_adjustment_get_page_size(vGtkAdjustment)); - rectangle(modelCr, model_damage); + rectangle(modelCr, modelDamage); modelCr.clip; // Setup pixel context and clip @@ -293,7 +319,7 @@ pixelCr.translate(0.0, _viewSize.y); pixelCr.scale(1.0, -1.0); - rectangle(pixelCr, pixel_damage); + rectangle(pixelCr, pixelDamage); pixelCr.clip; // Fill the background @@ -301,7 +327,7 @@ pixelCr.save; { // Make the window light grey pixelCr.setSourceRgba(0.9, 0.9, 0.9, 1.0); - rectangle(pixelCr, pixel_damage); + rectangle(pixelCr, pixelDamage); pixelCr.fill; } pixelCr.restore; @@ -309,7 +335,7 @@ foreach(ref layer; _layers) { modelCr.save; pixelCr.save; { - layer.draw(this, pixel_damage, pixelCr, model_damage, modelCr); + layer.draw(this, pixelDamage, pixelCr, modelDamage, modelCr); } pixelCr.restore; modelCr.restore; } } pixelCr.restore; modelCr.restore; @@ -319,7 +345,7 @@ bool onButtonPress(GdkEventButton * event, Widget widget) { assert(widget is _drawingArea); - trace("Got button event\n"); + //trace("Got button event\n"); Point pixelPoint = Point(event.x + 0.5, _viewSize.y - (event.y + 0.5)); Point modelPoint = pixelToModel(pixelPoint); @@ -356,12 +382,45 @@ return true; } - bool onKeyEvent(GdkEventKey * event, Widget widget) { + /* + public struct GdkEventKey { + GdkEventType type; + GdkWindow *window; + byte sendEvent; + uint time; + uint state; + uint keyval; + int length; + char *string; + ushort hardwareKeycode; + ubyte group; + uint bitfield0; + //uint isModifier : 1; + } + */ + bool onKeyPressEvent(GdkEventKey * event, Widget widget) { assert(widget is _drawingArea); - //writefln("Got key event\n"); + message("Got key event"); + + auto keyEvent = new KeyEvent(event.string[0..strlen(event.string)].idup, + event.keyval, + gtk2tkMask(event.state)); + message("Got key press %s", keyEvent); + _eventHandler.handleKeyPress(this, keyEvent); + + fixDamage; - //auto key_event = new KeyEvent("", - // mEventHandle.handle_key(key_event); + return true; + } + + bool onKeyReleaseEvent(GdkEventKey * event, Widget widget) { + assert(widget is _drawingArea); + + auto keyEvent = new KeyEvent(event.string[0..strlen(event.string)].idup, + event.keyval, + gtk2tkMask(event.state)); + message("Got key release %s", keyEvent); + _eventHandler.handleKeyRelease(this, keyEvent); fixDamage; @@ -377,11 +436,11 @@ Point pixelPoint = Point(event.x + 0.5, _viewSize.y - (event.y + 0.5)); Point modelPoint = pixelToModel(pixelPoint); - auto motion_event = new MotionEvent(pixelPoint, + auto motionEvent = new MotionEvent(pixelPoint, modelPoint, gtk2tkMask(event.state)); - _eventHandler.handleMotion(this, motion_event); + _eventHandler.handleMotion(this, motionEvent); fixDamage; @@ -395,12 +454,12 @@ Point pixelPoint = Point(event.x + 0.5, _viewSize.y - (event.y + 0.5)); Point modelPoint = pixelToModel(pixelPoint); - auto scroll_event = new ScrollEvent(gtk2tkDirection(event.direction), + auto scrollEvent = new ScrollEvent(gtk2tkDirection(event.direction), pixelPoint, modelPoint, gtk2tkMask(event.state)); - _eventHandler.handleScroll(this, scroll_event); + _eventHandler.handleScroll(this, scrollEvent); fixDamage; @@ -436,24 +495,61 @@ bool onEnterNotify(GdkEventCrossing * event, Widget widget) { assert(widget is _drawingArea); - //writefln("Enter %d %d %d", cast(int)event.mode, event.focus, event.state); + message("Enter %d %d %d", cast(int)event.mode, event.focus, event.state); // TODO return true; } bool onLeaveNotify(GdkEventCrossing * event, Widget widget) { assert(widget is _drawingArea); - //writefln("Leave %d %d %d", cast(int)event.mode, event.focus, event.state); + message("Leave %d %d %d", cast(int)event.mode, event.focus, event.state); // TODO return true; } + /* + public struct GdkEventFocus { + GdkEventType type; + GdkWindow *window; + byte sendEvent; + short inn; + } + */ + bool onFocusIn(GdkEventFocus * event, Widget widget) { + trace("onFocusIn"); + return true; + } + + bool onFocusOut(GdkEventFocus * event, Widget widget) { + trace("onFocusOut"); + return true; + } + + void onMoveFocus(GtkDirectionType direction, Widget widget) { + trace("onMoveFocus"); + } + + /* + bool onGrabBroken(Event event, Widget widget) { + trace("onGrabBroken"); + return true; + } + */ + + void onGrabFocus(Widget widget) { + trace("onGrabFocus"); + } + + void onGrabNotify(gboolean what, Widget widget){ + trace("onGrabNotify"); + } + void onValueChanged(Adjustment adjustment) { - GtkAdjustment * h_gtkAdjustment = _hAdjustment.getAdjustmentStruct; - GtkAdjustment * v_gtkAdjustment = _vAdjustment.getAdjustmentStruct; + GtkAdjustment * hGtkAdjustment = _hAdjustment.getAdjustmentStruct; + GtkAdjustment * vGtkAdjustment = _vAdjustment.getAdjustmentStruct; - Point viewLeftTop = Point(gtk_adjustment_get_value(h_gtkAdjustment), - gtk_adjustment_get_value(v_gtkAdjustment)); + Point viewLeftTop = Point(gtk_adjustment_get_value(hGtkAdjustment), + gtk_adjustment_get_value(vGtkAdjustment)); Vector modelSize = pixelToModel(_viewSize); @@ -501,22 +597,22 @@ // Update the adjustments - GtkAdjustment * h_gtkAdjustment = _hAdjustment.getAdjustmentStruct; - GtkAdjustment * v_gtkAdjustment = _vAdjustment.getAdjustmentStruct; + GtkAdjustment * hGtkAdjustment = _hAdjustment.getAdjustmentStruct; + GtkAdjustment * vGtkAdjustment = _vAdjustment.getAdjustmentStruct; - gtk_adjustment_set_lower(h_gtkAdjustment, _canvasBounds.minCorner.x); - gtk_adjustment_set_upper(h_gtkAdjustment, _canvasBounds.maxCorner.x); - gtk_adjustment_set_value(h_gtkAdjustment, viewLeftBottom.x); - gtk_adjustment_set_step_increment(h_gtkAdjustment, _canvasBounds.size.x / 16.0); - gtk_adjustment_set_page_increment(h_gtkAdjustment, _canvasBounds.size.x / 4.0); - gtk_adjustment_set_page_size(h_gtkAdjustment, modelSize.x); + gtk_adjustment_set_lower(hGtkAdjustment, _canvasBounds.minCorner.x); + gtk_adjustment_set_upper(hGtkAdjustment, _canvasBounds.maxCorner.x); + gtk_adjustment_set_value(hGtkAdjustment, viewLeftBottom.x); + gtk_adjustment_set_step_increment(hGtkAdjustment, _canvasBounds.size.x / 16.0); + gtk_adjustment_set_page_increment(hGtkAdjustment, _canvasBounds.size.x / 4.0); + gtk_adjustment_set_page_size(hGtkAdjustment, modelSize.x); - gtk_adjustment_set_lower(v_gtkAdjustment, _canvasBounds.minCorner.y); - gtk_adjustment_set_upper(v_gtkAdjustment, _canvasBounds.maxCorner.y); - gtk_adjustment_set_value(v_gtkAdjustment, viewLeftBottom.y); - gtk_adjustment_set_step_increment(v_gtkAdjustment, _canvasBounds.size.y / 16.0); - gtk_adjustment_set_page_increment(v_gtkAdjustment, _canvasBounds.size.y / 4.0); - gtk_adjustment_set_page_size(v_gtkAdjustment, modelSize.y); + gtk_adjustment_set_lower(vGtkAdjustment, _canvasBounds.minCorner.y); + gtk_adjustment_set_upper(vGtkAdjustment, _canvasBounds.maxCorner.y); + gtk_adjustment_set_value(vGtkAdjustment, viewLeftBottom.y); + gtk_adjustment_set_step_increment(vGtkAdjustment, _canvasBounds.size.y / 16.0); + gtk_adjustment_set_page_increment(vGtkAdjustment, _canvasBounds.size.y / 4.0); + gtk_adjustment_set_page_size(vGtkAdjustment, modelSize.y); _hAdjustment.changed; _hAdjustment.valueChanged; @@ -526,18 +622,14 @@ void fixDamage() { if (_damage.valid) { - //writefln("Damage: %s", _damage); int x, y, w, h; _damage.getQuantised(x, y, w, h); _drawingArea.queueDrawArea(x, cast(int)_viewSize.y - (y + h), w, h); _damage = Rectangle.DEFAULT; } - else { - //writefln("No damage"); - } } - double clampZoom(in double zoom) { return clamp(zoom, 0.2, 10.0); } + static double clampZoom(in double zoom) { return clamp(zoom, 0.2, 10.0); } Point modelToPixel(in Point model) const { return Point.DEFAULT + _viewSize / 2.0 + _zoom * (model - _viewCentre); @@ -566,9 +658,10 @@ void onRealize(Widget widget) { assert(widget is _drawingArea); //writefln("Got realize\n"); + _drawingArea.grabFocus(); } - bool _hadConfigure; + bool _boundsValid; Rectangle _damage; // pixels // Model units are in millimetres @@ -591,5 +684,7 @@ IEventHandler _eventHandler; IGrid _grid; double _ppi; + + static immutable MM_PER_INCH = 25.4; } }