/* newslider.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lui.h"
/* MJK 12.04.98 */
/* 22Sep97 Phil McDonald */
# include <math.h>
#define X_MARGIN 10
#define Y_MARGIN 4
#define SLIDER_BAR_LEN(s) ( s->width - 2 * X_MARGIN )
#define LUI_SLIDER_INACTIVE 0
#define LUI_SLIDER_ACTIVE 1
#define LUI_SLIDER_INT 0
#define LUI_SLIDER_FLOAT 1
/* MJK 12.04.98 */
/* 22Sep97 Phil McDonald */
static int make_string( LUI_NEWSLIDER *slider, float value, char *fmt,
char *retstr )
{
if (slider->type == LUI_SLIDER_FLOAT) {
char tmp[64], *c, *d;
if (strlen (fmt) > 0)
{
sprintf (retstr, fmt, value);
return strlen(retstr);
}
#ifdef JOHAN
static int make_string( LUI_NEWSLIDER *slider, float value, char *retstr )
{
if (slider->type == LUI_SLIDER_FLOAT) {
char tmp[64], *c, *d;
#endif
/* changed by BP on 10-15-91 to a format based upon value */
if (value>=0.01 || value<=-0.01)
sprintf(tmp, "%7.2f", value);
else
sprintf(tmp, "%7.5f", value);
for (c = tmp; *c == ' '; ++c);
/* remove trailing 0's - WLH 10-21-91 */
while((d = strrchr(c, '0')) == (c + strlen(c) - 1) &&
*(c + strlen(c) - 2) != '.') *d = 0;
sprintf(retstr, "%s", c);
}
else
sprintf(retstr, "%d", (int)(value+0.5));
return(strlen(retstr));
}
static void draw_slider( LUI_NEWSLIDER *s )
{
XPoint pts[4];
int x, y, w, h;
int xc, yc, size;
char caption[128], valstr[128];
/* Fill the background and draw border */
XFillRectangle( LUI_Display, s->window,
#ifdef OLD
/*s->hilite ? LUI_GC_white : */ LUI_GC_gray,
#endif
s->hilite ? LUI_GC_highgray : LUI_GC_gray,
0, 0, s->width, s->height );
LUI_DrawFrame( s->window, 0, 0, s->width, s->height,
LUI_Border, 1 );
/* Draw slider bar groove */
x = X_MARGIN + 6;
y = Y_MARGIN + LUI_Font_height - 1;
w = s->width - 2 * X_MARGIN - 12;
h = 6;
/* tiny end triangles */
XFillRectangle(LUI_Display, s->window, LUI_GC_white, x-6, y, x+12, 2*h);
XFillRectangle(LUI_Display, s->window, LUI_GC_md_grey, x+w, y, 6, 2*h);
pts[0].x = x-6; pts[0].y = y;
pts[1].x = x+w+6; pts[1].y = y;
pts[2].x = x+w; pts[2].y = y+h;
pts[3].x = x; pts[3].y = y+h;
XFillPolygon(LUI_Display, s->window,
LUI_GC_bottom, pts, 4, Convex, CoordModeOrigin);
XDrawLines(LUI_Display, s->window,
LUI_GC_black, pts, 4, CoordModeOrigin);
y += h;
pts[0].x = x; pts[0].y = y;
pts[1].x = x+w; pts[1].y = y;
pts[2].x = x+w+6; pts[2].y = y+h;
pts[3].x = x-6; pts[3].y = y+h;
XFillPolygon(LUI_Display, s->window, /*sl_grey*/
LUI_GC_top, pts, 4, Convex, CoordModeOrigin);
XDrawLines(LUI_Display, s->window,
LUI_GC_black, pts, 4, CoordModeOrigin);
XDrawRectangle(LUI_Display, s->window, LUI_GC_black,
x-6, y-6, w+12, 2*h);
/* Draw slider marker */
if (s->high==s->low) {
x = X_MARGIN;
}
else {
x = X_MARGIN + (SLIDER_BAR_LEN(s)) * (s->value-s->low)
/ (s->high-s->low);
}
y = Y_MARGIN + LUI_Font_height - 1;
w = 6;
h = 6;
/* changed to red tick by BEP 4-30-93 */
pts[0].x = x; pts[0].y = y;
pts[1].x = x+w; pts[1].y = y+h;
pts[2].x = x; pts[2].y = y+h*2;
pts[3].x = x-w; pts[3].y = y+h;
XFillPolygon(LUI_Display, s->window,
LUI_GC_black, pts, 4, Convex, CoordModeOrigin);
pts[0].x = x; pts[0].y = y+3;
pts[1].x = x+w-3; pts[1].y = y+h;
pts[2].x = x; pts[2].y = y+h*2-3;
pts[3].x = x-w+3; pts[3].y = y+h;
XFillPolygon(LUI_Display, s->window,
LUI_GC_red, pts, 4, Convex, CoordModeOrigin);
yc = Y_MARGIN + LUI_Font_yoff - 1;
/* MJK 12.04.98 */
/* 22Sep97 Phil McDonald */
{
char fmt[20] = "";
float range;
int ndigits;
range = (s->high > s->low) ? s->high - s->low : s->low - s->high;
if (range == 0.0) range = 1.0;
ndigits = (2.5 - log10 (range));
if (ndigits < 0) ndigits = 0;
if (ndigits > 9) ndigits = 9;
sprintf (fmt, "%%.%df", ndigits);
/* Label & current value */
make_string( s, s->value, fmt, valstr );
sprintf(caption, "%s = %s", s->label, valstr);
if (s->units != NULL && strlen (s->units) > 0)
{
strcat (caption, " ");
strcat (caption, s->units);
}
size = strlen(caption);
xc = s->width / 2 - XTextWidth(LUI_Font, caption, size) / 2.0 + 0.5;
XDrawString(LUI_Display, s->window, LUI_GC_black, xc, yc, caption, size);
/* Low labels */
size = make_string( s, s->low, fmt, valstr );
xc = X_MARGIN - 3;
XDrawString(LUI_Display, s->window, LUI_GC_black, xc, yc, valstr, size);
/* High label */
size = make_string( s, s->high, fmt, valstr );
xc = X_MARGIN + SLIDER_BAR_LEN(s) - XTextWidth(LUI_Font, valstr, size) + 3;
XDrawString(LUI_Display, s->window, LUI_GC_black, xc, yc, valstr, size);
}
#ifdef JOHAN
/* Label & current value */
make_string( s, s->value, valstr );
sprintf(caption, "%s = %s", s->label, valstr);
size = strlen(caption);
xc = s->width / 2 - XTextWidth(LUI_Font, caption, size) / 2.0 + 0.5;
XDrawString(LUI_Display, s->window, LUI_GC_black, xc, yc, caption, size);
/* Low labels */
size = make_string( s, s->low, valstr );
xc = X_MARGIN - 3;
XDrawString(LUI_Display, s->window, LUI_GC_black, xc, yc, valstr, size);
/* High label */
size = make_string( s, s->high, valstr );
xc = X_MARGIN + SLIDER_BAR_LEN(s) - XTextWidth(LUI_Font, valstr, size) + 3;
XDrawString(LUI_Display, s->window, LUI_GC_black, xc, yc, valstr, size);
#endif
}
static int slider_process( LUI_NEWSLIDER *s, XEvent *event )
{
switch (event->type) {
case EnterNotify:
s->hilite = 1;
draw_slider( s );
break;
case LeaveNotify:
s->hilite = 0;
draw_slider( s );
break;
case Expose:
draw_slider( s );
break;
case ButtonPress:
s->state = LUI_SLIDER_ACTIVE;
s->button = event->xbutton.button; /* WLH added 12-12-91 */
/* fall through to .... */
case MotionNotify:
if (s->state == LUI_SLIDER_ACTIVE) {
float x_in_pixels; /* inside slide bar range */
if (event->type==ButtonPress) {
x_in_pixels = event->xbutton.x - X_MARGIN;
}
else {
x_in_pixels = event->xmotion.x - X_MARGIN;
}
/* clamp value: */
if (x_in_pixels<0) {
x_in_pixels = 0;
}
else if (x_in_pixels > SLIDER_BAR_LEN(s)) {
x_in_pixels = SLIDER_BAR_LEN(s);
}
/* map from slider pixels to application range: */
s->value = s->low + (s->high-s->low) *
x_in_pixels/(SLIDER_BAR_LEN(s));
if (s->type == LUI_SLIDER_INT) {
s->value = (int)(s->value + 0.5);
}
if (s->old_value != s->value) {
if (s->callback) {
(*(s->callback))(s, s->value);
}
draw_slider( s );
}
s->old_value = s->value;
}
break;
case ButtonRelease:
s->state = LUI_SLIDER_INACTIVE;
/* s->hilite = 0;*/
/* This might cause problems: Added to allow an application to */
/* only do stuff on a button release */
if (s->callback) {
(*(s->callback))(s, s->value );
}
draw_slider( s );
break;
}
/* Flush remaining motion events in event queue */
while (QLength(LUI_Display) > 0) {
XEvent ne;
XPeekEvent(LUI_Display, &ne);
/* Don't flush if its a button press or release */
if (ne.type != MotionNotify)
break;
/* Get the next event */
XNextEvent(LUI_Display, &ne);
}
return 0;
}
void LUI_NewSliderDestroy( LUI_NEWSLIDER *s )
{
XDestroyWindow( LUI_Display, s->window );
if (s->label) {
free( s->label );
}
/* MJK 12.04.98 */
/* 24Nov97 Phil McDonald */
if (s->units) free (s->units);
free( s );
}
LUI_NEWSLIDER *LUI_NewSliderCreate( Window parent, int x, int y, int width )
{
LUI_NEWSLIDER *s;
int height;
height = 36;
LUI_LayoutCheck( &x, &y, &width, &height );
s = (LUI_NEWSLIDER *) malloc( sizeof(LUI_NEWSLIDER) );
if (!s) {
return NULL;
}
/* Create the slider window */
s->window = XCreateSimpleWindow( LUI_Display, parent,
x, y, width-2, height-2,
1, LUI_Color_black, LUI_Color_gray );
LUI_EventAdd2( s->window,
ExposureMask | ButtonPressMask | ButtonReleaseMask
| ButtonMotionMask | EnterWindowMask | LeaveWindowMask,
(LUI_FNCP) slider_process, s );
XMapWindow(LUI_Display, s->window);
/* Initialize slider */
s->label = strdup("");
s->x = x;
s->y = y;
s->width = width - 2;
s->height = height - 2;
s->state = LUI_SLIDER_INACTIVE;
s->type = LUI_SLIDER_FLOAT;
s->low = 0.0;
s->high = 1.0;
s->value = 0.5;
s->old_value = 0.5;
s->index = 0;
s->callback = NULL;
s->context_index = context_index;
s->hilite = 0;
/* MJK 12.04.98 */
/* 22Sep97 Phil McDonald */
s->units = strdup("");
LUI_AddWidgetToWindow( parent, s, (LUI_FNCP) LUI_NewSliderDestroy );
return s;
}
void LUI_NewSliderCallback( LUI_NEWSLIDER *s,
int (*callback)( LUI_NEWSLIDER *, float ) )
{
s->callback = callback;
}
void LUI_NewSliderSetLabel( LUI_NEWSLIDER *s, char *label )
{
if (s->label) {
free(s->label);
}
s->label = strdup( label );
}
void LUI_NewSliderSetRange( LUI_NEWSLIDER *s, float min, float max )
{
s->low = min;
s->high = max;
draw_slider( s );
}
void LUI_NewSliderSetValue( LUI_NEWSLIDER *s, float value )
{
s->value = value;
draw_slider( s );
}
/* MJK 12.04.98 */
/* 22Sep97 Phil McDonald */
void LUI_NewSliderSetUnits( LUI_NEWSLIDER *s, char *units )
{
if (s->units) {
free(s->units);
}
if (units != NULL){
s->units = strdup( units );
}
else{
s->units = NULL;
}
}
void LUI_NewSliderChange( LUI_NEWSLIDER *s, char *label, char *units,
float min, float max, float value)
{
LUI_NewSliderSetLabel( s, label );
LUI_NewSliderSetUnits( s, units );
LUI_NewSliderSetRange( s, min, max );
/* 18Feb98 Phil McDonald */
if (value < min) value = min;
if (value > max) value = max;
LUI_NewSliderSetValue( s, value );
}
#ifdef JOHAN
void LUI_NewSliderChange( LUI_NEWSLIDER *s, char *label,
float min, float max, float value )
{
LUI_NewSliderSetLabel( s, label );
LUI_NewSliderSetRange( s, min, max );
LUI_NewSliderSetValue( s, value );
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1