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