TD X-Window numero 2: graphe.c




#include <stdio.h>
#include <X11/Xlib.h>
#include "graphe.h"

#define FONT "-adobe-helvetica-medium-r-normal--18-180-75-75-p-98-iso8859-1"

main(argc, argv)
    int argc;
    char **argv;
{
    Display *dpy;
    Window win;
    GC draw_gc;				/* GC to draw with */
    GC fill_gc;				/* GC to fill with */
    GC xor_gc;				/* GC to draw in xor mode */
    XFontStruct *fontstruct;		/* Font descriptor */
    XGCValues gcv;			/* Struct for creating GC */

    Node selected_node = 0;
    Edge related_edges = 0;
    int drawing = 0;
    int mouse_offset_x, mouse_offset_y;

    /* on lit le graphe */
    Graph graph = ReadGraph(stdin);

    /* on ouvre une connection avec le serveur X */
    if ((dpy = XOpenDisplay(NULL)) == NULL) {
	fprintf(stderr, "%s: can't open %s\n", argv[0], XDisplayName(NULL));
	exit(1);
    }

    /* on charge une police pour les labels */
    if ((fontstruct = XLoadQueryFont(dpy, FONT)) == NULL) {
	fprintf(stderr, "%s: display %s doesn't know font %s\n",
		argv[0], DisplayString(dpy), FONT);
	exit(1);
    }

    /* on calcule la taille des noeuds pour la police chargee */
    FixGraphLabelDimensions(dpy, graph, fontstruct->fid);

    /* on cree une fenetre */
    win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
			      100, 100, 300, 200,
			      1, BlackPixel(dpy, DefaultScreen(dpy)),
			      WhitePixel(dpy, DefaultScreen(dpy)));

    XStoreName(dpy, win, graph->title);

    XSelectInput(dpy, win, ExposureMask
		 | ButtonPressMask | ButtonReleaseMask
		 | Button1MotionMask);

    XMapWindow(dpy, win);

    /* on cree les 3 gc : fill_gc, draw_gc, xor_gc */
    gcv.font = fontstruct->fid;
    gcv.foreground = WhitePixel(dpy, DefaultScreen(dpy));
    gcv.background = BlackPixel(dpy, DefaultScreen(dpy));
    fill_gc = XCreateGC(dpy, win,
			(GCFont | GCForeground | GCBackground), &gcv);

    gcv.foreground = BlackPixel(dpy, DefaultScreen(dpy));
    gcv.background = WhitePixel(dpy, DefaultScreen(dpy));
    draw_gc = XCreateGC(dpy, win,
			(GCFont | GCForeground | GCBackground), &gcv);

    gcv.function = GXxor;
    xor_gc = XCreateGC(dpy, win,
		       (GCFunction | GCForeground | GCBackground), &gcv);
    
    /* on gere les evenements X */
    while (1) {
	XEvent event;

	XNextEvent(dpy, &event);

	/* expose */
	if (event.type == Expose && event.xexpose.count == 0) {
	    XClearWindow(dpy, win);
	    DisplayGraph(graph, dpy, win, draw_gc, fill_gc);

	} else if (event.type == ButtonPress) {	/* appui bouton */
					/* bouton 1 = move */
	    if (event.xbutton.button == Button1) {
		selected_node =
		    FindNode(graph, event.xbutton.x, event.xbutton.y);
		if (selected_node) {
		    mouse_offset_x = event.xbutton.x - selected_node->x;
		    mouse_offset_y = event.xbutton.y - selected_node->y;
		    related_edges = RelatedEdges(graph, selected_node);
		}
					/* bouton 2 = print graph */
	    } else if (event.xbutton.button == Button2) {
		PrintGraph(graph, stdout);
					/* bouton 3 = quit */
	    } else if (event.xbutton.button == Button3) {
		exit(0);
	    } 

					/* release bouton = redisplay */
	} else if (event.type == ButtonRelease &&
		   event.xbutton.button == Button1
		   && selected_node) {
	    drawing = 0;
	    XClearWindow(dpy, win);
	    DisplayGraph(graph, dpy, win, draw_gc, fill_gc);
	    FreeEdges(related_edges);

					/* mouse tracking */
	} else if (event.type == MotionNotify && selected_node) {
	    if (drawing) {		/* erase old */
		DisplayNode(selected_node, dpy, win, xor_gc, 0);
		DisplayEdges(related_edges, dpy, win, xor_gc);
	    } else {
		drawing = 1;
	    }
	    /* calculate new */
	    selected_node->x = event.xmotion.x - mouse_offset_x;
	    selected_node->y = event.xmotion.y - mouse_offset_y;
	    /* draw new */
	    DisplayNode(selected_node, dpy, win, xor_gc, 0);
	    DisplayEdges(related_edges, dpy, win, xor_gc);
	}
    }
}



michel.buffa@essi.fr