TD X-Window numero 2: display.c



/*****************************************************************************\
*                                                                             *
*                  graphx.c                                   *
*             mini-afficheur de graphes                           *
*                                                                             *
\*****************************************************************************/

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

/*****************************************************************************\
*              FixGraphLabelDimensions                            *
\*****************************************************************************/

#define MARGIN 2

void
FixGraphLabelDimensions(dpy, graph, font)
    Display *dpy;
    Graph graph;
    Font font;
{    
    int             direction, font_ascent, font_descent;
    XCharStruct     overall;
                    /* get font info from server */
    XFontStruct *font_info;
    Node node;
    
    font_info = XQueryFont(dpy, font);
    for (node = graph->nodes; node; node = node->next) {
                    /* get label sizes */
    XTextExtents(font_info, node->label, strlen(node->label),
              &direction, &font_ascent, &font_descent,
              &overall);
                    /* compute offsets & sizes */
    node->baseline_x = MARGIN + 1;
    node->baseline_y = overall.ascent + MARGIN + 1;
    node->width = overall.width + 2*MARGIN + 2;
    node->height = overall.ascent + overall.descent + 2*MARGIN + 2;
    }
    XFreeFontInfo(0, font_info, 1);
}

/* affiche un graph */
void
DisplayGraph(graph, dpy, window, draw_gc, fill_gc)
    Graph graph;
    Display *dpy;
    Window window;
    GC draw_gc;
    GC fill_gc;
{

    /*
     * on affiche les fleches d'abord et ensuite les noeuds par *dessus* afin
     * d'eviter le calcul des points d'encrages.
     */
    DisplayEdges(graph->edges, dpy, window, draw_gc);
    DisplayNodes(graph->nodes, dpy, window, draw_gc, fill_gc);
}

/* affiche une liste de nodes */
DisplayNodes(nodes, dpy, window, draw_gc, fill_gc)
    Node nodes;
    Display *dpy;
    Window window;
    GC draw_gc;
    GC fill_gc;
{
    while (nodes) {
    DisplayNode(nodes, dpy, window, draw_gc, fill_gc);
    nodes = nodes->next;
    }
}

/* affiche un node */
DisplayNode(node, dpy, window, draw_gc, fill_gc)
    Node node;
    Display *dpy;
    Window window;
    GC draw_gc;
    GC fill_gc;
{
    /* on affiche le rectangle : le fond puis le bord */
    if (fill_gc)
    XFillRectangle(dpy, window, fill_gc,
        node->x, node->y, node->width, node->height);
    XDrawRectangle(dpy, window, draw_gc,
    node->x, node->y, node->width, node->height);
    /* on affiche le label */
    if (fill_gc)
    XDrawString(dpy, window, draw_gc,
        node->x + node->baseline_x, node->y + node->baseline_y,
        node->label, strlen(node->label));
}

/* affiche une liste de edges */
DisplayEdges(edges, dpy, window, gc)
    Edge edges;
    Display *dpy;
    Window window;
    GC gc;
{
    while (edges) {
    DisplayEdge(edges, dpy, window, gc);
    edges = edges->next;
    }
}

/* affiche une edge */
DisplayEdge(edge, dpy, window, gc)
    Edge edge;
    Display *dpy;
    Window window;
    GC gc;
{
    /* on affiche une droite reliant le centre des 2 noeuds */
    int x1, y1, x2, y2;

    x1 = edge->from->x + edge->from->width / 2;
    y1 = edge->from->y + edge->from->height / 2;
    x2 = edge->to->x + edge->to->width / 2;
    y2 = edge->to->y + edge->to->height / 2;
    XDrawLine(dpy, window, gc, x1, y1, x2, y2);
}

#define NodeContains(node, x, y) ((x >= node->x) \
                  && (x <= node->x + node->width) \
                  && (y >= node->y) \
                  && (y <= node->y + node->height))

/* retourne le premier node dont la bounding box contient le point (x,y) */
Node
FindNode(graph, x, y)
    Graph graph;
    int x;
    int y;
{
    Node nodes = graph->nodes;

    while (nodes) {
    if (NodeContains(nodes, x, y))
        return nodes;
    nodes = nodes->next;
    }
    return 0;
}



michel.buffa@essi.fr