Bargraph with Time-History
Histbar



Classname: XwHistbarWidgetClass

Description:

In order to visualize measurements, people often use bargraphs. This widget shows an easy to use method for displaying bargraphs p.e. in an realtime environment. As normal bargraphs show only the value of the actual time, Histbar is plotting a definable range of time in a 3 D manner for each bar. As time is going on, the history flows into the backgroung. Optiona, the history may not only be visible, but will be stored internally for a definable number of steps, so the user may get the values at any time p.e. to create a paper plot. Using this feature, the programmer has no need to create his own cyclic buffer and, as the widget will handle expose events, he doesn't need to rebuild the plot each time, an expose occurs. Several convenience functions allow to read back the bar value at a certain time or position within the widget.Changing colour, recscaling or adding bars dynamically is implemented as well as displaying actual values and annotation.

Example of a 11 Bars Histbar:


Resources:

The widget includes the »core« and the »primitive« class with all resources. To describe it's special features, it has several resources for it's own. The following table contains the resource-name, the resource-class and the access-type. Defining the resource in a general resourcefile like .Xdefaults, means, leave out the prefix XwN or XwC. The access type defines if the resource may be set at creation »C«, using XtSetValues »S«, only at creation using XtSetArg »CS« and being read using XtGetValues »G«.

Name

Class

Type

Default

Access

XmNinputCallback


XtCallbackList

NULL

S C

XmNexposeCallback

XmCExposeCallback

XtCallbackList

NULL

S C

XmNresizeCallback

XmCResizeCallback

XtCallbackList

NULL

S C

XwNhistbarGridScale

XwCHistbarGridScale

Float[4]

NULL

CS S G

XwNhistbarScale

XwCHistbarScale

Float[4]

NULL

CS S G

XwNhistbarAnnotColor

XwCHistbarAnnotColor

Pixel

inherit

C S G

XwNhistbarBARcolor

XwCHistbarBARcolor

Pixel

inherit

C S G

XwNhistbarAnnotTNdec

XwCHistbarAnnotTNdec

Int

0

C S G

XwNhistbarAnnotYNdec

XwCHistbarAnnotYNdec

Int

0

C S G

XwNhistbarAnnotTNgrid

XwCHistbarAnnotTNgrid

Int

0

C S G

XwNhistbarAnnotYNgrid

XwCHistbarAnnotYNgrid

Int

0

C S G

XwNhistbarNbars

XwCHistbarNbars

Int

DefaultNbars(10)

C S G

XwNhistbarAnnotation

XwCHistbarAnnotation

Int

XwHistbarAnno

C S G

XwNhistbarAddvalue

XwCEdrawAddvalue

Bool

FALSE

C S G

XwNhistbarAddtext

XwCHistbarAddtext

Bool

FALSE

C S G

XmNfontList

XmCFontList

XmFontList

inherit

C S G

XwNhistbarWidth

XwCHistbarWidth

Dimension

DefaultBarWidth

C S G

XwNhistbarSize

XwHistbarSize

int

DefaultBarSize

C S G

XwNhistbarHistory

XwCHistbarHistory

Bool

TRUE

C S G

XwNhistbarHistorysize

XwCHistbarHistorysize

Int

XwHistbarDefaultHistsize

C S G

XwNhistbarAngle

XwCHistbarAngle

Int

XwHistbarDefaultAngle

C S G

Detailed Description of special Resources:

Callbacks:

Possible Callbacks are:

XwNdestroyCallback, XmNexposeCallback, XmresizeCallback, XmNinputCallback. Depending on type of callback, the items within the callbackstructure will have slightly different meaning. The most important callback, I think, will be the Input-Callback, as it returns the scaled position of the cursor.

Callback Structure: (not available using destroy callback)

typedef struct {
int reason;
XEvent *event; int fd;
float time_wid;
int id;
float time_id;
Dimension width;
Dimension height;
}XwhistbarCallbackStruct;


width and height are the dimension of the visible area used for bars.


Input: Only valid for button 1 (left mouse) down)
time_wid time value of cursor position
id The bar-ID next right (or next below) the cursor, negative, if no bar
time_id time value of bar-history of bar vertical below cursor position.

Normally there is no need to handle expose or resize, as the widget does all necessay things itself, but sometimes, it might be useful to react on resize, p.e. resizing the bars.



Resources, that must be set:

XwNhistbarScale XwNhistbarGridScale

