/***********************************************************************/ /* Open Visualization Data Explorer */ /* (C) Copyright IBM Corp. 1989,1999 */ /* ALL RIGHTS RESERVED */ /* This code licensed under the */ /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */ /***********************************************************************/ #include /* Construct and manage the "frame sequencer guide" to be used as a * popup of the "sequence controller" (alias VCR control) * * August 1990 * IBM T.J. Watson Research Center * R. T. Maganti */ /* */ #ifdef OS2 #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include "Number.h" #include "Slider.h" #include "SliderP.h" #define zero pow(0.1,6) #if !defined(HAVE_TRUNC) #define trunc(c) ((double)((int)(c))) #endif /* * Hi, * Subclassing off an XmForm is dangerous. Changing basic widget methods here * is like messing with someone's dna. * * This widget attempted not only to use the attachments of the parent class * but also to redine the resize method. oops. Owning an XmForm might have * been better than being a type of XmForm. * * So be careful. */ /* * Templates of the local subroutines */ static void Initialize( XmSliderWidget request, XmSliderWidget new ); static Boolean SetValues( XmSliderWidget current, XmSliderWidget request, XmSliderWidget new ); static void Destroy( XmSliderWidget sw ); static void Resize( XmSliderWidget sw ); static void CenterNumber( XmSliderWidget sw ); static void CallbackFromNumber (XmNumberWidget w, XmSliderWidget slider, XmDoubleCallbackStruct* call_data); static void CallbackFromArrow ( XmArrowButtonWidget arrow, XmSliderWidget slider, XmAnyCallbackStruct *call_data ); static void CallbackFromScale ( XmScaleWidget scale, XmSliderWidget slider, XmScaleCallbackStruct *call_data ); static void CallbackFromScale2 ( XmScaleWidget scale, XmSliderWidget slider, XmScaleCallbackStruct *call_data ); static XmNumberWidget CreateSliderNumber( int x,int min,double value, int max, char* title, Widget *label, XmSliderWidget slider, Boolean above, Boolean editable, Boolean make_stepper, Boolean label_is_widget ); static double widgetnumber2appl( XmSliderWidget slider, int number ); static int appl2widgetnumber( XmSliderWidget slider, double application_number ); static double round(); extern void _XmForegroundColorDefault(); extern void _XmBackgroundColorDefault(); /* Declare defaults */ #define DEF_MIN 1 #define DEF_MAX 100 #define DEF_STEP 1 #if defined(hp700) || defined(aviion) || defined(solaris) || defined(sun4) || defined (DXD_WIN) || defined(OS2) #define trunc(x) ((double)((int)(x))) #endif #ifndef MAX #define MAX(a,b) (((a) > (b)) ? (a) : (b)) #endif static double DefaultMinDbl = DEF_MIN; static double DefaultMaxDbl = DEF_MAX; static float DefaultMinFlt = DEF_MIN; static float DefaultMaxFlt = DEF_MAX; static double DefaultCurrentDbl = (DEF_MIN + DEF_MAX) / 2; static XtResource resources[] = { { XmNcurrent, XmCCurrent, XmRDouble, sizeof(double), XtOffset(XmSliderWidget, slider.application_current_value), XmRDouble, (caddr_t) &DefaultCurrentDbl }, { XmNmaximum, XmCMaximum, XmRDouble, sizeof(double), XtOffset(XmSliderWidget, slider.application_max_value), XmRDouble, (caddr_t) &DefaultMaxDbl }, { XmNminimum, XmCMinimum, XmRDouble, sizeof(double), XtOffset(XmSliderWidget, slider.application_min_value), XmRDouble, (caddr_t) &DefaultMinDbl }, { XmNdataType, XmCDataType, XmRInt, sizeof(int), XtOffset(XmSliderWidget, slider.number_type), XmRImmediate, (caddr_t) INTEGER }, { XmNdecimalPlaces, XmCDecimalPlaces, XmRInt, sizeof(int), XtOffset(XmSliderWidget, slider.decimal_places), XmRImmediate, (caddr_t) 0 }, { XmNincrement, XmCIncrement, XmRDouble, sizeof(double), XtOffset(XmSliderWidget, slider.increment), XmRDouble, (caddr_t) &DefaultMinDbl }, { XmNvalueCallback, XmCValueCallback, XmRCallback, sizeof(caddr_t), XtOffset(XmSliderWidget, slider.value_callback), XmRCallback, NULL }, { XmNlimitColor, XmCLimitColor, XmRPixel, sizeof(Pixel), XtOffset(XmSliderWidget, slider.limit_color), XmRCallProc, (caddr_t) _XmForegroundColorDefault }, { XmNcurrentColor, XmCCurrentColor, XmRPixel, sizeof(Pixel), XtOffset(XmSliderWidget, slider.current_color), XmRCallProc, (caddr_t) _XmForegroundColorDefault }, }; /* Maintain actions support for basic manager functioning */ static char defaultTranslations[] = ": Enter() \n\ : FocusIn()"; extern void _XmManagerEnter(); extern void _XmManagerFocusIn(); static XtActionsRec actionsList[] = { { "Enter", (XtActionProc) _XmManagerEnter }, { "FocusIn", (XtActionProc) _XmManagerFocusIn }, }; /**************************************************************** * * Full class record constant * ****************************************************************/ XmSliderClassRec xmSliderClassRec = { { /* core_class fields */ (WidgetClass) &xmFormClassRec, /* superclass */ "XmSlider", /* class_name */ (Cardinal)sizeof(XmSliderRec), /* widget_size */ NULL, /* class_initialize */ NULL, /* class_part_init */ FALSE, /* class_inited */ (XtInitProc) Initialize, /* initialize */ NULL, /* initialize_hook */ (XtRealizeProc)_XtInherit, /* realize */ actionsList, /* actions */ XtNumber(actionsList), /* num_actions */ resources, /* resources */ XtNumber(resources), /* num_resources */ (XrmClass)NULLQUARK, /* xrm_class */ False, /* compress_motion */ False, /* compress_exposure */ TRUE, /* compress_enterlv */ FALSE, /* visible_interest */ (XtWidgetProc) Destroy, /* destroy */ (XtWidgetProc)_XtInherit, /* resize */ (XtExposeProc)_XtInherit, /* expose */ (XtSetValuesFunc) SetValues, /* set_values */ NULL, /* set_values_hook */ (XtAlmostProc)_XtInherit, /* set_values_almost */ NULL, /* get_values_hook */ NULL, /* accept_focus */ XtVersion, /* version */ NULL, /* callback_private */ defaultTranslations, /* tm_table */ XtInheritQueryGeometry, /* query_geometry */ (XtStringProc)NULL, /* display_accelerator */ (XtPointer)NULL, /* extension */ }, { /* composite_class fields */ XtInheritGeometryManager, /* geometry_manager */ (XtWidgetProc)_XtInherit, /* from BulletinBoard *//* change_managed */ (XtWidgetProc)_XtInherit, /* insert_child */ (XtWidgetProc)_XtInherit, /* delete_child */ NULL, /* extension */ }, { /* constraint_class fields */ NULL, /* resource list */ 0, /* num resources */ sizeof(XmFormConstraintRec), /* constraint size */ NULL, /* init proc */ NULL, /* destroy proc */ NULL, /* set values proc */ NULL, /* extension */ }, { /* manager_class fields */ #if (XmVersion >= 1001) XtInheritTranslations, /* translations */ #else (XtTranslations)_XtInherit, /* translations */ #endif NULL, /* get resources */ 0, /* num get_resources */ NULL, /* get_cont_resources */ 0, /* num_get_cont_resources */ (XmParentProcessProc)NULL, /* parent_process */ NULL, /* extension */ }, { /* bulletin board class - none */ NULL, /* mumble */ NULL, /* mumble */ }, { /* form class - none */ NULL, /* mumble */ }, { /* slider class - none */ NULL, /* mumble */ } }; WidgetClass xmSliderWidgetClass = (WidgetClass) &xmSliderClassRec; /* Subroutine: Initialize * Purpose: Create and Initialize the component widgets */ static void Initialize( XmSliderWidget request, XmSliderWidget new ) { #if (XmVersion < 1001) short thick; #else Dimension thick; #endif int n = 0; Dimension h; Arg wargs[40], wargs2[40]; XColor screen_color, exact_color; double dval; if (new->core.width < 200) new->core.width = 200; if (new->core.height < 55) new->core.height = 55; if (new->slider.application_max_value == new->slider.application_min_value) new->slider.aslope = 1.0 / zero; else new->slider.aslope = 1.0 / (new->slider.application_max_value - new->slider.application_min_value); new->slider.min_value = 0; if (new->slider.increment == 0) new->slider.max_value = new->slider.min_value; else { int places; places = new->slider.decimal_places; places = (places<2?2:places); places = (places>7?7:places); new->slider.max_value = pow ((double)10, (double)places); } if (new->slider.max_value==new->slider.min_value) new->slider.wslope = 1.0 / zero; else new->slider.wslope = 1.0 / (double)(new->slider.max_value - new->slider.min_value); new->slider.current_number = CreateSliderNumber(7, new->slider.min_value, new->slider.application_current_value, new->slider.max_value, " current", (Widget *)&new->slider.current_label, new, FALSE, TRUE, FALSE, FALSE); n = 0; XtSetArg ( wargs2[n], XmNarrowDirection, XmARROW_LEFT ); n++; new->slider.left_arrow = (XmArrowButtonWidget) XmCreateArrowButton((Widget)new, "left_arrow", wargs2, n); XtAddCallback((Widget)new->slider.left_arrow, XmNactivateCallback, (XtCallbackProc)CallbackFromArrow, new); XtManageChild((Widget)new->slider.left_arrow); n = 0; XtSetArg ( wargs2[n], XmNarrowDirection, XmARROW_RIGHT ); n++; new->slider.right_arrow = (XmArrowButtonWidget) XmCreateArrowButton((Widget)new, "right_arrow", wargs2, n ); XtAddCallback((Widget)new->slider.right_arrow, XmNactivateCallback, (XtCallbackProc)CallbackFromArrow, new); XtManageChild((Widget)new->slider.right_arrow); XtSetArg ( wargs2[0], XmNheight, &h ); XtGetValues ( (Widget)new->slider.right_arrow, wargs2, 1 ); n = 0; new->slider.current_value = appl2widgetnumber(new, new->slider.application_current_value); XtSetArg(wargs[n], XmNvalue, new->slider.current_value); n++; XtSetArg(wargs[n], XmNmaximum, new->slider.max_value); n++; XtSetArg(wargs[n], XmNminimum, 0 ); n++; XtSetArg(wargs[n], XmNscaleHeight, h); n++; XtSetArg(wargs[n], XmNtopAttachment, XmATTACH_FORM); n++; XtSetArg(wargs[n], XmNleftAttachment, XmATTACH_FORM); n++; XtSetArg(wargs[n], XmNleftOffset, 30); n++; XtSetArg(wargs[n], XmNbottomAttachment, XmATTACH_FORM); n++; XtSetArg(wargs[n], XmNbottomOffset, 36); n++; XtSetArg(wargs[n], XmNrightAttachment, XmATTACH_FORM); n++; XtSetArg(wargs[n], XmNrightOffset, 30); n++; XtSetArg(wargs[n], XmNorientation, XmHORIZONTAL ); n++; XtSetArg(wargs[n], XmNprocessingDirection, XmMAX_ON_RIGHT ); n++; #if (XmVersion < 1001) XtSetArg(wargs[n], XmNshadowThickness, new->manager.shadow_thickness); n++; #else XtSetArg(wargs[n], XmNshadowThickness, 1); n++; #endif new->slider.bar = (XmScaleWidget)XmCreateScale((Widget)new, "scale", wargs, n); XtAddCallback((Widget)new->slider.bar, XmNdragCallback,(XtCallbackProc)CallbackFromScale , new); XtAddCallback((Widget)new->slider.bar, XmNvalueChangedCallback,(XtCallbackProc)CallbackFromScale, new); XtManageChild((Widget)new->slider.bar); XtSetArg ( wargs2[0], XmNshadowThickness, &thick ); XtGetValues ((Widget) new->slider.bar, wargs2, 1 ); #if (XmVersion < 1001) XtSetArg ( wargs2[0], XmNshadowThickness, thick ); #else XtSetArg ( wargs2[0], XmNshadowThickness, 0 ); #endif XtSetValues ((Widget) new->slider.left_arrow, wargs2, 1 ); #if (XmVersion < 1001) XtSetArg ( wargs2[0], XmNshadowThickness, thick ); #else XtSetArg ( wargs2[0], XmNshadowThickness, 0 ); #endif XtSetValues ((Widget) new->slider.right_arrow, wargs2, 1 ); XtSetArg ( wargs2[0], XmNshadowThickness, thick ); XtSetValues ((Widget) new->slider.current_number, wargs2, 1 ); XtVaSetValues((Widget)new, XmNresizePolicy, XmRESIZE_NONE, NULL); /* * attach the arrows to the slider */ XtVaSetValues ((Widget)new->slider.left_arrow, XmNleftAttachment, XmATTACH_NONE, XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget, new->slider.bar, XmNrightOffset, 2, XmNtopAttachment, XmATTACH_NONE, XmNtopWidget, new->slider.bar, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, new->slider.bar, XmNtopOffset, 0, XmNbottomOffset, 1, NULL); XtVaSetValues ((Widget)new->slider.right_arrow, XmNrightAttachment, XmATTACH_NONE, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, new->slider.bar, XmNleftOffset, 2, XmNtopAttachment, XmATTACH_NONE, XmNtopWidget, new->slider.bar, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, new->slider.bar, XmNtopOffset, 0, XmNbottomOffset, 1, NULL); {Widget num = (Widget)new->slider.current_number; XtVaSetValues (num, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 50, XmNleftOffset, -(num->core.width>>1), XmNbottomAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_NONE, NULL);} } /* converts the integer from scale widget to the actucal number for the application */ static double widgetnumber2appl( XmSliderWidget slider, int widget_number ) { double res; res = slider->slider.wslope * ( ((widget_number - slider->slider.min_value) * slider->slider.application_max_value) + ((slider->slider.max_value - widget_number) * slider->slider.application_min_value) ); res = round(res, slider->slider.decimal_places); if(res < slider->slider.application_min_value) res = slider->slider.application_min_value; if(res > slider->slider.application_max_value) res = slider->slider.application_max_value; return ( res ); } static int appl2widgetnumber( XmSliderWidget slider, double application_number ) { double res; res = 0.5 + slider->slider.aslope * ( ((application_number - slider->slider.application_min_value) * slider->slider.max_value) + ((slider->slider.application_max_value - application_number) * slider->slider.min_value) ); return ( (int)(res) ); } static Boolean SetValues( XmSliderWidget current, XmSliderWidget request, XmSliderWidget new ) { Arg wargs[16]; int type, ival; double dval, max; XmSliderCallbackStruct callback_data; int n; Boolean center_number = False; if(new->slider.application_current_value != current->slider.application_current_value) { if (new->slider.application_current_value > new->slider.application_max_value) { n = 0; new->slider.application_current_value = new->slider.application_max_value; dval = new->slider.application_max_value; DoubleSetArg(wargs[n], XmNdValue, dval); n++; XtSetValues((Widget)new->slider.current_number, wargs, n); } else if (new->slider.application_current_value < new->slider.application_min_value) { n = 0; new->slider.application_current_value = new->slider.application_min_value; dval = new->slider.application_min_value; DoubleSetArg(wargs[n], XmNdValue, dval); n++; XtSetValues((Widget)new->slider.current_number, wargs, n); } else { DoubleSetArg(wargs[0],XmNdValue,new->slider.application_current_value); XtSetValues((Widget)new->slider.current_number, wargs, 1); } } if(new->slider.application_max_value != current->slider.application_max_value) { dval = new->slider.application_max_value; /* update the max for all the widget numbers */ DoubleSetArg(wargs[0], XmNdMaximum, dval ); XtSetValues((Widget)new->slider.current_number, wargs, 1); if (new->slider.application_current_value > new->slider.application_max_value) { n = 0; new->slider.application_current_value = new->slider.application_max_value; dval = new->slider.application_max_value; DoubleSetArg(wargs[n], XmNdValue, dval); n++; XtSetValues((Widget)new->slider.current_number, wargs, n); } center_number = True; } if(new->slider.application_min_value != current->slider.application_min_value) { dval = new->slider.application_min_value; DoubleSetArg(wargs[0], XmNdMinimum, dval ); XtSetValues((Widget)new->slider.current_number, wargs, 1); if (new->slider.application_current_value < new->slider.application_min_value) { n = 0; new->slider.application_current_value = new->slider.application_min_value; dval = new->slider.application_min_value; DoubleSetArg(wargs[n], XmNdValue, dval); n++; XtSetValues((Widget)new->slider.current_number, wargs, n); } center_number = True; } if ( new->slider.number_type != current->slider.number_type ) { XtSetArg(wargs[0], XmNdataType, new->slider.number_type); XtSetValues((Widget)new->slider.current_number, wargs, 1); center_number = True; } if ( new->slider.decimal_places != current->slider.decimal_places ) { XtSetArg(wargs[0], XmNdecimalPlaces, new->slider.decimal_places); XtSetValues((Widget)new->slider.current_number, wargs, 1 ); center_number = True; } /* Update the scale widget if min, max, current or inc vals have changed */ if( (new->slider.application_current_value != current->slider.application_current_value) || (new->slider.application_max_value != current->slider.application_max_value) || (new->slider.application_min_value != current->slider.application_min_value) || (new->slider.decimal_places != current->slider.decimal_places) || (new->slider.increment != current->slider.increment) ) { if (new->slider.increment==0) new->slider.max_value = new->slider.min_value; else { int places; places = new->slider.decimal_places; places = (places<2?2:places); places = (places>7?7:places); new->slider.max_value = pow((double)10, (double)places); } if (new->slider.application_max_value==new->slider.application_min_value) new->slider.aslope = 1.0 / zero; else new->slider.aslope = 1.0 / (new->slider.application_max_value - new->slider.application_min_value); if (new->slider.max_value==new->slider.min_value) new->slider.wslope = 1.0 / zero; else new->slider.wslope = 1.0 / (double)(new->slider.max_value - new->slider.min_value); new->slider.current_value = appl2widgetnumber(new, new->slider.application_current_value ); XtSetArg(wargs[0], XmNmaximum, new->slider.max_value); XtSetArg(wargs[1], XmNvalue, new->slider.current_value); XtSetValues((Widget)new->slider.bar, wargs, 2); } if(center_number) CenterNumber(new); XFlush(XtDisplay(new)); return TRUE; } static void Destroy( XmSliderWidget sw ) { XtRemoveAllCallbacks((Widget)sw, XmNvalueCallback); } static void Resize( XmSliderWidget sw ) { } static void CenterNumber(XmSliderWidget sw ) { } /* Subroutine: CreateSliderNumber * Purpose: Handle creation of number (digital readout) widget */ static XmNumberWidget CreateSliderNumber( int x, int min, double value, int max, char* title, Widget *label, XmSliderWidget slider, Boolean above, Boolean editable, Boolean make_stepper, Boolean label_is_widget ) { Arg wargs[30]; double dmin, dmax, dval; Widget number; XmString text; int len; int size; int n; /* * Create the panel-meter like number display */ /* The stepper's values are absolute */ dmin = slider->slider.application_min_value; dmax = slider->slider.application_max_value; dval = value; n = 0; /* Estimate a comfortably large size to initially create NumberWidget */ XtSetArg(wargs[n], XmNheight, 19); n++; DoubleSetArg(wargs[n], XmNdMinimum, dmin); n++; DoubleSetArg(wargs[n], XmNdMaximum, dmax); n++; DoubleSetArg(wargs[n], XmNdValue, dval); n++; XtSetArg(wargs[n], XmNdecimalPlaces, slider->slider.decimal_places ); n++; /* Center text in the field and resize for tighter fit of font */ XtSetArg(wargs[n], XmNcenter, TRUE); n++; XtSetArg(wargs[n], XmNrecomputeSize, True); n++; if( editable ) { XtSetArg(wargs[n], XmNeditable, TRUE); n++; } else { XtSetArg(wargs[n], XmNeditable, FALSE); n++; } XtSetArg(wargs[n], XmNdataType, DOUBLE); n++; XtSetArg(wargs[n], XmNcharPlaces, 15); n++; XtSetArg(wargs[n], XmNshadowThickness, slider->manager.shadow_thickness); n++; XtSetArg(wargs[n], XmNfixedNotation, False); n++; number = XmCreateNumber((Widget)slider, title, wargs, n); /* Callback for when a new value is entered directly */ XtAddCallback(number, XmNactivateCallback, (XtCallbackProc)CallbackFromNumber, slider); XtManageChild(number); XtSetArg(wargs[0], XmNleftAttachment, XmATTACH_POSITION); XtSetArg(wargs[1], XmNrightAttachment, XmATTACH_NONE); XtSetArg(wargs[2], XmNleftPosition, x); if( above ) { XtSetArg(wargs[3], XmNtopAttachment, XmATTACH_NONE); XtSetArg(wargs[4], XmNbottomAttachment, XmATTACH_WIDGET); XtSetArg(wargs[5], XmNbottomWidget, number); } else { XtSetArg(wargs[3], XmNtopAttachment, XmATTACH_WIDGET); XtSetArg(wargs[4], XmNbottomAttachment, XmATTACH_NONE); XtSetArg(wargs[5], XmNtopWidget, number); } /* Create the string for the label, and then the label */ text = XmStringCreate(title, XmSTRING_DEFAULT_CHARSET); XtSetArg(wargs[6], XmNlabelString, text); *label = XmCreateLabel((Widget)slider, "label", wargs, 7); XmStringFree(text); slider->slider.current_number = (XmNumberWidget)number; CenterNumber (slider); return (XmNumberWidget)number; } static void CallbackFromScale ( XmScaleWidget scale, XmSliderWidget slider, XmScaleCallbackStruct *call_data ) { Arg wargs[10]; double dval; XmSliderCallbackStruct callback_data; if ( (call_data->reason != XmCR_DRAG) && (call_data->reason != XmCR_VALUE_CHANGED) ) return; slider->slider.current_value = call_data->value; dval = widgetnumber2appl(slider, call_data->value); slider->slider.application_current_value = dval; slider->slider.current_value = appl2widgetnumber(slider, slider->slider.application_current_value ); DoubleSetArg( wargs[0], XmNdValue, dval ); XtSetValues((Widget)slider->slider.current_number, wargs, 1); callback_data.reason = call_data->reason; callback_data.value = dval; XtCallCallbacks((Widget)slider, XmNvalueCallback, &callback_data); } static void CallbackFromScale2 ( XmScaleWidget scale, XmSliderWidget slider, XmScaleCallbackStruct *call_data ) { Arg wargs[10]; double dval; XmSliderCallbackStruct callback_data; if ( call_data->reason != XmCR_VALUE_CHANGED ) return; slider->slider.current_value = call_data->value; dval = widgetnumber2appl(slider, call_data->value); DoubleSetArg( wargs[0], XmNcurrent, dval ); XtSetValues((Widget) slider, wargs, 1 ); DoubleSetArg(wargs[0], XmNdValue, dval ); XtSetValues((Widget)slider->slider.current_number, wargs, 1); callback_data.reason = call_data->reason; callback_data.value = dval; XtCallCallbacks((Widget)slider, XmNvalueCallback, &callback_data); } static double gridify (double dval, double inc) { Boolean posval; double ddv, diff, newval; int dv; if (dval >= 0.0) posval = True; else posval = False; ddv = dval / inc; dv = (int)ddv; diff = ddv - dv; if (diff >= 0.5 ) dv++; newval = inc * dv; if ((posval) && (newval < 0.0)) newval = -newval; return newval; } static void CallbackFromArrow ( XmArrowButtonWidget arrow, XmSliderWidget slider, XmAnyCallbackStruct *call_data ) { short inc; int value, which, n = 0, ival ; XmSliderCallbackStruct callback_data; Arg wargs[10]; double dval, old_value; if ( call_data->reason != XmCR_ACTIVATE ) return; old_value = slider->slider.application_current_value; if( arrow == slider->slider.left_arrow ) { dval = slider->slider.application_current_value - slider->slider.increment; dval = round(dval, slider->slider.decimal_places); if (slider->slider.increment != 0.0) dval = gridify (dval, slider->slider.increment); DoubleSetArg ( wargs[0], XmNcurrent, dval ); XtSetValues ((Widget) slider, wargs, 1 ); callback_data.reason = call_data->reason; callback_data.value = slider->slider.application_current_value; if (callback_data.value != old_value) XtCallCallbacks((Widget)slider, XmNvalueCallback, &callback_data); } if( arrow == slider->slider.right_arrow ) { dval = slider->slider.application_current_value + slider->slider.increment; dval = round(dval, slider->slider.decimal_places); if (slider->slider.increment != 0.0) dval = gridify (dval, slider->slider.increment); DoubleSetArg ( wargs[0], XmNcurrent, dval ); XtSetValues ((Widget) slider, wargs, 1 ); callback_data.reason = call_data->reason; callback_data.value = slider->slider.application_current_value; if (callback_data.value != old_value) XtCallCallbacks((Widget)slider, XmNvalueCallback, &callback_data); } } /* Subroutine: CallbackFromNumber * Purpose: Callback routine from number widget to allow/disallow stepper * to manipulate the value, or to set a new value. */ static void CallbackFromNumber( XmNumberWidget nw, XmSliderWidget slider, XmDoubleCallbackStruct* call_data ) { int value, which; XmSliderCallbackStruct callback_data; Arg wargs[10]; double dval; if( call_data->reason == XmCR_ACTIVATE ) { if( nw == slider->slider.current_number ) { slider->slider.current_value = call_data->value; DoubleSetArg(wargs[0], XmNcurrent, call_data->value ); XtSetValues((Widget)slider, wargs, 1 ); callback_data.reason = call_data->reason; callback_data.value = call_data->value; XtCallCallbacks((Widget)slider, XmNvalueCallback, &callback_data); } } } /* Subroutine: XmCreateSlider * Purpose: This function creates and returns a Slider widget. */ Widget XmCreateSlider( Widget parent, char *name, ArgList args, Cardinal num_args) { return (XtCreateWidget(name, xmSliderWidgetClass, parent, args, num_args)); } static double round(double a, int decimal_places) { double value; double expon; double remember; remember = a; /* * Round the value */ expon = pow((double)10, (double)decimal_places); a = a * expon; if (a < 0) { a = a - 0.5; } else { a = a + 0.5; } if (fabs(a) < INT_MAX) { value = trunc(a); return (value / expon); } else { return (remember); } } /* * Add a warning callback to the number widget within the slider */ void XmSliderAddWarningCallback(Widget w, XtCallbackProc proc, XtPointer clientData) { XmSliderWidget sw = (XmSliderWidget)w; XtAddCallback((Widget)sw->slider.current_number, XmNwarningCallback, proc, clientData); }