Bargraph with
Time-History
Histbar
Classname: XwHistbarWidgetClass
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.
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 |
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.
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.
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.
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.
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.
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]).
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.
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.
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.
Widget XwCreatehistbar (Widget parent , char *name , ArgList arglist , Cardinal argcount);
Just a conveniance function for creating a histbar Widget.
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.
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.
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.
#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