FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Mouse Button Event for Drawing Area

 
Post new topic   Reply to topic     Forum Index -> gtkD
View previous topic :: View next topic  
Author Message
tezem



Joined: 18 Feb 2008
Posts: 14

PostPosted: Mon Feb 18, 2008 1:00 pm    Post subject: Mouse Button Event for Drawing Area Reply with quote

Hi,

I wrote a class which derives from DrawingArea and want to use button release events. I played around with EventBox but that wasn't successfull. Can somebody tell me how to achive this? Following is my code and in the constructor of the class the approach to handle the events. I think it should work but since I get null for getWindow() I cannot activate the mask for the button event.

Code:
class Grid : DrawingArea
{
   private ubyte[] sudoku;
   private ubyte blockx;
   private ubyte blocky;
      
   this(ubyte[] s, ubyte x, ubyte y) {
      sudoku = s;
      blockx = x;
      blocky = y;
      
      //Attach our expose callback, which will draw the window.
      addOnExpose(&exposeCallback);
      
      Window w = getWindow();
      writefln("%s", w);
      //w.addEvent(EventMask.BUTTON_RELEASE_MASK);
      addOnButtonRelease(&buttonReleased);
   }
   
   private gboolean buttonReleased(GdkEventButton* event, Widget widget) {
      writefln("released");
      return 0;
   }

    //Override default signal handler:
    private gboolean exposeCallback(GdkEventExpose* event, Widget widget) {   
      Drawable dr = getDrawable();
      Context cr = new Context(dr);
      
      if (event)
      {
         // clip to the area indicated by the expose event so that we only redraw
         // the portion of the window that needs to be redrawn
         cr.rectangle(event.area.x, event.area.y,
            event.area.width, event.area.height);
         cr.clip();
      }

      int width;
      int height;

      dr.getSize(&width, &height);
      
      // translate (0, 0) to be (0.5, 0.5), i.e. the center of the window
      cr.translate(width / 2, height / 2);
      
      writefln("%s, %s", width, height);
      
      cr.setSourceRgba(0, 0, 0, 1);
      
      int smaller;
      if(width <= height)
         smaller = width;
      else
         smaller = height;
      
      double length = smaller - smaller * 0.02;
      
      int size = blockx * blocky;
      double csize = length / size;
      double lineWidth = 1 + length * 0.001;
      cr.setSourceRgba(0, 0, 0, 1);
      cr.setLineWidth(lineWidth + 2);
      double reference = 0 - length / 2;
      
      // surrounding rectangle, this way we get a nicer looking grid
      cr.rectangle(reference, reference, length, length);
      cr.stroke();
      
      for(int i = 1; i <= (size - 1) * 2; i++) {
         cr.setSourceRgba(0, 0, 0, 0.7);
         cr.setLineWidth(lineWidth);
         
         // horizontal lines
         if(i < size) {
            if(i % blocky == 0) {
               cr.setSourceRgba(0, 0, 0, 1);
               cr.setLineWidth(lineWidth + 2);
            }
            
            double refY = reference + i * csize;
            cr.moveTo(reference, refY);
            cr.lineTo(reference + length, refY);
         }
         // vertical lines
         else {
            if((i - (size - 1)) % blockx == 0) {
               cr.setSourceRgba(0, 0, 0, 1);
               cr.setLineWidth(lineWidth + 2);
            }
            
            double refX = reference + (i - (size - 1)) * csize;
            cr.moveTo(refX, reference);
            cr.lineTo(refX, reference + length);
         }
         
         cr.stroke();
      }
      
      cr.setSourceRgba(0, 0, 0, 1);
      cr.setFontSize(csize * 0.6);
      
      // fill in the sudoku values
      foreach(i, ubyte v; sudoku) {
         if(v != 0) {
            auto posX = reference + (i - (i / size) * size) * csize + csize / 2;
            auto posY = reference + (i / size) * csize + csize / 2;
            char[] c = std.string.toString(v);
            cairo_text_extents_t extents;
            
            cr.textExtents(c, &extents);
            cr.moveTo((posX - (extents.width / 2)) - extents.xBearing, posY + (extents.height / 2));
            cr.showText(c);
         }
      }
      
      delete cr;
      
      return 0;
   }
}
Back to top
View user's profile Send private message
Mike Wey



