changeset 136:752676232e4b

Port to GtkD-2.0 (gtk+3)
author David Bryant <bagnose@gmail.com>
date Wed, 26 Sep 2012 17:36:31 +0930
parents be50d20643a1
children 9a9dcae45e08
files doodle/dia/icanvas.d doodle/dia/layer_stack.d doodle/gtk/cairo_canvas.d doodle/gtk/events.d doodle/gtk/palette.d doodle/tk/events.d doodle/tk/geometry.d
diffstat 7 files changed, 117 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- 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 {
--- 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);
--- 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;
--- 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),
--- 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) {
--- 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 {
--- 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