There is no possibility to create a barswithout having any scale, so these resources must be set at creation, they might be changed during lifetime.The only method to set them is using SetValue, as they need an array of four float values. The first pair defines the timescale, the second the ordinate. Hold in mind, that the ordinate scale describes only half of the height of the widget. There must be enough space for the history display. XwNhistbarScale uses the first value as the minimum value of the visible area and the second as the size(width/height) of visible area. Internally it scales the total pixmap according to these values. XwNhistbarGridScale uses the first value as the minimum (first) grid(and annotation) value and the second as distance to next annotation. Again, not only the visible, but the total pixmap will be given a time annotation.

Resources, that should be set:

XwNhistbarAnnotation

This resources defines the existance of annotation. Changing the resource at run-time will change the display immediately.

Possible values:
XwHistbarAnno 1 /* annotation */
XwHistbarNoAnno 0 /* no annotation */

XwNhistbarAnnotTNdec XwNhistbarAnnotYNdec

These two control the number of decimals for annotation. Be careful and reduce them to a minimum, as there is no protection against overwriting of numbers. Together with the GridScale it might happen, that the annotation distance is to small for big numbers, therefor the next two resources allow to skip some annotation items without drawing annotation. The number of decimals for the ordinate will influence the number of decimals for displaying the current value.

XwNhistbarAnnotTNgrid XwNhistbarAnnotYNgrid

As the default of 1 shows, they define, how often annotation should be plotted to gridlines. So a value of 2 will say, that every other gridline gets annotation.

Additional controlling Resources:

Colours:

The colour of the bar itself must be set via a public function, as each bar may have a different colour. But all other colours, background, grid, annotation and annotation background may be set as resource.

Resource

Function

default

Remark

XwNHistbarBARcolor

Background colour of the plotting area

Inherited from background

No immediate change

XwNHistbarAnnotColor

Colour for Annotation text

Inherited from foreground

No immediate change

background

Background colour


No immediate change


As the above colours won't change immediately whe you change the resource, but will be effective only when a total redraw is enforced, the colour of the bar can be changed via a public function, the colourchange will affect the new plotted bar only, as long as no enforced redraw will happen.

XwNHistbarAddvalue XwNHistbarAddtext

XwNHistbarAddvalue is a switch, if it is set to true, the actual bar value will be displayed directly below the bar, using the font and colour of annotation.

XwNHistbarAddtext allows the display of a descriptive text below the bars . The text has to be set using a public function.

HISTORY and HISTORY-size:

XwNHistbarHistory XwNHistbarHistorysize

The first is just a switch, enabling the ring-buffer. The default size is fixed using a defined value XwHistbarDefaultHistsize. So normally this size is big enough to hold a lot of points.Using XwNHistbarHistorysize gives a lot more control over the number of points, that can be stored.

BARWIDTH and Distance between bars

XwNhistbarWidth XwNhistbarSize

The first defines the width of all bars in pixels, the second sets the number of times of width are to be used between two bars. The defaúlts are set via defined values, (DefaultBarWidth [10] DefaultBarSize[3]).

Angle of z-axis(time)

XwNhistbarAngle

This resource allows the user to change the history angle, influencing so the effect of 3D. The angle may be varied between 0 an 90 degree, the default is set to 45 degree.


Public Functions

XwHistbarAddbar

long int XwHistbarAddbar (Widget w , unsigned long int Colour);


To use the plotting feature this function must be called first of all after creating the widget. It defines the colour of the requested bar and allocates memory for it. The return value should be used as bar ID for further access of this particular bar. It will be automatically created and counts from zero, so the first ID is 0.


XwHistdobar

void XwHistdobar (Widget w , long int ID , float xy[2] . int flag );

The basic function for plotting. It adds a point to the bar given by it's ID and plots a bar. The flag defines if the new bars should be really displayed, or if the visible update should wait.As all plotting is done in the hidden pixmap, the expose of new bars should be done after plotting the last. This saves a lot of computer power..

flag: zero just do the bar .

not zero, expose the new visible

If there is only one single bar, expose is done every time dobar is called.



XwCreatehistbar

Widget XwCreatehistbar (Widget parent , char *name , ArgList arglist , Cardinal argcount);

Just a conveniance function for creating a histbar Widget.

XwHistbarSettext

void XwHistbarSettext (Widget w , int ID , char *text);

The given text will be displayed ibelow the bar, using the bar's colout. An empty text (or a NULL pointer) will delete the bar's text display.

XwHistbarchangecolor

void XwHistbarchangecolor ( Widget w , int ID , Pixel color);

This function changes the colour for the particular bar. So from now, all newer bars plotted appear in new colour, all elder bars will still have the old colour until a history redraw is done. Text and marker values will change colour immediately.

XwHistbarhistory

