# HG changeset patch # User David Bryant # Date 1348646791 -34200 # Node ID 752676232e4b0bacc0151955b5b908d8b14fe172 # Parent be50d20643a167c6af2a861a3ea2f00ed33670b6 Port to GtkD-2.0 (gtk+3) diff -r be50d20643a1 -r 752676232e4b doodle/dia/icanvas.d --- a/doodle/dia/icanvas.d Mon Sep 17 11:49:45 2012 +0930 +++ b/doodle/dia/icanvas.d Wed Sep 26 17:36:31 2012 +0930 @@ -18,12 +18,12 @@ PENCIL } -interface IViewport2 { +interface IDamageable { void damageModel(in Rectangle area); void damageScreen(in Rectangle area); } -interface IViewport : IViewport2 { +interface IViewport : IDamageable { void zoomRelative(in double factor, in Point screenDatum); void panRelative(in Vector screenDisplacement); void setCursor(in Cursor cursor); @@ -48,8 +48,8 @@ bool handleKeyRelease(scope IViewport viewport, in KeyEvent event); // XXX Still not sure about these: - //bool handleFocusIn(scope IViewport viewport, FocusEvent event); - //bool handleFocusOut(scope IViewport viewport, FocusEvent event); + //bool handleFocusIn(scope IViewport viewport, in FocusEvent event); + //bool handleFocusOut(scope IViewport viewport, in FocusEvent event); } interface IGrid { diff -r be50d20643a1 -r 752676232e4b doodle/dia/layer_stack.d --- a/doodle/dia/layer_stack.d Mon Sep 17 11:49:45 2012 +0930 +++ b/doodle/dia/layer_stack.d Wed Sep 26 17:36:31 2012 +0930 @@ -17,7 +17,7 @@ } void draw(in Rectangle screenDamage, scope Renderer screenRenderer, - in Rectangle modelDamage, scope Renderer modelRenderer, + in Rectangle modelDamage, scope Renderer modelRenderer, in ScreenModel screenModel) const { foreach(layer; _layers) { layer.draw(screenDamage, screenRenderer, modelDamage, modelRenderer, screenModel); diff -r be50d20643a1 -r 752676232e4b doodle/gtk/cairo_canvas.d --- a/doodle/gtk/cairo_canvas.d Mon Sep 17 11:49:45 2012 +0930 +++ b/doodle/gtk/cairo_canvas.d Wed Sep 26 17:36:31 2012 +0930 @@ -17,24 +17,28 @@ import gtk.Widget; import gtk.Toolbar; import gtk.Table; - import gtk.HRuler; - import gtk.VRuler; + import gtk.Label; + alias gtk.Label.Label HRuler; + alias gtk.Label.Label VRuler; import gtk.Range; import gtk.HScrollbar; import gtk.VScrollbar; import gtk.DrawingArea; import gtk.Adjustment; - import gdk.Drawable; - import gtkc.gtk; import gtkc.gtktypes; //import gtkc.gdktypes; import std.math; import std.stdio; + import core.thread; } +// Bring doodle.tk.geometry.Rectangle into local namespace so we +// get it instead of gdk.Rectangle.Rectangle +alias doodle.tk.geometry.Rectangle Rectangle; + final class CairoCanvas : Table, IViewport { static this() { _cursors = [ @@ -56,26 +60,26 @@ // Create our child widgets and register callbacks - _hRuler = new HRuler; + _hRuler = new HRuler("horizontal"); attach(_hRuler, 1, 2, 0, 1, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.SHRINK, 0, 0); - _hRuler.setMetric(MetricType.PIXELS); + //_hRuler.setMetric(MetricType.PIXELS); - _vRuler = new VRuler; + _vRuler = new VRuler("vertical"); attach(_vRuler, 0, 1, 1, 2, AttachOptions.SHRINK, AttachOptions.FILL | AttachOptions.EXPAND, 0, 0); - _vRuler.setMetric(MetricType.PIXELS); + //_vRuler.setMetric(MetricType.PIXELS); _drawingArea = new DrawingArea; _drawingArea.addOnRealize(&onRealize); _drawingArea.addOnConfigure(&onConfigure); - _drawingArea.addOnExpose(&onExpose); + _drawingArea.addOnDraw(&onDraw); _drawingArea.addOnButtonPress(&onButtonPress); _drawingArea.addOnButtonRelease(&onButtonRelease); _drawingArea.addOnKeyPress(&onKeyPressEvent); @@ -94,8 +98,7 @@ // addOnPopupMenu // addOnQueryTooltip // addOnSelection* - _drawingArea.setEvents(EventMask.EXPOSURE_MASK | - EventMask.POINTER_MOTION_MASK | + _drawingArea.setEvents(EventMask.POINTER_MOTION_MASK | EventMask.POINTER_MOTION_HINT_MASK | EventMask.BUTTON_MOTION_MASK | EventMask.BUTTON_PRESS_MASK | @@ -166,11 +169,11 @@ } void damageModel(in Rectangle area) { - _damageScreen = _damageScreen | _screenModel.modelToScreen(area); + _tmpDamageScreen = _tmpDamageScreen | _screenModel.modelToScreen(area); } void damageScreen(in Rectangle area) { - _damageScreen = _damageScreen | area; + _tmpDamageScreen = _tmpDamageScreen | area; } } @@ -185,10 +188,12 @@ updateRulers(); } - bool onConfigure(GdkEventConfigure * event, Widget widget) { + bool onConfigure(gdk.Event.Event event, Widget widget) { assert(widget is _drawingArea); - auto viewBoundsScreen = Rectangle(Point(0.0, 0.0), Vector(cast(double)event.width, cast(double)event.height)); + //_surface = ImageSurface.create(CairoFormat.ARGB32, event.configure().width, event.configure().height); + + auto viewBoundsScreen = Rectangle(Point(0.0, 0.0), Vector(cast(double)event.configure().width, cast(double)event.configure().height)); if (_screenModel is null) { Rectangle layerBounds = _layerStack.bounds; @@ -207,20 +212,26 @@ return true; } - bool onExpose(GdkEventExpose * event, Widget widget) { + bool onDraw(Context context, Widget widget) { assert(widget is _drawingArea); - auto dr = _drawingArea.getWindow(); - scope modelCr = new Context(dr); // Causing a memory leak! - scope screenCr = new Context(dr); // Causing a memory leak! + double x0, y0, x1, y1; + context.clipExtents(x0, y0, x1, y1); + Rectangle screenDamage = + Rectangle(_screenModel.viewBoundsScreen.position + + Vector(x0, _screenModel.viewBoundsScreen.h - y1), + Vector(x1 - x0, y1 - y0)); + assert(screenDamage.valid); - Rectangle screenDamage = - event is null ? _screenModel.viewBoundsScreen : - Rectangle(_screenModel.viewBoundsScreen.position + Vector(cast(double)event.area.x, _screenModel.viewBoundsScreen.h - cast(double)(event.area.y + event.area.height)), - Vector(cast(double)event.area.width, cast(double)event.area.height)); + writefln("External screen damage: %s", screenDamage); + writefln("Internal screen damage: %s", _internalDamageScreen); + assert(screenDamage.contains(_internalDamageScreen)); Rectangle modelDamage = _screenModel.screenToModel(screenDamage); + scope Context modelCr = Context.create(context.getTarget()); + scope Context screenCr = Context.create(context.getTarget()); + modelCr.save(); screenCr.save(); { { // Setup model context and clip @@ -251,80 +262,97 @@ } screenCr.restore(); _layerStack.draw(screenDamage, new CairoRenderer(screenCr), - modelDamage, new CairoRenderer(modelCr), + modelDamage, new CairoRenderer(modelCr), _screenModel); - } screenCr.restore(); modelCr.restore(); + } screenCr.restore(); screenCr.restore(); + + _internalDamageScreen = Rectangle(); return true; } - bool onButtonPress(GdkEventButton * event, Widget widget) { + bool onButtonPress(gdk.Event.Event event, Widget widget) { assert(widget is _drawingArea); - _eventHandler.handleButtonPress(this, makeButtonEvent(event, _screenModel)); - fixDamage(); + _eventHandler.handleButtonPress(this, makeButtonEvent(event.button(), _screenModel)); + reportDamage(); return true; } - bool onButtonRelease(GdkEventButton * event, Widget widget) { + bool onButtonRelease(gdk.Event.Event event, Widget widget) { assert(widget is _drawingArea); - _eventHandler.handleButtonRelease(this, makeButtonEvent(event, _screenModel)); - fixDamage(); + _eventHandler.handleButtonRelease(this, makeButtonEvent(event.button(), _screenModel)); + reportDamage(); return true; } - bool onKeyPressEvent(GdkEventKey * event, Widget widget) { + bool onKeyPressEvent(gdk.Event.Event event, Widget widget) { assert(widget is _drawingArea); - _eventHandler.handleKeyPress(this, makeKeyEvent(event, _screenModel)); - fixDamage(); + _eventHandler.handleKeyPress(this, makeKeyEvent(event.key(), _screenModel)); + reportDamage(); return true; } - bool onKeyReleaseEvent(GdkEventKey * event, Widget widget) { + bool onKeyReleaseEvent(gdk.Event.Event event, Widget widget) { assert(widget is _drawingArea); - _eventHandler.handleKeyRelease(this, makeKeyEvent(event, _screenModel)); - fixDamage(); + _eventHandler.handleKeyRelease(this, makeKeyEvent(event.key(), _screenModel)); + reportDamage(); return true; } - bool onMotionNotify(GdkEventMotion * event, Widget widget) { + bool onMotionNotify(gdk.Event.Event event, Widget widget) { assert(widget is _drawingArea); + if (event.motion().isHint) { + int x, y; + GdkModifierType mask; + _drawingArea.getWindow().getPointer(x, y, mask); + _eventHandler.handleMotion(this, makeMotionEventHint(x, y, mask, _screenModel)); + } + else { + _eventHandler.handleMotion(this, makeMotionEvent(event.motion(), _screenModel)); + } + + reportDamage(); + // Pass the events on to the rulers so that they update - gtk_widget_event(_hRuler.getWidgetStruct(), cast(GdkEvent *)event); - gtk_widget_event(_vRuler.getWidgetStruct(), cast(GdkEvent *)event); + _hRuler.event(event); + _vRuler.event(event); - _eventHandler.handleMotion(this, makeMotionEvent(event, _screenModel)); - fixDamage(); + // Simulate delay in case we were slow to handle the event. + // This is really only relevant if we were to do the drawing from inside + // the handler. ??? + Thread.sleep(dur!("msecs")(50)); + return true; } - bool onScroll(GdkEventScroll * event, Widget widget) { + bool onScroll(gdk.Event.Event event, Widget widget) { assert(widget is _drawingArea); - _eventHandler.handleScroll(this, makeScrollEvent(event, _screenModel)); - fixDamage(); + _eventHandler.handleScroll(this, makeScrollEvent(event.scroll(), _screenModel)); + reportDamage(); return true; } - bool onEnterNotify(GdkEventCrossing * event, Widget widget) { + bool onEnterNotify(gdk.Event.Event event, Widget widget) { assert(widget is _drawingArea); - _eventHandler.handleEnter(this, makeCrossingEvent(event, _screenModel)); - fixDamage(); + _eventHandler.handleEnter(this, makeCrossingEvent(event.crossing(), _screenModel)); + reportDamage(); return true; } - bool onLeaveNotify(GdkEventCrossing * event, Widget widget) { + bool onLeaveNotify(gdk.Event.Event event, Widget widget) { assert(widget is _drawingArea); - _eventHandler.handleLeave(this, makeCrossingEvent(event, _screenModel)); - fixDamage(); + _eventHandler.handleLeave(this, makeCrossingEvent(event.crossing(), _screenModel)); + reportDamage(); return true; } - bool onFocusIn(GdkEventFocus * event, Widget widget) { + bool onFocusIn(gdk.Event.Event event, Widget widget) { trace("onFocusIn"); return true; } - bool onFocusOut(GdkEventFocus * event, Widget widget) { + bool onFocusOut(gdk.Event.Event event, Widget widget) { trace("onFocusOut"); return true; } @@ -368,6 +396,7 @@ // below so we can preserve it double lower, upper, position, maxSize; + /+ _hRuler.getRange(lower, upper, position, maxSize); _hRuler.setRange(viewLeftBottom.x, viewRightTop.x, @@ -379,6 +408,7 @@ viewLeftBottom.y, position, _screenModel.zoom * 50.0); + +/ } void updateAdjustments() { @@ -405,13 +435,15 @@ _screenModel.viewBoundsModel.h); } - void fixDamage() { - if (_damageScreen.valid) { + void reportDamage() { + if (_tmpDamageScreen.valid) { int x, y, w, h; - _damageScreen.getQuantised(x, y, w, h); + _tmpDamageScreen.getQuantised(x, y, w, h); _drawingArea.queueDrawArea(x, cast(int)_screenModel.viewBoundsScreen.h - (y + h), w, h); - _damageScreen = Rectangle(); + _internalDamageScreen = _internalDamageScreen | _tmpDamageScreen; + _tmpDamageScreen = Rectangle(); } + assert(!_tmpDamageScreen.valid); } void onRealize(Widget widget) { @@ -433,7 +465,8 @@ Adjustment _vAdjustment; VScrollbar _vScrollbar; - Rectangle _damageScreen; + Rectangle _tmpDamageScreen; // accumulated from damageModel and damageScreen calls + Rectangle _internalDamageScreen; // aggregated from _tmpDamageScreen in reportDamage calls ScreenModel _screenModel; static immutable CursorType[Cursor] _cursors; diff -r be50d20643a1 -r 752676232e4b doodle/gtk/events.d --- a/doodle/gtk/events.d Mon Sep 17 11:49:45 2012 +0930 +++ b/doodle/gtk/events.d Wed Sep 26 17:36:31 2012 +0930 @@ -97,7 +97,7 @@ } */ -ButtonEvent makeButtonEvent(const GdkEventButton * event, in ScreenModel screenModel) { +ButtonEvent makeButtonEvent(const gdk.Event.GdkEventButton * event, in ScreenModel screenModel) { Point screenPoint = Point(event.x + 0.5, screenModel.viewBoundsScreen.h - (event.y + 0.5)); Point modelPoint = screenModel.screenToModel(screenPoint); return new ButtonEvent(gtk2tkButtonAction(event.type), @@ -121,11 +121,17 @@ } */ -MotionEvent makeMotionEvent(const GdkEventMotion * event, in ScreenModel screenModel) { +MotionEvent makeMotionEvent(const gdk.Event.GdkEventMotion * event, in ScreenModel screenModel) { + assert(!event.isHint); Point screenPoint = Point(event.x + 0.5, screenModel.viewBoundsScreen.h - (event.y + 0.5)); Point modelPoint = screenModel.screenToModel(screenPoint); + return new MotionEvent(screenPoint, modelPoint, gtk2tkMask(event.state)); +} - return new MotionEvent(screenPoint, modelPoint, gtk2tkMask(event.state)); +MotionEvent makeMotionEventHint(int x, int y, gdk.Event.GdkModifierType mask, in ScreenModel screenModel) { + Point screenPoint = Point(cast(double)x + 0.5, screenModel.viewBoundsScreen.h - (cast(double)y + 0.5)); + Point modelPoint = screenModel.screenToModel(screenPoint); + return new MotionEvent(screenPoint, modelPoint, gtk2tkMask(cast(gdk.Event.guint)mask)); } /* @@ -145,7 +151,7 @@ } */ -KeyEvent makeKeyEvent(const GdkEventKey * event, in ScreenModel screenModel) { +KeyEvent makeKeyEvent(const gdk.Event.GdkEventKey * event, in ScreenModel screenModel) { return new KeyEvent(event.string[0..strlen(event.string)].idup, event.keyval, gtk2tkMask(event.state)); @@ -166,7 +172,7 @@ } */ -ScrollEvent makeScrollEvent(const GdkEventScroll * event, in ScreenModel screenModel) { +ScrollEvent makeScrollEvent(const gdk.Event.GdkEventScroll * event, in ScreenModel screenModel) { Point screenPoint = Point(event.x + 0.5, screenModel.viewBoundsScreen.h - (event.y + 0.5)); Point modelPoint = screenModel.screenToModel(screenPoint); return new ScrollEvent(gtk2tkDirection(event.direction), @@ -202,7 +208,7 @@ } */ -CrossingEvent makeCrossingEvent(const GdkEventCrossing * event, in ScreenModel screenModel) { +CrossingEvent makeCrossingEvent(const gdk.Event.GdkEventCrossing * event, in ScreenModel screenModel) { Point screenPoint = Point(event.x + 0.5, screenModel.viewBoundsScreen.h - (event.y + 0.5)); Point modelPoint = screenModel.screenToModel(screenPoint); return new CrossingEvent(gtk2tkCrossingMode(event.mode), diff -r be50d20643a1 -r 752676232e4b doodle/gtk/palette.d --- a/doodle/gtk/palette.d Mon Sep 17 11:49:45 2012 +0930 +++ b/doodle/gtk/palette.d Wed Sep 26 17:36:31 2012 +0930 @@ -24,7 +24,6 @@ setStyle(GtkToolbarStyle.ICONS); // HORIZONTAL, VERTICAL setOrientation(GtkOrientation.HORIZONTAL); - setTooltips(true); } override void configure(Item[] items, Callback callback) { diff -r be50d20643a1 -r 752676232e4b doodle/tk/events.d --- a/doodle/tk/events.d Mon Sep 17 11:49:45 2012 +0930 +++ b/doodle/tk/events.d Wed Sep 26 17:36:31 2012 +0930 @@ -3,7 +3,6 @@ public { import doodle.tk.geometry; import doodle.tk.screen_model; - import gtkc.gdktypes; } private { diff -r be50d20643a1 -r 752676232e4b doodle/tk/geometry.d --- a/doodle/tk/geometry.d Mon Sep 17 11:49:45 2012 +0930 +++ b/doodle/tk/geometry.d Wed Sep 26 17:36:31 2012 +0930 @@ -196,6 +196,15 @@ } } + bool contains(in Rectangle r) const { + if (r.valid) { + return x0 <= r.x0 && y0 <= r.y0 && x1 >= r.x1 && y1 >= r.y1; + } + else { + return valid; + } + } + // // FIXME this method is all about pixels. Not sure it belongs in