Hello,
I have a problem with Cairo and Expose events. I am trying to make a custom 
widget. I need a canvas ta draw on. If there's a different way to achieve it, 
please, tell me.
First, the example in 
http://www.go-mono.com/docs/monodoc.ashx?link=T%3aCairo.Context seems not to 
work, when I hide and un-hide the app it works correctly, but move a smaller 
window over it and it doesn't re-draw itself. Is this a problem in my 
workstation, does anybody else see this same problem?
Based on that example and on a Python implementation of the same thing I wrote 
the code (at the bottom) that draws a pentagram. This has a deeper problem. 
It redraws itself incorrectly. It seems like when. It seems like if the part 
exposed gets re-drawn, but the coordinate system is moved from 0,0 to x,y 
where x,y is where the exposing starts. It's hard to explain, I'll attach a 
screenshot.
Any help is appreciated.
-- 
Pupeno <[EMAIL PROTECTED]> (http://pupeno.com)

PS: The code:

namespace ScoreReadingTrainer {
        public enum Clef {
                G, F, C3, C4
        }
        
        public class Score: Gtk.DrawingArea {
                // Margin, in %, on the left of the score (right has no margin).
                readonly private byte margin = 2;
                
                readonly private byte steps = 24;
                
                private Clef clef;
                
                public Score() {
                        this.clef = Clef.G;
                        this.ExposeEvent += Draw;
                }

                void Draw(object o, Gtk.ExposeEventArgs e) {
                        Score score = o as Score;
                        if(score != null) { // Either it is a Score or we are 
in problems.
                                Cairo.Context context = 
Gdk.Context.CreateDrawable(score.GdkWindow);
                                this.Draw(context, e.Event.Area.X, 
e.Event.Area.Y, e.Event.Area.Width, 
e.Event.Area.Height);
                        }
                }
                
                void Draw(Cairo.Context context, int x, int y, int width, int 
height) {
                        context.Rectangle(x, y, width, height);
                        context.Clip();
                        this.Draw(context);
                }
                
                void Draw(Cairo.Context context) {
                        int width = this.Allocation.Width;
                        int height = this.Allocation.Height;
                        int realMargin = this.margin * width / 100;
                        
                        Console.WriteLine("{0}: width={1}, height={2}", 
System.DateTime.Now, width, 
height);
                        
                        // Paint a white background.
                        context.Save();
                        context.Color = new Cairo.Color(1,1,1);
                        context.Paint();
                        context.Restore();
                        
                        // Draw the pentagram.
                        context.Save();
                        context.Color = new Cairo.Color(0, 0, 0); // TODO: 
maybe use 0.2, 0.2, 0.2.
                        context.LineWidth = height / 200;         // Make a 
relative line width so 
we don't end up with a lines too fat or too thin.
                        if(context.LineWidth < 1) {               // Ensure 
that lines
                                context.LineWidth = 1;                  // are 
at least one pixel wide.
                        }
                        for(int line = -2; line <= 2; line++) {// line in 
self.lines:
                                double y = this.stepToPixels(line);
                                if(context.LineWidth == 1) {            // 
Ensure that if lines are one 
pixel wide
                                        y += 0.5;                             
// they will be one full pixel and 
not two half pixels: http://cairographics.org/FAQ
                                }
                                Console.WriteLine("{0}: Line {1} at {2} of 
width {3}.", 
System.DateTime.Now, line, y, context.LineWidth);
                                context.MoveTo(realMargin, y);
                                context.LineTo(width, y);
                                context.Stroke();
                        }
                        context.Restore();
                }
    
                int stepToPixels(int step) {
                        // """ Having the step number, return the pixel. A step 
is the minimum 
possible separations between notes, vertically."""
                        int height = this.Allocation.Height;
                        int middle = height / 2;
                        int stepDistance = height / this.steps;
                        return middle - step * stepDistance;
                }
        }
}

namespace Gdk {
        public class Context {
                //Use [DllImport("libgdk-win32-2.0-0.dll")] for  Win32 
                [DllImport("libgdk-x11-2.0.so")]
                        internal static extern IntPtr 
gdk_x11_drawable_get_xdisplay(IntPtr raw);

                [DllImport("libgdk-x11-2.0.so")]
                        internal static extern IntPtr 
gdk_x11_drawable_get_xid(IntPtr raw);

                [DllImport("libgdk-x11-2.0.so")]
                        internal static extern IntPtr 
gdk_drawable_get_visual(IntPtr raw);

                [DllImport("libgdk-x11-2.0.so")]
                        internal static extern IntPtr 
gdk_x11_visual_get_xvisual(IntPtr raw);

                public static Cairo.Context CreateDrawable(Gdk.Drawable 
drawable) {
                        IntPtr x_drawable = IntPtr.Zero;
                        int x_off = 0, y_off = 0;

                        int x, y, w, h, d;
                        ((Gdk.Window)drawable).GetGeometry(out x, out y, out w, 
out h, out d);

                        if(drawable is Gdk.Window) {
                                ((Gdk.Window) 
drawable).GetInternalPaintInfo(out drawable, out x_off, out 
y_off);
                        }

                        x_drawable = drawable.Handle;
                        IntPtr visual = gdk_drawable_get_visual(x_drawable);

                        IntPtr Xdisplay = 
gdk_x11_drawable_get_xdisplay(x_drawable);
                        IntPtr Xvisual = gdk_x11_visual_get_xvisual(visual);
                        IntPtr Xdrawable = gdk_x11_drawable_get_xid(x_drawable);

                        Cairo.XlibSurface s = new Cairo.XlibSurface(Xdisplay, 
Xdrawable, Xvisual, 
w, h);

                        Cairo.Context g = new Cairo.Context(s);

                        if(drawable is Gdk.Window){
                                g.Translate(-(double)x_off,-(double)y_off);
                        }
                        return g;
                }
        }
} 

Attachment: correct.png
Description: PNG image

Attachment: scrambled.png
Description: PNG image

Attachment: pgpnRZrI5XZKi.pgp
Description: PGP signature

_______________________________________________
Mono-list maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-list

Reply via email to