Joined: 07 May 2007
Posts: 428

PostPosted: Mon Feb 18, 2008 1:13 pm    Post subject: Reply with quote

Unless i'm reading over it, you are not calling the constructor of the base class. Without it there won't be any gtk struct to get the window from.
Back to top
View user's profile Send private message
tezem



Joined: 18 Feb 2008
Posts: 14

PostPosted: Tue Feb 19, 2008 2:58 am    Post subject: Reply with quote

With

Code:
this(ubyte[] s, ubyte x, ubyte y) {
      super();
      
      sudoku = s;
      blockx = x;
      blocky = y;
      
      //Attach our expose callback, which will draw the window.
      addOnExpose(&exposeCallback);
      
      Window w = getWindow();
      writefln("%s", w);
      //w.addEvent(EventMask.BUTTON_RELEASE_MASK);
      addOnButtonRelease(&buttonReleased);
   }


I still get null.
Back to top
View user's profile Send private message
Mike Wey



Joined: 07 May 2007
Posts: 428

PostPosted: Tue Feb 19, 2008 2:30 pm    Post subject: Reply with quote

scratch that last reply, since the default constructor is called implicitly already. Smile

But for the problem a gtk.Widget doesn't have a gdk.Window associated with it until it's visible (after calling showAll on the window containing it as far as i can tell). it's documented someware but i can't remember.
Back to top
View user's profile Send private message
tezem



Joined: 18 Feb 2008
Posts: 14

PostPosted: Wed Feb 20, 2008 4:49 am    Post subject: Reply with quote

Here is the calling code for my class.

Code:
int main(char[][] args) {
   GtkD.init(args);
   
   MainWindow win = new MainWindow("SuDoku grid");
   
   win.setDefaultSize( 250, 250 );
   
   ubyte blockx = 4;
   ubyte blocky = 4;
   Sudoku s = new Sudoku(blockx, blocky);
   Grid g = new Grid(s.solve(), blockx, blocky);
   win.add(g);
   g.show();
   win.showAll();

   GtkD.main();
   return 0;
}


I tried to move the win.showAll(); after win.setDefaultSize(); but it's still null. What I find strange is that in gtk.Widget the getDrawable and getWindow code is the same.
Back to top
View user's profile Send private message
Mike Wey



Joined: 07 May 2007
Posts: 428

PostPosted: Wed Feb 20, 2008 12:47 pm    Post subject: Reply with quote

You are calling getWindow() in the constructor for the Grid, and since you can't move the call to the constructor to after the call to showAll() it won't work in the constructor. So you probably need an other way to set the eventmask, when i was testing the code i moved the getWindow related part to the exposeCallback.

Quote:
What I find strange is that in gtk.Widget the getDrawable and getWindow code is the same.


The gtkWidget struct only has a gdkWindow in it, and gdkDrawable is the base class of gdkWindow, so the getDrawable function is a bit redundant.
I don't know why both functions are in gtk.Widget but reading the comments in the cairo demo it looks like the getDrawable function was there before the getWindow function.
Back to top
View user's profile Send private message
tezem



Joined: 18 Feb 2008
Posts: 14

PostPosted: Thu Feb 21, 2008 5:32 am    Post subject: Reply with quote

Yes right I get the Window if I put it into the expose function but w.setEvents(EventMask.BUTTON_RELEASE_MASK); still doesn't call my buttonReleased callback.
I also looked at the gtkD examples, especially the TestDrawingArea (http://www.dsource.org/projects/gtkd/browser/trunk/demos/gtkD/TestDrawingArea.d) but I found the mask setting nowhere and the code segfaults too.
Back to top
View user's profile Send private message
Mike Wey



Joined: 07 May 2007
Posts: 428

PostPosted: Thu Feb 21, 2008 2:17 pm    Post subject: Reply with quote

Isn't addEvents in gtk.Widget and not gdk.Window. http://library.gnome.org/devel/gtk/stable/GtkWidget.html#gtk-widget-add-events
So there is actually no need for the gdk.Window.

To make it even better the addOnButtonRelease already calls addEvents(EventMask.BUTTON_RELEASE_MASK) for you.
But to get the ButtonRelease event working you also need the BUTTON_PRESS_MASK.

So the final code in the constructor whould be something like this:

Code:
        .....

        //Attach our expose callback, which will draw the window.
        addOnExpose(&exposeCallback);
       
        //We Don't need this.
        //Window w = getWindow();
        //writefln("%s", w);
        //w.addEvent(EventMask.BUTTON_RELEASE_MASK);

        //Set the BUTTON_PRESS_MASK so we can receve the ButtonRelears event
        addEvents(EventMask.BUTTON_PRESS_MASK);
        addOnButtonRelease(&buttonReleased);
    }


