/* demo8g.c : demos de EZ-Draw reecrits en gtk+ 2.x * * Edouard.Thiel@lif.univ-mrs.fr - 23/03/2010 - version 0.9 * * Compilation sous Unix : * gcc -Wall demo8g.c ez-gtk.c -o demo8g `pkg-config gtk+-2.0 --cflags --libs` -lm * * This program is free software under the terms of the * GNU Lesser General Public License (LGPL) version 2.1. */ #include "ez-gtk.h" #include /*------------ Fenetre 1 : une horloge tourne les aiguilles ------------------*/ GtkWidget *win1, *area1; int cpt1 = 0, win1_w = 250, win1_h = 250, etat1 = 1, delay1 = 30, timer1_id = -1; void dessin_aiguille (GdkWindow *win, GdkGC *gc, Ezg_color color, double angle, int xc, int yc, int d1, int d2, int ra) { double a = (angle-90) * M_PI / 180, c = cos (a), s = sin (a), x1 = xc + c*d1, y1 = yc + s*d1, x2 = xc + c*d2, y2 = yc + s*d2, x3 = x1 - s*ra, y3 = y1 + c*ra, x4 = x1 + s*ra, y4 = y1 - c*ra, x5 = x2 - s*ra, y5 = y2 + c*ra, x6 = x2 + s*ra, y6 = y2 - c*ra; ezg_set_color (gc, color); gdk_draw_line (win, gc, x3, y3, x5, y5); gdk_draw_line (win, gc, x5, y5, x6, y6); gdk_draw_line (win, gc, x6, y6, x4, y4); gdk_draw_line (win, gc, x4, y4, x3, y3); } /* * Appele'e par gtk_main lorsqu'il faut tout redessiner. */ gint area1_onExpose (GtkWidget *widget, GdkEventExpose *ev) { GdkGC *gc = ezg_get_gc (widget); double h = cpt1 / 60.0, m = cpt1 % 60; /* On cree un layout pour dessiner du texte */ PangoLayout *layout = gtk_widget_create_pango_layout (widget, NULL); ezg_area_clear (widget); ezg_set_color (gc, EZG_MAGENTA); ezg_set_nfont (layout, 2); ezg_draw_text (widget, gc, layout, EZG_TC, win1_w/2, 6, "%02d:%02d", (int) h, (int) m); dessin_aiguille (widget->window, gc, EZG_RED, h*30, win1_w/2, win1_h/2, 20, 70, 10); dessin_aiguille (widget->window, gc, EZG_BLUE, m* 6, win1_w/2, win1_h/2, 15, 92, 6); ezg_set_color (gc, EZG_BLACK); ezg_set_nfont (layout, 0); ezg_draw_text (widget, gc, layout, EZG_BL, 8, win1_h-8, "espace : pause q : quitter"); /* Libere la memoire */ g_object_unref (G_OBJECT (layout)); return TRUE; /* L'evenement a ete traite' */ } /* * Appele'e par gtk_main lorsque le timer est arrive' a eche'ance. */ gboolean area1_onTimeout (gpointer data) { cpt1 = (cpt1 + 1) % 720; ezg_area_expose (area1); return TRUE; /* Re'arme le timer */ } /* * Appele'e par gtk_main lorsqu'une touche a ete presse'e. */ gint area1_onKeyPress (GtkWidget *widget, GdkEventKey *ev) { /* ev->keyval contient le symbole de la touche pressee */ switch (ev->keyval) { case GDK_q : gtk_main_quit (); break; case GDK_space : if (etat1) { etat1 = 0; g_source_remove (timer1_id); } else { etat1 = 1; timer1_id = g_timeout_add (delay1, area1_onTimeout, NULL); } break; } return TRUE; /* L'evenement a ete traite' */ } /*---------- Fenetre 2 : une balle rebondit sur une raquette -----------------*/ GtkWidget *win2, *area2; int ba_x = 100, ba_y = 100, ba_dx = 4, ba_dy = 3, win2_w = 280, win2_h = 180, delay2 = 20, timer2_id = -1; void avancer_balle (int x1, int y1, int x2, int y2) { ba_x += ba_dx; ba_y += ba_dy; if (ba_x <= x1) { ba_x = x1; ba_dx = -ba_dx; } else if (ba_x >= x2) { ba_x = x2; ba_dx = -ba_dx; } if (ba_y <= y1) { ba_y = y1; ba_dy = -ba_dy; } else if (ba_y >= y2) { ba_y = y2; ba_dy = -ba_dy; } } /* * Appele'e par gtk_main lorsque la taille de la fenetre a change'. */ gint area2_onConfigure (GtkWidget *widget, GdkEventConfigure *ev) { win2_w = ev->width; win2_h = ev->height; return TRUE; /* L'evenement a ete traite' */ } /* * Appele'e par gtk_main lorsqu'il faut tout redessiner. */ gint area2_onExpose (GtkWidget *widget, GdkEventExpose *ev) { GdkGC *gc = ezg_get_gc (widget); ezg_area_clear (widget); ezg_set_color (gc, EZG_BLACK); gdk_draw_arc (widget->window, gc, FALSE, ba_x-10, ba_y-10, 20, 20, 0, 360*64); ezg_set_color (gc, EZG_BLUE); gdk_draw_rectangle (widget->window, gc, TRUE, ba_x-25, win2_h-8, 51, 6); return TRUE; /* L'evenement a ete traite' */ } /* * Appele'e par gtk_main lorsque le timer est arrive' a eche'ance. */ gboolean area2_onTimeout (gpointer data) { avancer_balle (10, 10, win2_w-10, win2_h-19); ezg_area_expose (area2); return TRUE; /* Re'arme le timer */ } /*----------------------------------------------------------------------------*/ int main (int argc, char *argv[]) { /* Initialise gtk et analyse la ligne de commande */ gtk_init (&argc, &argv); win1 = ezg_window_create (win1_w, win1_h, "Demo 8g : horloge"); area1 = ezg_area_create (win1); /* On autorise certains evenements */ GTK_WIDGET_SET_FLAGS (area1, GTK_CAN_FOCUS); gtk_widget_set_events (area1, GDK_EXPOSURE_MASK | GDK_KEY_PRESS_MASK); /* On attache des callbacks pour gerer certains evenements */ g_signal_connect (G_OBJECT (area1), "expose_event" , G_CALLBACK (area1_onExpose) , NULL); g_signal_connect (G_OBJECT (area1), "key_press_event", G_CALLBACK (area1_onKeyPress), NULL); g_signal_connect (G_OBJECT (win1) , "destroy" , G_CALLBACK (gtk_main_quit) , NULL); /* On cree un timer pour provoquer l'animation. Remarque : l'affichage est automatiquement double-bufferise' par le drawing area, ainsi l'affichage ne clignotte pas. */ timer1_id = g_timeout_add (delay1, area1_onTimeout, NULL); /* Rend visibles la fenetre et son contenu */ gtk_widget_show_all (win1); win2 = ezg_window_create (win2_w, win2_h, "Demo 8g : rebonds"); area2 = ezg_area_create (win2); /* On autorise certains evenements */ gtk_widget_set_events (area2, GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK); /* On attache des callbacks pour gerer certains evenements */ g_signal_connect (G_OBJECT (area2), "expose_event" , G_CALLBACK (area2_onExpose) , NULL); g_signal_connect (G_OBJECT (area2), "configure_event", G_CALLBACK (area2_onConfigure) , NULL); g_signal_connect (G_OBJECT (win2) , "destroy" , G_CALLBACK (gtk_main_quit) , NULL); /* On cree un timer pour provoquer l'animation */ timer2_id = g_timeout_add (delay2, area2_onTimeout, NULL); /* Rend visibles la fenetre et son contenu */ gtk_widget_show_all (win2); /* Boucle d'evenements qui fait "vivre" la fenetre */ gtk_main (); exit (0); }