home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / x / volume10 / xt-examples / part04 / BarDisplay.c next >
C/C++ Source or Header  |  1990-11-04  |  8KB  |  250 lines

  1. /***********************************************************
  2. Copyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
  3.  
  4.                         All Rights Reserved
  5.  
  6. Permission to use, copy, modify, and distribute these examples for any
  7. purpose and without fee is hereby granted, provided that the above
  8. copyright notice appear in all copies and that both that copyright
  9. notice and this permission notice appear in supporting documentation,
  10. and that the name of Digital not be used in advertising or publicity
  11. pertaining to distribution of the software without specific, written
  12. prior permission.
  13.  
  14. DIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  15. SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  16. FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
  17. OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  18. OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  19. OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  20. OR PERFORMANCE OF THIS SOFTWARE.
  21.  
  22. ******************************************************************/
  23.  
  24. #include <X11/IntrinsicP.h>    /* Intrinsics header file */
  25. #include <X11/StringDefs.h>    /* Resource string definitions */
  26. #include "BarDisplaP.h"        /* Bar display object */
  27. #include "GraphP.h"        /* Graph widget */
  28.  
  29. #define Offset(field) XtOffsetOf(BarDisplayRec, barDisplay.field)
  30.  
  31. static XtResource resources[] = {
  32.     {XtNspace, XtCSpace, XtRDimension, sizeof(Dimension),
  33.         Offset(space), XtRImmediate, (XtPointer) 5},
  34.     {XtNdefaultGraphWidth, XtCDefaultGraphWidth,
  35.     XtRDimension, sizeof(Dimension),
  36.         Offset(default_graph_width), XtRImmediate, (XtPointer) 200},
  37.     {XtNformat, XtCFormat, XtRString, sizeof(String),
  38.     Offset(format), XtRString, "%g"}
  39. };
  40. #undef Offset
  41.  
  42. /* Forward declarations */
  43.  
  44. static void Initialize(), Redisplay(), ComputeSize();
  45. static Boolean SetValues();
  46.  
  47. /* Class record declaration */
  48.  
  49. BarDisplayClassRec barDisplayClassRec = {
  50.     /* Object class part */
  51.   {
  52.     /* superclass         */    (WidgetClass) &graphDisplayClassRec,
  53.     /* class_name         */    "BarDisplay",
  54.     /* widget_size         */    sizeof(BarDisplayRec),
  55.     /* class_initialize      */ NULL,
  56.     /* class_part_initialize */    NULL,
  57.     /* class_inited          */    FALSE,
  58.     /* initialize         */    Initialize,
  59.     /* initialize_hook       */    NULL,        
  60.     /* obj1             */    NULL,
  61.     /* obj2             */    NULL,
  62.     /* obj3             */    0,
  63.     /* resources         */    resources,
  64.     /* num_resources         */    XtNumber(resources),
  65.     /* xrm_class         */    NULLQUARK,
  66.     /* obj4             */    0,
  67.     /* obj5             */    0,
  68.     /* obj6             */    0,
  69.     /* obj7             */    0,
  70.     /* destroy             */    NULL,
  71.     /* obj8             */    NULL,
  72.     /* obj9             */    NULL,
  73.     /* set_values         */    SetValues,
  74.     /* set_values_hook       */    NULL,            
  75.     /* obj10             */    NULL,  
  76.     /* get_values_hook       */    NULL,            
  77.     /* obj11             */    NULL,
  78.     /* version             */    XtVersion,
  79.     /* callback offsets      */ NULL,
  80.     /* obj12             */ NULL,
  81.     /* obj13             */    NULL,
  82.     /* obj14             */ NULL,
  83.     /* extension             */ NULL
  84.   },
  85.     /* GraphDisplay class part    */
  86.   {
  87.     /* compute_size         */ ComputeSize,
  88.     /* expose             */ Redisplay,
  89.     /* extension             */ NULL
  90.   },
  91.     /* BarDisplay class part  */
  92.   {
  93.     /* extension             */ NULL
  94.   }
  95. };
  96.  
  97. /* Class record pointer */
  98.  
  99. WidgetClass barDisplayObjectClass = (WidgetClass) &barDisplayClassRec;
  100.  
  101. static void Initialize(request, new, args, num_args)
  102.     Widget request, new;
  103.     ArgList args;
  104.     Cardinal *num_args;
  105. {
  106.     BarDisplayObject bd = (BarDisplayObject) new;
  107.  
  108.     /* Copy format */
  109.     bd->barDisplay.format = XtNewString(bd->barDisplay.format);
  110. }
  111.  
  112. static Boolean SetValues(old, request, new, args, num_args)
  113.     Widget  old, request, new;
  114.     ArgList args;
  115.     Cardinal *num_args;
  116. {
  117.     BarDisplayObject oldbd = (BarDisplayObject) old;
  118.     BarDisplayObject newbd = (BarDisplayObject) new;
  119.  
  120. #define NE(field) (oldbd->barDisplay.field != newbd->barDisplay.field)
  121.  
  122.     if (NE(format)) {
  123.     newbd->barDisplay.format =
  124.         XtNewString(newbd->barDisplay.format);
  125.     }
  126.  
  127.     /* If space or format has changed and we're realized, redisplay */
  128.  
  129.     if (NE(space) || NE(format)) {
  130.  
  131.     /* Kludge.  There's no way to tell the Intrinsics to
  132.        automatically redisplay, so clear the parent, causing
  133.        expose events.  Subclasses will do this too, but multiple
  134.        redisplays are avoided since the parent has
  135.        XtExposeCompressMultiple. */
  136.  
  137.     if (XtIsRealized(XtParent((Widget) newbd))) {
  138.         XClearArea(XtDisplayOfObject(newbd),
  139.             XtWindowOfObject(newbd), 0, 0, 0, 0, TRUE);
  140.     }
  141.     }
  142.  
  143.     return FALSE;
  144. }
  145.  
  146. static void ComputeLabelDimensions(bd, label_w, total_w, height)
  147.     BarDisplayObject bd;
  148.     Dimension *label_w, *total_w, *height;
  149. {
  150.     register XFontStruct *fs = bd->graphDisplay.font;
  151.     register int i;
  152.     int width;
  153.     GraphWidget parent = (GraphWidget) XtParent((Widget) bd);
  154.     char buf[100];
  155.  
  156.     *label_w = *total_w = 0;
  157.     if (parent->graph.labels != NULL) {
  158.     for (i = 0; i < parent->graph.num_entries; i++) {
  159.         width = XTextWidth(fs, parent->graph.labels[i],
  160.             strlen(parent->graph.labels[i]));
  161.         if (width > *label_w) *label_w = width;
  162.     }
  163.     }
  164.  
  165.     for (i = 0; i < parent->graph.num_entries; i++) {
  166.     (void) sprintf(buf, bd->barDisplay.format,
  167.         (float) parent->graph.values[i] / parent->graph.scale);
  168.     width = XTextWidth(fs, buf, strlen(buf));
  169.     if (width > *total_w) *total_w = width;
  170.     }
  171.  
  172.     *total_w += *label_w;
  173.     *height = fs->max_bounds.ascent + fs->max_bounds.descent;
  174. }
  175.  
  176. static void ComputeSize(w)
  177.     GraphWidget w;
  178. {
  179.     BarDisplayObject bd = (BarDisplayObject) w->composite.children[0];
  180.     Dimension label_width, total_width, label_height;
  181.  
  182.     ComputeLabelDimensions(bd, &label_width,
  183.         &total_width, &label_height);
  184.     
  185.     /* If parent has no width, compute one */
  186.     if (w->core.width == 0) {
  187.     w->core.width = 4*bd->barDisplay.space + total_width +
  188.         bd->barDisplay.default_graph_width;
  189.     }
  190.  
  191.     /* If parent has no height, compute one */
  192.     if (w->core.height == 0) {
  193.     w->core.height = w->graph.num_entries *
  194.         (bd->barDisplay.space + label_height) +
  195.         bd->barDisplay.space;
  196.     }
  197. }
  198.  
  199. static void Redisplay(w, event, region)
  200.     GraphWidget w;
  201.     XEvent *event;
  202.     Region region;
  203. {
  204.     BarDisplayObject bd = (BarDisplayObject) w->composite.children[0];
  205.     Dimension label_width, total_width, label_height;
  206.     Boolean displayBars;
  207.     register int i;
  208.     int x, y, bar_width;
  209.     char buf[100];
  210.     register int *values = w->graph.values;
  211.     register String *labels = w->graph.labels;
  212.  
  213.     ComputeLabelDimensions(bd, &label_width, &total_width,
  214.         &label_height);
  215.     
  216.     /* See if there's enough room to display bars */
  217.  
  218.     bar_width = w->core.width - total_width - 4*bd->barDisplay.space;
  219.     displayBars = (bar_width > (int) bd->barDisplay.space);
  220.  
  221.     y = bd->barDisplay.space;
  222.     for (i = 0; i < w->graph.num_entries; i++) {
  223.     if (labels != NULL) {
  224.         XDrawString(XtDisplay(w), XtWindow(w), bd->graphDisplay.gc,
  225.             bd->barDisplay.space,
  226.             y + bd->graphDisplay.font->max_bounds.ascent,
  227.             labels[i], strlen(labels[i]));
  228.         x = label_width + 2*bd->barDisplay.space;
  229.     } else x = 0;
  230.  
  231.     if (displayBars) {
  232.         XFillRectangle(XtDisplay(w), XtWindow(w),
  233.             bd->graphDisplay.gc, x, y, 
  234.             bar_width * values[i] / w->graph.max_value,
  235.             bd->graphDisplay.font->max_bounds.ascent);
  236.         x += bar_width * values[i] / w->graph.max_value +
  237.             bd->barDisplay.space;
  238.     }
  239.  
  240.     (void) sprintf(buf, bd->barDisplay.format,
  241.                 (float) values[i] / w->graph.scale);
  242.     XDrawString(XtDisplay(w), XtWindow(w), bd->graphDisplay.gc,
  243.         x, y + bd->graphDisplay.font->max_bounds.ascent,
  244.         buf, strlen(buf));
  245.     
  246.     y += label_height + bd->barDisplay.space;
  247.     }
  248. }
  249.  
  250.