Create the callbacks hash on first use.
[ruby-ecore.git] / src / ecore_evas / rb_ecore_evas.c
1 /*
2  * $Id: rb_ecore_evas.c 303 2005-03-22 17:42:04Z tilman $
3  *
4  * Copyright (C) 2004 ruby-ecore team (see AUTHORS)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <ruby.h>
22 #include <stdbool.h>
23
24 #include <Ecore.h>
25 #include <Ecore_Evas.h>
26 #include <evas/rb_evas.h>
27
28 #define __RB_ECORE_EVAS_C
29 #include "../ecore/rb_ecore.h"
30 #include "rb_ecore_evas_main.h"
31 #include "rb_ecore_evas.h"
32
33 #define RUBY_ECORE_EVAS_KEY "__RB_ECORE_EVAS_KEY"
34
35 #define CALLBACK_DEFINE_HANDLER(name) \
36         static void on_##name (Ecore_Evas *real) \
37         { \
38                 VALUE self; \
39                 VALUE cb; \
40 \
41                 self = (VALUE) ecore_evas_data_get (real, \
42                                                     RUBY_ECORE_EVAS_KEY); \
43                 GET_OBJ (self, RbEcoreEvas, ee); \
44 \
45                 cb = rb_hash_aref (ee->callbacks, rb_str_new2 (#name)); \
46                 rb_funcall (cb, rb_intern ("call"), 0); \
47         } \
48
49 #define CALLBACK_REG_HANDLER(name) \
50                 GET_OBJ (self, RbEcoreEvas, ee); \
51 \
52                 if (!rb_block_given_p ()) \
53                         return Qnil; \
54 \
55                 if (NIL_P (ee->callbacks)) \
56                         ee->callbacks = rb_hash_new (); \
57 \
58                 rb_hash_aset (ee->callbacks, rb_str_new2 (#name), \
59                               rb_block_proc ()); \
60 \
61                 ecore_evas_callback_##name##_set (ee->real, on_##name); \
62 \
63                 return Qnil;
64
65 VALUE cEcoreEvas;
66
67 /* called by the child classes */
68 void c_ecore_evas_mark (RbEcoreEvas *ee)
69 {
70         if (!NIL_P (ee->evas))
71                 rb_gc_mark (ee->evas);
72
73         if (!NIL_P (ee->callbacks))
74                 rb_gc_mark (ee->callbacks);
75 }
76
77 void c_ecore_evas_free (RbEcoreEvas *ee, bool free_mem)
78 {
79         if (ee->real)
80                 ecore_evas_free (ee->real);
81
82         ecore_evas_shutdown ();
83         ecore_shutdown ();
84
85         if (free_mem)
86                 free (ee);
87 }
88
89 /* :nodoc: */
90 static VALUE c_init (int argc, VALUE *argv, VALUE self)
91 {
92         GET_OBJ (self, RbEcoreEvas, ee);
93
94         ee->evas = Qnil;
95         ee->callbacks = Qnil;
96
97         ecore_evas_data_set (ee->real, RUBY_ECORE_EVAS_KEY, (void *) self);
98
99         return Qnil;
100 }
101
102 /* :nodoc: */
103 static VALUE c_inspect (VALUE self)
104 {
105         INSPECT (self, RbEcoreEvas);
106 }
107
108 /*
109  * call-seq:
110  *  ee.show => nil
111  *
112  * Shows <i>ee</i>.
113  */
114 static VALUE c_show (VALUE self)
115 {
116         GET_OBJ (self, RbEcoreEvas, ee);
117
118         ecore_evas_show (ee->real);
119
120         return Qnil;
121 }
122
123 /*
124  * call-seq:
125  *  ee.hide => nil
126  *
127  * Hides <i>ee</i>.
128  */
129 static VALUE c_hide (VALUE self)
130 {
131         GET_OBJ (self, RbEcoreEvas, ee);
132
133         ecore_evas_hide (ee->real);
134
135         return Qnil;
136 }
137
138 /*
139  * call-seq:
140  *  ee.visible? => true or false
141  *
142  * Returns true if <i>ee</i> is visible, else returns false.
143  */
144 static VALUE c_visible_get (VALUE self)
145 {
146         GET_OBJ (self, RbEcoreEvas, ee);
147
148         return ecore_evas_visibility_get (ee->real) ? Qtrue : Qfalse;
149 }
150
151 /*
152  * call-seq:
153  *   ee.raise => nil
154  *
155  * Raises <i>ee</i>.
156  */
157 static VALUE c_raise (VALUE self)
158 {
159         GET_OBJ (self, RbEcoreEvas, ee);
160
161         ecore_evas_raise (ee->real);
162
163         return Qnil;
164 }
165
166 /*
167  * call-seq:
168  *  ee.lower => nil
169  *
170  * Lowers <i>ee</i>.
171  */
172 static VALUE c_lower (VALUE self)
173 {
174         GET_OBJ (self, RbEcoreEvas, ee);
175
176         ecore_evas_lower (ee->real);
177
178         return Qnil;
179 }
180
181 /*
182  * call-seq:
183  *   ee.layer => fixnum
184  *
185  * Returns the layer of <i>ee</i>.
186  */
187 static VALUE c_layer_get (VALUE self)
188 {
189         GET_OBJ (self, RbEcoreEvas, ee);
190
191         return INT2FIX (ecore_evas_layer_get (ee->real));
192 }
193
194 /*
195  * call-seq:
196  *  ee.layer(fixnum) => fixnum
197  *
198  * Sets the layer of <i>ee</i>.
199  */
200 static VALUE c_layer_set (VALUE self, VALUE val)
201 {
202         GET_OBJ (self, RbEcoreEvas, ee);
203
204         Check_Type (val, T_FIXNUM);
205
206         ecore_evas_layer_set (ee->real, FIX2INT (val));
207
208         return Qnil;
209 }
210
211 /*
212  * call-seq:
213  *  ee.evas => evas
214  *
215  * Returns the <code>Evas::Evas</code> object for <i>ee</i>.
216  */
217 static VALUE c_evas_get (VALUE self)
218 {
219         GET_OBJ (self, RbEcoreEvas, ee);
220
221         if (NIL_P (ee->evas))
222                 ee->evas = TO_EVAS (self, ecore_evas_get (ee->real));
223
224         return ee->evas;
225 }
226
227 /*
228  * call-seq:
229  *  ee.geometry => array
230  *
231  * Returns an array containing the geometry of <i>ee</i>.
232  *
233  *  ee.move(150, 300)   #=> nil
234  *  ee.resize(200, 200) #=> nil
235  *  ee.geometry         #=> [150, 300, 200, 200]
236  */
237 static VALUE c_geometry_get (VALUE self)
238 {
239         int x = 0, y = 0, w = 0, h = 0;
240
241         GET_OBJ (self, RbEcoreEvas, ee);
242
243         ecore_evas_geometry_get (ee->real, &x, &y, &w, &h);
244
245         return rb_ary_new3 (4, INT2FIX (x), INT2FIX (y),
246                             INT2FIX (w), INT2FIX (h));
247 }
248
249 /*
250  * call-seq:
251  *  ee.get_size_min => array
252  *
253  * Returns an array containing the minimum size of <i>ee</i>.
254  *
255  *  ee.set_size_min(100, 200) #=> nil
256  *  ee.get_size_min           #=> [100, 200]
257  */
258 static VALUE c_get_size_min (VALUE self)
259 {
260         int w = 0, h = 0;
261
262         GET_OBJ (self, RbEcoreEvas, ee);
263
264         ecore_evas_size_min_get (ee->real, &w, &h);
265
266         return rb_ary_new3 (2, INT2FIX (w), INT2FIX (h));
267 }
268
269 /*
270  * call-seq:
271  *  ee.set_size_min(width, height) => nil
272  *
273  * Sets the minimum size of <i>ee</i>.
274  *
275  *  ee.set_size_min(100, 200) #=> nil
276  */
277 static VALUE c_set_size_min (VALUE self, VALUE w, VALUE h)
278 {
279         GET_OBJ (self, RbEcoreEvas, ee);
280
281         Check_Type (w, T_FIXNUM);
282         Check_Type (h, T_FIXNUM);
283
284         ecore_evas_size_min_set (ee->real, FIX2INT (w), FIX2INT (h));
285
286         return Qnil;
287 }
288
289 /*
290  * call-seq:
291  *  ee.get_size_max => array
292  *
293  * Returns an array containing the maximum size of <i>ee</i>.
294  *
295  *  ee.set_size_max(100, 200) #=> nil
296  *  ee.get_size_max           #=> [100, 200]
297  */
298 static VALUE c_get_size_max (VALUE self)
299 {
300         int w = 0, h = 0;
301
302         GET_OBJ (self, RbEcoreEvas, ee);
303
304         ecore_evas_size_max_get (ee->real, &w, &h);
305
306         return rb_ary_new3 (2, INT2FIX (w), INT2FIX (h));
307 }
308
309 /*
310  * call-seq:
311  *  ee.set_size_max(width, height) => nil
312  *
313  * Sets the maximum size of <i>ee</i>.
314  *
315  *  ee.set_size_max(100, 200) #=> nil
316  */
317 static VALUE c_set_size_max (VALUE self, VALUE w, VALUE h)
318 {
319         GET_OBJ (self, RbEcoreEvas, ee);
320
321         Check_Type (w, T_FIXNUM);
322         Check_Type (h, T_FIXNUM);
323
324         ecore_evas_size_max_set (ee->real, FIX2INT (w), FIX2INT (h));
325
326         return Qnil;
327 }
328
329 /*
330  * call-seq:
331  *  ee.move(x, y) => nil
332  *
333  * Moves <i>ee</i> to the coordinates specified in
334  * <i>x</i> and <i>y</i>.
335  *
336  *  ee.move(100, 200) #=> nil
337  */
338 static VALUE c_move (VALUE self, VALUE x, VALUE y)
339 {
340         GET_OBJ (self, RbEcoreEvas, ee);
341
342         Check_Type (x, T_FIXNUM);
343         Check_Type (y, T_FIXNUM);
344
345         ecore_evas_move (ee->real, FIX2INT (x), FIX2INT (y));
346
347         return Qnil;
348 }
349
350 /*
351  * call-seq:
352  *  ee.resize(width, height) => nil
353  *
354  * Resizes <i>ee</i> to width x height.
355  *
356  *  ee.resize(100, 200) #=> nil
357  */
358 static VALUE c_resize (VALUE self, VALUE w, VALUE h)
359 {
360         GET_OBJ (self, RbEcoreEvas, ee);
361
362         Check_Type (w, T_FIXNUM);
363         Check_Type (h, T_FIXNUM);
364
365         ecore_evas_resize (ee->real, FIX2INT (w), FIX2INT (h));
366
367         return Qnil;
368 }
369
370 /*
371  * call-seq:
372  *  ee.title => string
373  *
374  * Returns the title of <i>ee</i>.
375  */
376 static VALUE c_title_get (VALUE self)
377 {
378         const char *tmp;
379
380         GET_OBJ (self, RbEcoreEvas, ee);
381
382         if (!(tmp = ecore_evas_title_get (ee->real)))
383                 return Qnil;
384         else
385                 return rb_str_new2 (tmp);
386 }
387
388 /*
389  * call-seq:
390  *  ee.title(string)
391  *
392  * Sets the title of <i>ee</i>.
393  */
394 static VALUE c_title_set (VALUE self, VALUE val)
395 {
396         GET_OBJ (self, RbEcoreEvas, ee);
397
398         Check_Type (val, T_STRING);
399
400         ecore_evas_title_set (ee->real, StringValuePtr (val));
401
402         return Qnil;
403 }
404
405 /*
406  * call-seq:
407  *  ee.borderless? => true or false
408  *
409  * Returns true if <i>ee</i> is borderless, else returns false.
410  */
411 static VALUE c_borderless_get (VALUE self)
412 {
413         GET_OBJ (self, RbEcoreEvas, ee);
414
415         return ecore_evas_borderless_get (ee->real) ? Qtrue : Qfalse;
416 }
417
418 /*
419  * call-seq:
420  *  ee.borderless(true or false)
421  *
422  * Sets whether <i>ee</i> is borderless or not.
423  */
424 static VALUE c_borderless_set (VALUE self, VALUE val)
425 {
426         GET_OBJ (self, RbEcoreEvas, ee);
427
428         CHECK_BOOL (val);
429
430         ecore_evas_borderless_set (ee->real, val == Qtrue);
431
432         return Qnil;
433 }
434
435 /*
436  * call-seq:
437  *  ee.shaped? => true or false
438  *
439  * Returns true if <i>ee</i> is shaped, else returns false.
440  */
441 static VALUE c_shaped_get (VALUE self)
442 {
443         GET_OBJ (self, RbEcoreEvas, ee);
444
445         return ecore_evas_shaped_get (ee->real) ? Qtrue : Qfalse;
446 }
447
448 /*
449  * call-seq:
450  *  ee.shaped(true or false)
451  *
452  * Sets whether <i>ee</i> is shaped or not.
453  */
454 static VALUE c_shaped_set (VALUE self, VALUE val)
455 {
456         GET_OBJ (self, RbEcoreEvas, ee);
457
458         CHECK_BOOL (val);
459
460         ecore_evas_shaped_set (ee->real, val == Qtrue);
461
462         return Qnil;
463 }
464
465 /*
466  * call-seq:
467  *  ee.sticky? => true or false
468  *
469  * Returns true if <i>ee</i> is sticky, else returns false.
470  */
471 static VALUE c_sticky_get (VALUE self)
472 {
473         GET_OBJ (self, RbEcoreEvas, ee);
474
475         return ecore_evas_sticky_get (ee->real) ? Qtrue : Qfalse;
476 }
477
478 /*
479  * call-seq:
480  *  ee.sticky(true or false)
481  *
482  * Sets whether <i>ee</i> is sticky or not.
483  */
484 static VALUE c_sticky_set (VALUE self, VALUE val)
485 {
486         GET_OBJ (self, RbEcoreEvas, ee);
487
488         CHECK_BOOL (val);
489
490         ecore_evas_sticky_set (ee->real, val == Qtrue);
491
492         return Qnil;
493 }
494
495 /*
496  * call-seq:
497  *  ee.rotation => fixnum
498  *
499  * Returns the rotation of <i>ee</i>.
500  */
501 static VALUE c_rotation_get (VALUE self)
502 {
503         GET_OBJ (self, RbEcoreEvas, ee);
504
505         return INT2FIX (ecore_evas_rotation_get (ee->real));
506 }
507
508 /*
509  * call-seq:
510  *  ee.rotation(fixnum)
511  *
512  * Sets the rotation of <i>ee</i>.
513  */
514 static VALUE c_rotation_set (VALUE self, VALUE val)
515 {
516         GET_OBJ (self, RbEcoreEvas, ee);
517
518         Check_Type (val, T_FIXNUM);
519
520         ecore_evas_rotation_set (ee->real, FIX2INT (val));
521
522         return Qnil;
523 }
524
525 /* FIXME: this is unsafe!
526  * :nodoc:
527  */
528 static VALUE c_delete (VALUE self)
529 {
530         GET_OBJ (self, RbEcoreEvas, ee);
531
532         /* reap our children */
533         rb_gc_start ();
534
535         ecore_evas_free (ee->real);
536         ee->real = NULL;
537
538         return Qnil;
539 }
540
541 CALLBACK_DEFINE_HANDLER (resize);
542 CALLBACK_DEFINE_HANDLER (move);
543 CALLBACK_DEFINE_HANDLER (show);
544 CALLBACK_DEFINE_HANDLER (hide);
545 CALLBACK_DEFINE_HANDLER (delete_request);
546 CALLBACK_DEFINE_HANDLER (destroy);
547 CALLBACK_DEFINE_HANDLER (focus_in);
548 CALLBACK_DEFINE_HANDLER (focus_out);
549 CALLBACK_DEFINE_HANDLER (mouse_in);
550 CALLBACK_DEFINE_HANDLER (mouse_out);
551 CALLBACK_DEFINE_HANDLER (pre_render);
552 CALLBACK_DEFINE_HANDLER (post_render);
553
554 /*
555  * call-seq:
556  *  ee.on_resize { block } => nil
557  *
558  * Sets the handler for the resize event.
559  */
560 static VALUE c_on_resize (VALUE self)
561 {
562         CALLBACK_REG_HANDLER (resize);
563 }
564
565 /*
566  * call-seq:
567  *  ee.on_move { block } => nil
568  *
569  * Sets the handler for the move event.
570  */
571 static VALUE c_on_move (VALUE self)
572 {
573         CALLBACK_REG_HANDLER (move);
574 }
575
576 /*
577  * call-seq:
578  *  ee.on_show { block } => nil
579  *
580  * Sets the handler for the show event.
581  */
582 static VALUE c_on_show (VALUE self)
583 {
584         CALLBACK_REG_HANDLER (show);
585 }
586
587 /*
588  * call-seq:
589  *  ee.on_hide { block } => nil
590  *
591  * Sets the handler for the hide event.
592  */
593 static VALUE c_on_hide (VALUE self)
594 {
595         CALLBACK_REG_HANDLER (hide);
596 }
597
598 /*
599  * call-seq:
600  *  ee.on_delete_request { block } => nil
601  *
602  * Sets the handler for the delete request event.
603  */
604 static VALUE c_on_delete_request (VALUE self)
605 {
606         CALLBACK_REG_HANDLER (delete_request);
607 }
608
609 /*
610  * call-seq:
611  *  ee.on_destroy { block } => nil
612  *
613  * Sets the handler for the destroy event.
614  */
615 static VALUE c_on_destroy (VALUE self)
616 {
617         CALLBACK_REG_HANDLER (destroy);
618 }
619
620 /*
621  * call-seq:
622  *  ee.on_focus_in { block } => nil
623  *
624  * Sets the handler for the focus in event.
625  */
626 static VALUE c_on_focus_in (VALUE self)
627 {
628         CALLBACK_REG_HANDLER (focus_in);
629 }
630
631 /*
632  * call-seq:
633  *  ee.on_focus_out { block } => nil
634  *
635  * Sets the handler for the focus out event.
636  */
637 static VALUE c_on_focus_out (VALUE self)
638 {
639         CALLBACK_REG_HANDLER (focus_out);
640 }
641
642 /*
643  * call-seq:
644  *  ee.on_mouse_in { block } => nil
645  *
646  * Sets the handler for the mouse in event.
647  */
648 static VALUE c_on_mouse_in (VALUE self)
649 {
650         CALLBACK_REG_HANDLER (mouse_in);
651 }
652
653 /*
654  * call-seq:
655  *  ee.on_mouse_out { block } => nil
656  *
657  * Sets the handler for the mouse out event.
658  */
659 static VALUE c_on_mouse_out (VALUE self)
660 {
661         CALLBACK_REG_HANDLER (mouse_out);
662 }
663
664 /*
665  * call-seq:
666  *  ee.on_pre_render { block } => nil
667  *
668  * Sets the handler for the pre render event.
669  */
670 static VALUE c_on_pre_render (VALUE self)
671 {
672         CALLBACK_REG_HANDLER (pre_render);
673 }
674
675 /*
676  * call-seq:
677  *  ee.on_post_render { block } => nil
678  *
679  * Sets the handler for the post render event.
680  */
681 static VALUE c_on_post_render (VALUE self)
682 {
683         CALLBACK_REG_HANDLER (post_render);
684 }
685
686 void Init_EcoreEvas (void)
687 {
688         cEcoreEvas = rb_define_class_under (mEvas, "EcoreEvas", rb_cObject);
689
690         rb_define_private_method (rb_singleton_class (cEcoreEvas),
691                                   "new", NULL, 0);
692         rb_define_method (cEcoreEvas, "initialize", c_init, -1);
693         rb_define_method (cEcoreEvas, "inspect", c_inspect, 0);
694         rb_define_method (cEcoreEvas, "delete", c_delete, 0);
695         rb_define_method (cEcoreEvas, "show", c_show, 0);
696         rb_define_method (cEcoreEvas, "hide", c_hide, 0);
697         rb_define_method (cEcoreEvas, "visible?", c_visible_get, 0);
698         rb_define_method (cEcoreEvas, "raise", c_raise, 0);
699         rb_define_method (cEcoreEvas, "lower", c_lower, 0);
700         rb_define_method (cEcoreEvas, "layer", c_layer_get, 0);
701         rb_define_method (cEcoreEvas, "layer=", c_layer_set, 1);
702         rb_define_method (cEcoreEvas, "evas", c_evas_get, 0);
703         rb_define_method (cEcoreEvas, "geometry", c_geometry_get, 0);
704         rb_define_method (cEcoreEvas, "get_size_min", c_get_size_min, 0);
705         rb_define_method (cEcoreEvas, "set_size_min", c_set_size_min, 2);
706         rb_define_method (cEcoreEvas, "get_size_max", c_get_size_max, 0);
707         rb_define_method (cEcoreEvas, "set_size_max", c_set_size_max, 2);
708         rb_define_method (cEcoreEvas, "move", c_move, 2);
709         rb_define_method (cEcoreEvas, "resize", c_resize, 2);
710         rb_define_method (cEcoreEvas, "title", c_title_get, 0);
711         rb_define_method (cEcoreEvas, "title=", c_title_set, 1);
712         rb_define_method (cEcoreEvas, "borderless?", c_borderless_get, 0);
713         rb_define_method (cEcoreEvas, "borderless=", c_borderless_set, 1);
714         rb_define_method (cEcoreEvas, "shaped?", c_shaped_get, 0);
715         rb_define_method (cEcoreEvas, "shaped=", c_shaped_set, 1);
716         rb_define_method (cEcoreEvas, "sticky?", c_sticky_get, 0);
717         rb_define_method (cEcoreEvas, "sticky=", c_sticky_set, 1);
718         rb_define_method (cEcoreEvas, "rotation", c_rotation_get, 0);
719         rb_define_method (cEcoreEvas, "rotation=", c_rotation_set, 1);
720
721         rb_define_method (cEcoreEvas, "on_resize", c_on_resize, 0);
722         rb_define_method (cEcoreEvas, "on_move", c_on_move, 0);
723         rb_define_method (cEcoreEvas, "on_show", c_on_show, 0);
724         rb_define_method (cEcoreEvas, "on_hide", c_on_hide, 0);
725         rb_define_method (cEcoreEvas, "on_delete_request", c_on_delete_request, 0);
726         rb_define_method (cEcoreEvas, "on_destroy", c_on_destroy, 0);
727         rb_define_method (cEcoreEvas, "on_focus_in", c_on_focus_in, 0);
728         rb_define_method (cEcoreEvas, "on_focus_out", c_on_focus_out, 0);
729         rb_define_method (cEcoreEvas, "on_mouse_in", c_on_mouse_in, 0);
730         rb_define_method (cEcoreEvas, "on_mouse_out", c_on_mouse_out, 0);
731         rb_define_method (cEcoreEvas, "on_pre_render", c_on_pre_render, 0);
732         rb_define_method (cEcoreEvas, "on_post_render", c_on_post_render, 0);
733 }