void XwHistbarhistory (Widget w , long int ID , float **x , float **y , int *size);

Sometimes there is a need to get all plotted information back to memory. For example to do a hardcopy. If the history option (XwNHistbarHistory) is enabled, this function will allocate (malloc) two arrays, copy the internal history into them and return the addresses together with the number of items. The user is responsible to free the memory after usage.


Example (code fragments)

#include "WHistbar.h"



/* creating the widget */

n = 0;

XtSetArg(args[n], XmNleftAttachment, XmATTACH_SELF); n++;

XtSetArg(args[n], XmNx, 12); n++;

XtSetArg(args[n], XmNtopAttachment, XmATTACH_SELF); n++;

XtSetArg(args[n], XmNy, 64); n++;

XtSetArg(args[n], XmNrightAttachment, XmATTACH_SELF); n++;

XtSetArg(args[n], XmNwidth, 480); n++;

XtSetArg(args[n], XmNheight, 255); n++;

histb = XtCreateWidget("userWidget1", XwHistbarWidgetClass, histbar, args, n);

XtManageChild(histb);



/* scaling the widget, this might be done already at creation */

XwHistbarAddbar( histb , MGetPixel("green",histb));

XwHistbarSettext( histb , 0 , "BAR 0");


{

float scal[4] = {500,50.0,0,800};

float grid[4] = {500,10,0,100};

n = 0;

XtSetArg(args[n], XwNhistbarBARcolor, MGetPixel("black",histb)); n++;

XtSetArg(args[n], XwNhistbarAnnotColor, MGetPixel("blue",histb)); n++;

XtSetArg(args[n],XwNhistbarScale, scal); n++;

XtSetArg(args[n],XwNhistbarGridScale, grid); n++;

XtSetValues(histb,args,n);

XtAddCallback(histb, XmNinputCallback, (XtCallbackProc) input_cb, (XtPointer)NULL);

}


/* adding addition bars */


static void add_a_bar(Widget parent, XtPointer data, XmPushButtonCallbackStruct *cbs)

{

int id;

char annot[30];

if(next <=15){

id = XwHistbarAddbar( histb , MGetPixel(col[next],histb));

next++;

sprintf(annot,"BAR %d",id);

XwHistbarSettext( histb , id , annot);

}

}


/* plotting , add a new barvalue for each bar , increment the time */


static void histplotter(void) {

static double timbase = 500;

int i;

float height,height2 , xy[2] , xya[2] , xyb[2];

/* assume height = 200 */

/* do a sine for height */

xy[1] = (sin(timbase) + 1.0) * 400 * (rand()/(RAND_MAX+1.0));

xya[1] = (sin(timbase/2) + 1.0)*400;

timbase += 0.5 ;

xyb[1] = (sin(timbase/8) + 1.0) * 400;

xyb[0]=xy[0] = xya[0] = timbase;

XwHistdobar ( histb , 0,xy,doit);


for (i=0; i<next;i++){

switch(i){

case 0:

XwHistdobar ( histb , i+1,xya,0);

break;

case 1:

XwHistdobar ( histb , i+1,xyb,0);

break;

default:

xya[1] = (sin((timbase*(1.3*i)/8)) + 1.0)*400;

xya[1] /= (i-1);

XwHistdobar ( histb , i+1,xya,0);

break;

}

}

if(plotr == 1 )

plottimer = XtAppAddTimeOut(XtWidgetToApplicationContext(histb),

rate , (XtTimerCallbackProc)histplotter , NULL);

if(plotr == -1)

MCloseDialog(histb);


}


/* get somevalues back at left mouse button */

static void input_cb(Widget parent, XtPointer data, XwHistbarCallbackStruct *cbs) {

printf("INPUT %d %d",cbs->event->xbutton.x,cbs->event->xbutton.y);

printf("ID: %d hor-time= %f ID-time=%f\n",cbs->id,cbs->time_win,cbs->time_id);


printf("EXTRACT: %f\n",XwHistbarGetValue(parent,cbs->id,cbs->time_id));

}



Inhaltsverzeichnis

Description: 1
Example of a 11 Bars Histbar: 1
Resources: 1
Detailed Description of special Resources: 2
Callbacks: 2
Resources, that must be set: 3
Resources, that should be set: 3
Additional controlling Resources: 3
HISTORY and HISTORY-size: 4
BARWIDTH and Distance between bars 4
Angle of z-axis(time) 4
Public Functions 4
XwHistbarAddbar 4
XwHistdobar 4
XwCreatehistbar 5
XwHistbarSettext 5
XwHistbarchangecolor 5
XwHistbarhistory 5
Example (code fragments) 5