Quote:
I also looked at the gtkD examples, especially the TestDrawingArea (http://www.dsource.org/projects/gtkd/browser/trunk/demos/gtkD/TestDrawingArea.d) but I found the mask setting nowhere and the code segfaults too.


I haven't noticed any Segfaults with that example, does it happen when you do something specific?
Back to top
View user's profile Send private message
tezem



Joined: 18 Feb 2008
Posts: 14

PostPosted: Fri Feb 22, 2008 1:20 am    Post subject: Reply with quote

Ah thanks now it works. Sorry it's my first time with gtk.

Quote:
I haven't noticed any Segfaults with that example, does it happen when you do something specific?


What I do is checkout the demos from svn go into the demos/gtkD dir and build everything with "dsss build". That step finishes successfull but when I execute TestWindow I get the following:

Quote:
Loaded lib = libgtk-x11-2.0.so
Loaded lib = libglib-2.0.so
Loaded lib = libgobject-2.0.so
Loaded lib = libgdk-x11-2.0.so
Loaded lib = libgdk_pixbuf-2.0.so
Loaded lib = libcairo.so.2
Loaded lib = libpango-1.0.so
Loaded lib = libgthread-2.0.so
Loaded lib = libatk-1.0.so
failed (libglib-2.0.so) g_atomic_int_inc
failed (libglib-2.0.so) g_atomic_int_dec_and_test
failed (libglib-2.0.so) g_module_supported
failed (libglib-2.0.so) g_module_build_path
failed (libglib-2.0.so) g_module_open
failed (libglib-2.0.so) g_module_symbol
failed (libglib-2.0.so) g_module_name
failed (libglib-2.0.so) g_module_make_resident
failed (libglib-2.0.so) g_module_close
failed (libglib-2.0.so) g_module_error
failed (libglib-2.0.so) g_io_channel_win32_new_fd
failed (libglib-2.0.so) g_io_channel_win32_new_socket
failed (libglib-2.0.so) g_io_channel_win32_new_messages
failed (libglib-2.0.so) g_ascii_isalnum
failed (libglib-2.0.so) g_ascii_isalpha
failed (libglib-2.0.so) g_ascii_iscntrl
failed (libglib-2.0.so) g_ascii_isdigit
failed (libglib-2.0.so) g_ascii_isgraph
failed (libglib-2.0.so) g_ascii_islower
failed (libglib-2.0.so) g_ascii_isprint
failed (libglib-2.0.so) g_ascii_ispunct
failed (libglib-2.0.so) g_ascii_isspace
failed (libglib-2.0.so) g_ascii_isupper
failed (libglib-2.0.so) g_ascii_isxdigit
failed (libglib-2.0.so) g_win32_error_message
failed (libglib-2.0.so) g_win32_getlocale
failed (libglib-2.0.so) g_win32_get_package_installation_directory
failed (libglib-2.0.so) g_win32_get_package_installation_subdirectory
failed (libglib-2.0.so) g_win32_get_windows_version
failed (libglib-2.0.so) g_win32_locale_filename_from_utf8
failed (libgthread-2.0.so) g_mutex_new
failed (libgthread-2.0.so) g_mutex_lock
failed (libgthread-2.0.so) g_mutex_trylock
failed (libgthread-2.0.so) g_mutex_unlock
failed (libgthread-2.0.so) g_mutex_free
failed (libgthread-2.0.so) g_cond_new
failed (libgthread-2.0.so) g_cond_signal
failed (libgthread-2.0.so) g_cond_broadcast
failed (libgthread-2.0.so) g_cond_wait
failed (libgthread-2.0.so) g_cond_timed_wait
failed (libgthread-2.0.so) g_cond_free
failed (libgthread-2.0.so) g_private_new
failed (libgthread-2.0.so) g_private_get
failed (libgthread-2.0.so) g_private_set
failed (libgthread-2.0.so) g_thread_supported
failed (libgthread-2.0.so) g_thread_create
failed (libgthread-2.0.so) g_thread_yield
failed (libgthread-2.0.so) g_static_mutex_lock
failed (libgthread-2.0.so) g_static_mutex_trylock
failed (libgthread-2.0.so) g_static_mutex_unlock
failed (libgthread-2.0.so) g_static_mutex_get_mutex
failed (libpango-1.0.so) script_engine_list
failed (libpango-1.0.so) script_engine_init
failed (libpango-1.0.so) script_engine_exit
failed (libpango-1.0.so) script_engine_create

(TestWindow:6148): Gtk-CRITICAL **: gtk_image_get_pixbuf: assertion `image->storage_type == GTK_IMAGE_PIXBUF || image->storage_type == GTK_IMAGE_EMPTY' failed

(TestWindow:6148): Gtk-CRITICAL **: gtk_image_get_pixbuf: assertion `image->storage_type == GTK_IMAGE_PIXBUF || image->storage_type == GTK_IMAGE_EMPTY' failed
Segmentation fault (core dumped)


Another question just appeared, maybe you can help me with that too? I made a borderless window and want it to be resized but setDefaultSize doesn't do anything. The other thing I don't understand is that there seems to be no way to get the root gtk window. I need it to set this inputWindow transient above the main gtk window. Because I didn't find a way to get the root window I need add the root gtk window to the constructor of my class and store it under gtkWin. Here is the code:

Code:
inputWindow = new gtk.Window.Window("none");
      inputWindow.setTransientFor(gtkWin);
      inputWindow.setModal(true);
      inputWindow.setDecorated(false);
      inputWindow.setResizable(false);
      inputWindow.setDefaultSize(cast(int)csize, cast(int)csize);
      inputWindow.setSkipTaskbarHint(true);
      
      Table t = new Table(blockx, blocky, true);
      
      for(int i = 0; i < blockx * blocky; i++) {
         int r = i / blockx;
         int c = i - r * blockx;writefln("%s, %s", r, c);
         Button b = new Button(std.string.toString(i + 1), false);
         b.addOnClicked(&inputDialogClicked);
         t.attachDefaults(b, c, c + 1, r, r + 1);
      }
      
      inputWindow.add(t);
      
      int x, y;
      gdk.Window.Window win = getWindow();
      win.getOrigin(&x, &y);
      double refX = x + (width / 2 - length / 2);
      double refY = y + (height / 2 - length / 2);
      int size;
      inputWindow.getSize(&size, &size);writefln("size: %s", size);
      inputWindow.move((refX + column * csize) - size, (refY + row * csize) - size);
      inputWindow.setDefaultSize(250, 250);
      inputWindow.showAll();
Back to top
View user's profile Send private message
Mike Wey



Joined: 07 May 2007
Posts: 428

PostPosted: Fri Feb 22, 2008 3:12 pm    Post subject: Reply with quote

The TestWindow will no longer Segfault in r441.

Quote:
Another question just appeared, maybe you can help me with that too? I made a borderless window and want it to be resized but setDefaultSize doesn't do anything.


Yes, setDefaultSize and resize won't work when the window is not resizable the window will use it's "natural" default size. You can still make the window a specific size using gtk.Window.setSizeRequest. or you could change some settings of the table/buttons so you don't need to set a size.

Quote:
The other thing I don't understand is that there seems to be no way to get the root gtk window. I need it to set this inputWindow transient above the main gtk window. Because I didn't find a way to get the root window I need add the root gtk window to the constructor of my class and store it under gtkWin.


gtk.Widget.getRootWindow() might work, it returns a GdkWindow.
if you want the gtk.Window , gtk.Widget.getToplevel() will get you te top level gtk.Window.
Back to top
View user's profile Send private message
tezem



Joined: 18 Feb 2008
Posts: 14

PostPosted: Sat Feb 23, 2008 10:57 am    Post subject: Reply with quote

Thanks a lot for helping me out.
Back to top
View user's profile Send private message
fla



Joined: 18 Jun 2008
Posts: 2

PostPosted: Sat Jun 21, 2008 11:01 pm    Post subject: Reply with quote

Hi tezem,
could you post your full solution, please?

kind regards
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic     Forum Index -> gtkD All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group