Il s'agit dans cet exemple de tracer la courbe de la fonction f (x) = m x2. C'est un curseur qui permet la récupération de la valeur du paramètre m.

/**
* fparm.cpp
*
* fonction dépendant d'un paramètre
*/
#include "geo2D/geo2D.h"
#define W 800
#define H 600
#define W0 400
#define H0 300
class fcarre: public fonction {
public:
double m;
fcarre (double m);
double image (double x);
};
fcarre est une sur-classe de la classe fonction.
fcarre::fcarre (double m) {
fcarre::m = m;
}
bool fonction::def (double x) {
return TRUE;
}
double fonction::image (double x) {
return 0.0;
}
On définit les deux méthodes de la classe fonction.
double fcarre::image (double x) {
return m * x * x;
}
Retourne l'image du réel x par la fonction carré qui dépend du paramètre m.
class Donnees {
public:
GdkCursor *fleche;
GdkCursor *hand;
bool presse;
repere *R;
curseur *cm;
fcarre *f;
courbe *c;
};
On définit les données géométriques et les outils utiles dans cette application.
static void paint (GtkWidget *widget, GdkEventExpose *event, Donnees *D) {
cairo_t *cr;
cr = gdk_cairo_create (widget->window); // création du graphique
cairo_select_font_face (cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size (cr, 12.0); // on fixe la police et sa taille
cairo_set_source_rgb (cr, 1,1,1); // on peint l'écran en blanc
cairo_paint (cr);
cairo_stroke (cr);
cairo_set_source_rgb (cr, 1, 0, 0);
cairo_set_line_width (cr, 1.0);
D->R->trace (cr);
cairo_set_source_rgb (cr, 0, 0, 1);
cairo_set_line_width (cr, 1.0);
D->cm->trace (cr);
D->c->trace (cr);
cairo_stroke (cr);
cairo_destroy (cr);
}
On redessine ici le graphique.
static void event_press (GtkWidget *widget, GdkEventButton *event, Donnees *D) {
int X = event->x;
int Y = event->y;
D->presse = D->cm->select (X, Y) || D->cm->select_curseur (X, Y);
if (D->presse)
gdk_window_set_cursor (widget->window, D->hand);
}
On gère ici l'appui sur le bouton gauche de la souris.
static void event_motion (GtkWidget *widget, GdkEventMotion *event, Donnees *D) {
int X = event->x;
int Y = event->y;
if (D->presse) {
D->cm->bouge (X, Y);
D->cm->bouge_curseur (X, Y);
D->f->m = D->cm->valeur ();
gtk_widget_queue_draw (widget);
} else
gdk_window_set_cursor (widget->window, (D->cm->zone (X, Y) || D->cm->zone_curseur (X, Y)) ?
D->hand : D->fleche);
}
On gère ici la déplacement de la souris.
static void event_release (GtkWidget *widget, GdkEventButton *event, Donnees *D) {
D->cm->stop ();
D->cm->stop_curseur ();
D->presse = FALSE;
gdk_window_set_cursor (widget->window, D->fleche);
}
On gère ici le relachement du bouton de la souris
int main (int argc, char *argv []) {
GtkWidget *fenetre;
Donnees *D;
D = new Donnees;
D->R = new repere (W0, H0, W, H, 50.0, 50.0, 1.0, 1.0);
D-> cm = new curseur (-2.0, 2.0, 0.5, W - 300, 100, 200, "m", D->R);
D->f = new fcarre (0.5);
D->c = new courbe (D->f, NULL, D->R);
D->presse = false;
gtk_init (&argc, &argv);
D->fleche = gdk_cursor_new (GDK_LEFT_PTR);
D->hand = gdk_cursor_new (GDK_HAND1);
fenetre = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (fenetre, "expose-event", G_CALLBACK (paint), D);
g_signal_connect (fenetre, "destroy", G_CALLBACK (gtk_main_quit), NULL);
gtk_widget_add_events (fenetre, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK
| GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
g_signal_connect (G_OBJECT (fenetre), "button_press_event", G_CALLBACK (event_press), D);
g_signal_connect (G_OBJECT (fenetre), "button_release_event", G_CALLBACK (event_release), D);
g_signal_connect (G_OBJECT (fenetre), "motion_notify_event", G_CALLBACK (event_motion), D);
gtk_window_set_position (GTK_WINDOW (fenetre), GTK_WIN_POS_CENTER);
gtk_window_set_default_size (GTK_WINDOW (fenetre), W, H);
gtk_widget_set_app_paintable (fenetre, TRUE);
gtk_widget_show_all (fenetre);
gtk_main ();
return 0;
}
Programme principal (voir les commentaires concernant l'application droite.cpp).