/* #include <X11/copyright.h> */
/* $XConsortium: Bar.c,v 1.2 88/10/25 17:40:25 swick Exp $ */
/* Copyright Massachusetts Institute of Technology 1987, 1988 */
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include "array.h"
#include "BarP.h"
static Dimension def_dimension = (Dimension)~0;
static XtOrientation def_orient = XtorientHorizontal;
static Boolean def_true = True;
#define DEF_LENGTH ((Dimension) 200)
#define DEF_THICKNESS ((Dimension) 15)
/*
* !! should provide converters for Arrays of some supported types, and
* for fillstyles
*/
static XtResource resources[] = {
#define offset(field) XtOffset(BarWidget, bar.field)
#define Offset(field) XtOffset(BarWidget, field)
/* {name, class, type, size, offset, default_type, default_addr}, */
/*
* We define these core class values to set defaults, so we can
* initialize correctly
*/
{XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
Offset(core.width), XtRDimension, (caddr_t)&def_dimension},
{XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
Offset(core.height), XtRDimension, (caddr_t)&def_dimension},
/* Private bar widget resources */
{XtNlength, XtCLength, XtRDimension, sizeof(Dimension),
offset(length), XtRDimension, (caddr_t) &def_dimension},
{XtNthickness, XtCThickness, XtRDimension, sizeof(Dimension),
offset(thickness), XtRDimension, (caddr_t) &def_dimension},
{XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation),
offset(orientation), XtROrientation, (caddr_t) &def_orient},
{XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
offset(foreground), XtRString, XtDefaultForeground},
{XtNfillStyle, XtCFillStyle, XtRInt, sizeof(int),
offset(fillstyle), XtRInt, (caddr_t) 0},
{XtNpixmaps, XtCPixmaps, XtRArray, sizeof(Array *),
offset(pixmaps), XtRArray, (caddr_t) NULL},
#undef offset
#undef Offset
};
static void ClassInitialize();
static void Initialize();
static void Resize();
static void Redisplay();
BarClassRec barClassRec = {
{ /* core fields */
/* superclass */ (WidgetClass) &widgetClassRec,
/* class_name */ "Bar",
/* widget_size */ sizeof(BarRec),
/* class_initialize */ ClassInitialize,
/* class_part_initialize */ NULL,
/* class_inited */ FALSE,
/* initialize */ Initialize,
/* initialize_hook */ NULL,
/* realize */ XtInheritRealize,
/* actions */ NULL,
/* num_actions */ 0,
/* resources */ resources,
/* num_resources */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
/* compress_exposure */ TRUE,
/* compress_enterleave */ TRUE,
/* visible_interest */ FALSE,
/* destroy */ NULL,
/* resize */ Resize,
/* expose */ Redisplay,
/* set_values */ NULL,
/* set_values_hook */ NULL,
/* set_values_almost */ XtInheritSetValuesAlmost,
/* get_values_hook */ NULL,
/* accept_focus */ NULL,
/* version */ XtVersion,
/* callback_private */ NULL,
/* tm_table */ NULL,
/* query_geometry */ XtInheritQueryGeometry,
/* display_accelerator */ XtInheritDisplayAccelerator,
/* extension */ NULL
},
{ /* Bar class fields */
/* extension */ NULL
}
};
WidgetClass barWidgetClass = (WidgetClass)&barClassRec;
static void
ClassInitialize()
{
XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation,
NULL, (Cardinal)0 );
}
static void
SetDimensions(w)
BarWidget w;
{
if (w->bar.orientation == XtorientVertical) {
w->bar.length = w->core.height;
w->bar.thickness = w->core.width;
}
else {
w->bar.length = w->core.width;
w->bar.thickness = w->core.height;
}
}
/*
* We can't use XtGetGC, since we're going to write to the GC, so we use
* a simple caching scheme to share a gc between Bar widgets of the same
* fillstyle on the same display. The first Bar widget in gets to be
* the GC we cache. For most applications, all Bars will be on one
* display and use the same fillStyle, we hope.
*/
static GC gc_cache;
static Display *dpy_cache;
static int fstyle_cache;
/* ARGSUSED */
static void
Initialize(request, new)
Widget request; /* what the client asked for */
Widget new; /* what we're going to give him */
{
BarWidget w = (BarWidget) new;
XGCValues gcv;
Display *dpy = XtDisplay(new);
if (dpy_cache == NULL || w->bar.fillstyle != fstyle_cache ||
dpy_cache != dpy) {
gcv.fill_style = w->bar.fillstyle;
gcv.foreground = w->bar.foreground;
gcv.background = w->core.background_pixel;
w->bar.gc = XCreateGC(dpy, DefaultRootWindow(dpy),
GCFillStyle | GCForeground | GCBackground, &gcv);
if (dpy_cache == NULL) {
dpy_cache = dpy;
fstyle_cache = w->bar.fillstyle;
gc_cache = w->bar.gc;
}
} else {
w->bar.gc = gc_cache;
}
/* Width and height override length and thickness */
if (w->bar.length == def_dimension)
w->bar.length = DEF_LENGTH;
if (w->bar.thickness == def_dimension)
w->bar.thickness = DEF_THICKNESS;
if (w->core.width == def_dimension)
w->core.width = (w->bar.orientation == XtorientVertical)
? w->bar.thickness : w->bar.length;
if (w->core.height == def_dimension)
w->core.height = (w->bar.orientation == XtorientHorizontal)
? w->bar.thickness : w->bar.length;
w->bar.values = NULL;
w->bar.nvalues = 0;
SetDimensions(w);
}
/* ARGSUSED */
static void
Resize(gw)
Widget gw;
{
SetDimensions((BarWidget)gw);
Redisplay(gw, (XEvent*)NULL, (Region)NULL);
}
/* ARGSUSED */
static void
Redisplay(gw, event, region)
Widget gw;
XEvent *event;
Region region;
{
BarWidget w = (BarWidget) gw;
int x, y;
unsigned int width, height;
int maxvalue, i;
int vertical = (w->bar.orientation == XtorientVertical);;
if (! XtIsRealized(gw))
return;
for(maxvalue = 0, i = 0; i < w->bar.nvalues; i++)
maxvalue += w->bar.values[i];
if(maxvalue <= 0)
return;
x = y = 0;
if(vertical)
width = w->bar.thickness;
else
height = w->bar.thickness;
if (w->bar.nvalues > w->bar.pixmaps->nitems) {
XtWarning("Too many values to represent in a bar");
return;
}
for(i = 0; i < w->bar.nvalues; i++) {
unsigned int rectlen = (w->bar.length * w->bar.values[i] +
maxvalue / 2) / (unsigned int)maxvalue;
if (rectlen == 0)
continue;
if (i == w->bar.nvalues - 1) {
if (vertical)
rectlen = w->core.height - y;
else
rectlen = w->core.width - x;
}
switch (w->bar.fillstyle) {
case FillSolid:
XSetForeground(XtDisplay(gw), w->bar.gc,
((Pixel *) w->bar.pixmaps->items)[i]);
break;
case FillTiled:
XSetTile(XtDisplay(gw), w->bar.gc,
((Pixmap *) w->bar.pixmaps->items)[i]);
break;
case FillStippled:
case FillOpaqueStippled:
XSetStipple(XtDisplay(gw), w->bar.gc,
((Pixmap *) w->bar.pixmaps->items)[i]);
break;
}
if(vertical) {
XFillRectangle(XtDisplay(gw), XtWindow(gw), w->bar.gc,
x, y, width, rectlen);
y += rectlen;
} else {
XFillRectangle(XtDisplay(gw), XtWindow(gw), w->bar.gc,
x, y, rectlen, height);
x += rectlen;
}
}
}
/* !! We really should make the widget support Xt{Get,Set}Values fully */
/* Public routines. */
void
SetBarValues(gw, values, nvalues)
Widget gw;
int *values;
int nvalues;
{
BarWidget w = (BarWidget) gw;
int i;
if (nvalues > w->bar.pixmaps->nitems) {
#define ERRFMT "Tried to set %d values for bar - maximum is %d\n"
char errbuf[sizeof(ERRFMT) + 32];
(void) sprintf(errbuf, ERRFMT, nvalues, w->bar.pixmaps->nitems);
#undef ERRFMT
XtWarning(errbuf);
nvalues = w->bar.pixmaps->nitems;
}
if (nvalues <= 0) {
#define ERRFMT "Tried to set %d values for bar - it must be > 0\n"
char errbuf[sizeof(ERRFMT) + 32];
(void) sprintf(errbuf, ERRFMT, nvalues);
XtWarning(errbuf);
#undef ERRFMT
return;
}
if (w->bar.values == NULL || w->bar.nvalues < nvalues) {
if (w->bar.values) XtFree((char *) w->bar.values);
w->bar.values = (int *) XtMalloc(nvalues * sizeof(int));
}
w->bar.nvalues = nvalues;
for(i = 0; i < nvalues; i++)
w->bar.values[i] = values[i];
Redisplay( gw, (XEvent*)NULL, (Region)NULL );
}
syntax highlighted by Code2HTML, v. 0.9.1