1 /**************************************************************************\
2  *
3  *  This file is part of the Coin 3D visualization library.
4  *  Copyright (C) by Kongsberg Oil & Gas Technologies.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU General Public License
8  *  ("GPL") version 2 as published by the Free Software Foundation.
9  *  See the file LICENSE.GPL at the root directory of this source
10  *  distribution for additional information about the GNU GPL.
11  *
12  *  For using Coin with software that can not be combined with the GNU
13  *  GPL, and for taking advantage of the additional benefits of our
14  *  support services, please contact Kongsberg Oil & Gas Technologies
15  *  about acquiring a Coin Professional Edition License.
16  *
17  *  See http://www.coin3d.org/ for more information.
18  *
19  *  Kongsberg Oil & Gas Technologies, Bygdoy Alle 5, 0257 Oslo, NORWAY.
20  *  http://www.sim.no/  sales@sim.no  coin-support@coin3d.org
21  *
22 \**************************************************************************/
23 
24 #include <assert.h>
25 #include <stdlib.h>
26 
27 #include <X11/Intrinsic.h>
28 #include <Xm/Xm.h>
29 #include <Xm/Form.h>
30 #include <Xm/Label.h>
31 #include <Xm/Scale.h>
32 #include <Xm/Text.h>
33 #include <Xm/PushB.h>
34 
35 #include <Inventor/errors/SoDebugError.h>
36 #include <Inventor/SbPList.h>
37 
38 #include <soxtdefs.h>
39 #include <Inventor/Xt/SoXtBasic.h>
40 
41 #include <Inventor/Xt/widgets/SoXtSlider.h>
42 
43 /*!
44   \class SoXtSlider Inventor/Xt/widgets/compound/SoXtSlider.h
45   \brief The SoXtSlider class manages a compound widget containing a
46   generic slider.
47 
48   This class is internal to SoXt and may change interface without notice.
49 */
50 
51 // *************************************************************************
52 
53 /*!
54 */
55 
SoXtSlider(const char * const thetitle)56 SoXtSlider::SoXtSlider(
57   const char * const thetitle)
58 {
59   this->s_form = NULL;
60   this->s_value = NULL;
61   this->s_slider = NULL;
62 
63   this->r_form = NULL;
64   this->r_value = NULL;
65   this->r_slider = NULL;
66   this->r_minValue = NULL;
67   this->r_maxValue = NULL;
68 
69   this->f_form = NULL;
70   this->f_value = NULL;
71   this->f_slider = NULL;
72   this->f_min = NULL;
73   this->f_minValue = NULL;
74   this->f_max = NULL;
75   this->f_maxValue = NULL;
76   this->f_label = NULL;
77 
78   this->o_form = NULL;
79   this->o_value = NULL;
80   this->o_slider = NULL;
81   this->o_label = NULL;
82 
83   if ( thetitle ) {
84     this->title = new char [strlen(thetitle)+1];
85     assert(this->title);
86     strcpy(this->title, thetitle);
87   } else {
88     this->title = NULL;
89   }
90   this->callbacks = NULL;
91 
92   this->current = 0.0f;
93   this->minimum = 0.0f;
94   this->maximum = 1.0f;
95 } // SoXtSlider()
96 
97 /*!
98 */
99 
~SoXtSlider(void)100 SoXtSlider::~SoXtSlider(
101   void)
102 {
103   delete [] this->title;
104 } // ~SoXtSlider()
105 
106 // *************************************************************************
107 
108 /*!
109 */
110 
111 void
setValue(float value)112 SoXtSlider::setValue(
113   float value)
114 {
115   this->current = value;
116   // FIXME: update widgets
117 } // setValue()
118 
119 /*!
120 */
121 
122 float
getValue(void) const123 SoXtSlider::getValue(
124   void) const
125 {
126   return this->current;
127 } // getValue()
128 
129 // *************************************************************************
130 
131 /*!
132 */
133 
134 void
setRange(float min,float max)135 SoXtSlider::setRange(
136   float min,
137   float max)
138 {
139   this->minimum = min;
140   this->maximum = max;
141 } // setRange()
142 
143 /*!
144 */
145 
146 void
getRange(float & min,float & max) const147 SoXtSlider::getRange(
148   float & min,
149   float & max) const
150 {
151   min = this->minimum;
152   max = this->maximum;
153 } // getRange()
154 
155 // *************************************************************************
156 
157 struct SoXtSliderCallbackInfo {
158   SoXtSliderCB * callback;
159   void * closure;
160 };
161 
162 /*!
163 */
164 
165 void
addCallback(SoXtSliderCB * callback,void * closure)166 SoXtSlider::addCallback(
167   SoXtSliderCB * callback,
168   void * closure)
169 {
170   if (this->callbacks == NULL)
171     this->callbacks = new SbPList;
172   SoXtSliderCallbackInfo * info = new SoXtSliderCallbackInfo;
173   info->callback = callback;
174   info->closure = closure;
175   this->callbacks->append(info);
176 } // addCallback()
177 
178 /*!
179 */
180 
181 void
removeCallback(SoXtSliderCB * callback,void * closure)182 SoXtSlider::removeCallback(
183   SoXtSliderCB * callback,
184   void * closure)
185 {
186   if (this->callbacks == NULL) {
187 #if SOXT_DEBUG
188     SoDebugError::postInfo("SoXtSlider::removeCallback",
189       "no callbacks");
190 #endif // SOXT_DEBUG
191     return;
192   }
193   const int num = this->callbacks->getLength();
194   for (int i = 0; i < num; i++) {
195     SoXtSliderCallbackInfo * info =
196       (SoXtSliderCallbackInfo *) (*this->callbacks)[i];
197     if (info->callback == callback && info->closure == closure) {
198       this->callbacks->remove(i);
199       return;
200     }
201   }
202 #if SOXT_DEBUG
203   SoDebugError::postInfo("SoXtSlider::removeCallback",
204     "no such callback");
205 #endif // SOXT_DEBUG
206 } // removeCallback()
207 
208 /*!
209 */
210 
211 void
invokeCallbacks(void)212 SoXtSlider::invokeCallbacks(
213   void)
214 {
215   if (this->callbacks != NULL) {
216     const int num = this->callbacks->getLength();
217     for (int i = 0; i < num; i++) {
218       SoXtSliderCallbackInfo * info =
219         (SoXtSliderCallbackInfo *) (*this->callbacks)[i];
220       info->callback(info->closure, this->title, this->current);
221     }
222   }
223 } // invokeCallbacks()
224 
225 // *************************************************************************
226 
227 /*!
228 */
229 
230 Widget
buildSimpleWidget(const Widget parent)231 SoXtSlider::buildSimpleWidget(// protected
232   const Widget parent)
233 {
234   if (this->s_form == (Widget) NULL) {
235     this->s_form = XtVaCreateManagedWidget("simple",
236       xmFormWidgetClass, parent,
237       NULL);
238 
239     this->s_value = XtVaCreateManagedWidget("value",
240       xmTextWidgetClass, this->s_form,
241       XmNleftAttachment, XmATTACH_FORM,
242       XmNtopAttachment, XmATTACH_FORM,
243       XmNrightAttachment, XmATTACH_NONE,
244       XmNbottomAttachment, XmATTACH_NONE,
245       XmNwidth, 60,
246       XmNhighlightThickness, 0,
247       NULL);
248 
249     char text[16];
250     sprintf(text, "%g", this->current);
251     XmTextSetString(this->s_value, text);
252     XmTextSetCursorPosition(this->s_value, strlen(text));
253 
254     XtAddCallback(this->s_value, XmNactivateCallback,
255       SoXtSlider::value_cb, (XtPointer) this);
256     XtAddCallback(this->s_value, XmNlosingFocusCallback,
257       SoXtSlider::value_cb, (XtPointer) this);
258 
259     this->s_slider = XtVaCreateManagedWidget("slider",
260       xmScaleWidgetClass, this->s_form,
261       XmNleftAttachment, XmATTACH_WIDGET,
262       XmNleftWidget, this->s_value,
263       XmNleftOffset, 2,
264       XmNtopAttachment, XmATTACH_FORM,
265       XmNtopOffset, 2,
266       XmNrightAttachment, XmATTACH_FORM,
267       XmNrightOffset, 2,
268       XmNbottomAttachment, XmATTACH_FORM,
269       XmNbottomOffset, 2,
270       XmNorientation, XmHORIZONTAL,
271       XmNtraversalOn, False,
272       XmNminimum, 0,
273       XmNvalue, 0,
274       XmNmaximum, 999,
275       XmNshowValue, False,
276       XmNhighlightThickness, 0,
277       XtVaTypedArg,
278         XmNtitleString, XmRString,
279         "", 0,
280       NULL);
281 
282     XtAddCallback(this->s_slider, XmNdragCallback,
283       SoXtSlider::slider_cb, (XtPointer) this);
284     XtAddCallback(this->s_slider, XmNvalueChangedCallback,
285       SoXtSlider::slider_cb, (XtPointer) this);
286   }
287   return this->s_form;
288 } // buildSimpleWidget()
289 
290 /*!
291 */
292 
293 Widget
buildRangedWidget(const Widget parent)294 SoXtSlider::buildRangedWidget(
295   const Widget parent)
296 {
297   if (this->r_form == (Widget) NULL) {
298     this->r_form = XtVaCreateManagedWidget("ranged",
299       xmFormWidgetClass, parent,
300       NULL);
301 
302     this->r_slider = XtVaCreateManagedWidget("slider",
303       xmScaleWidgetClass, this->r_form,
304       XmNorientation, XmHORIZONTAL,
305       XmNtraversalOn, False,
306       XmNminimum, 0,
307       XmNvalue, 0,
308       XmNmaximum, 999,
309       XmNshowValue, False,
310       XmNhighlightThickness, 0,
311       XtVaTypedArg,
312         XmNtitleString, XmRString, "", 0,
313       NULL);
314 
315     XtAddCallback(this->r_slider, XmNdragCallback,
316       SoXtSlider::slider_cb, (XtPointer) this);
317     XtAddCallback(this->r_slider, XmNvalueChangedCallback,
318       SoXtSlider::slider_cb, (XtPointer) this);
319 
320     this->r_value = XtVaCreateManagedWidget("value",
321       xmTextWidgetClass, this->r_form,
322       XmNhighlightThickness, 0,
323       NULL);
324 
325     char text[16];
326     sprintf(text, "%g", this->current);
327     XmTextSetString(this->r_value, text);
328     XmTextSetCursorPosition(this->r_value, strlen(text));
329 
330     XtAddCallback(this->r_value, XmNactivateCallback,
331       SoXtSlider::value_cb, (XtPointer) this);
332     XtAddCallback(this->r_value, XmNlosingFocusCallback,
333       SoXtSlider::value_cb, (XtPointer) this);
334 
335     this->r_minValue = XtVaCreateManagedWidget("minValue",
336       xmTextWidgetClass, this->r_form,
337       XmNhighlightThickness, 0,
338       NULL);
339 
340     sprintf(text, "%g", this->minimum);
341     XmTextSetString(this->r_minValue, text);
342     XmTextSetCursorPosition(this->r_minValue, strlen(text));
343 
344     XtAddCallback(this->r_minValue, XmNactivateCallback,
345       SoXtSlider::min_value_cb, (XtPointer) this);
346     XtAddCallback(this->r_minValue, XmNlosingFocusCallback,
347       SoXtSlider::min_value_cb, (XtPointer) this);
348 
349     this->r_maxValue = XtVaCreateManagedWidget("maxValue",
350       xmTextWidgetClass, this->r_form,
351       XmNhighlightThickness, 0,
352       NULL);
353 
354     sprintf(text, "%g", this->maximum);
355     XmTextSetString(this->r_maxValue, text);
356     XmTextSetCursorPosition(this->r_maxValue, strlen(text));
357 
358     XtAddCallback(this->r_maxValue, XmNactivateCallback,
359       SoXtSlider::max_value_cb, (XtPointer) this);
360     XtAddCallback(this->r_maxValue, XmNlosingFocusCallback,
361       SoXtSlider::max_value_cb, (XtPointer) this);
362 
363   XtVaSetValues(this->r_value,
364     XmNleftAttachment, XmATTACH_FORM,
365     XmNtopAttachment, XmATTACH_FORM,
366     XmNrightAttachment, XmATTACH_NONE,
367     XmNbottomAttachment, XmATTACH_NONE,
368     XmNwidth, 60,
369     NULL);
370 
371   XtVaSetValues(this->r_minValue,
372     XmNleftAttachment, XmATTACH_WIDGET,
373     XmNleftWidget, this->r_value,
374     XmNtopAttachment, XmATTACH_FORM,
375     XmNrightAttachment, XmATTACH_NONE,
376     XmNbottomAttachment, XmATTACH_NONE,
377     XmNwidth, 50,
378     NULL);
379 
380   XtVaSetValues(this->r_maxValue,
381     XmNleftAttachment, XmATTACH_NONE,
382     XmNtopAttachment, XmATTACH_FORM,
383     XmNrightAttachment, XmATTACH_FORM,
384     XmNbottomAttachment, XmATTACH_NONE,
385     XmNwidth, 50,
386     NULL);
387 
388   XtVaSetValues(this->r_slider,
389     XmNleftAttachment, XmATTACH_WIDGET,
390     XmNleftWidget, this->r_minValue,
391     XmNleftOffset, 2,
392     XmNtopAttachment, XmATTACH_FORM,
393     XmNtopOffset, 2,
394     XmNrightAttachment, XmATTACH_WIDGET,
395     XmNrightWidget, this->r_maxValue,
396     XmNrightOffset, 2,
397     XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
398     XmNbottomWidget, this->r_minValue,
399     XmNbottomOffset, 2,
400     XtVaTypedArg,
401       XmNtitleString, XmRString,
402       "", 0,
403     NULL);
404   }
405   return this->r_form;
406 } // buildRangedWidget()
407 
408 /*!
409 */
410 
411 Widget
buildFullWidget(const Widget parent)412 SoXtSlider::buildFullWidget(
413   const Widget parent)
414 {
415   if (this->f_form == (Widget) NULL) {
416     char text[16];
417 
418     this->f_form = XtVaCreateManagedWidget("slider",
419       xmFormWidgetClass, parent,
420       NULL);
421 
422     this->f_minValue = XtVaCreateManagedWidget("minValue",
423       xmTextWidgetClass, this->f_form,
424       XmNleftAttachment, XmATTACH_FORM,
425       XmNtopAttachment, XmATTACH_FORM,
426       XmNrightAttachment, XmATTACH_NONE,
427       XmNbottomAttachment, XmATTACH_NONE,
428       XmNwidth, 50,
429       XmNhighlightThickness, 0,
430       NULL);
431 
432     sprintf(text, "%g", this->minimum);
433     XmTextSetString(this->f_minValue, text);
434     XmTextSetCursorPosition(this->f_minValue, strlen(text));
435 
436     XtAddCallback(this->f_minValue, XmNactivateCallback,
437       SoXtSlider::min_value_cb, (XtPointer) this);
438     XtAddCallback(this->f_minValue, XmNlosingFocusCallback,
439       SoXtSlider::min_value_cb, (XtPointer) this);
440 
441     this->f_maxValue = XtVaCreateManagedWidget("maxValue",
442       xmTextWidgetClass, this->f_form,
443       XmNleftAttachment, XmATTACH_NONE,
444       XmNtopAttachment, XmATTACH_FORM,
445       XmNrightAttachment, XmATTACH_FORM,
446       XmNbottomAttachment, XmATTACH_NONE,
447       XmNwidth, 50,
448       XmNhighlightThickness, 0,
449       NULL);
450 
451     sprintf(text, "%g", this->maximum);
452     XmTextSetString(this->f_maxValue, text);
453     XmTextSetCursorPosition(this->f_maxValue, strlen(text));
454 
455     XtAddCallback(this->f_maxValue, XmNactivateCallback,
456       SoXtSlider::max_value_cb, (XtPointer) this);
457     XtAddCallback(this->f_maxValue, XmNlosingFocusCallback,
458       SoXtSlider::max_value_cb, (XtPointer) this);
459 
460     this->f_value = XtVaCreateManagedWidget("value",
461       xmTextWidgetClass, this->f_form,
462       XmNleftAttachment, XmATTACH_WIDGET,
463       XmNleftWidget, this->f_minValue,
464       XmNleftOffset, 2,
465       XmNtopAttachment, XmATTACH_FORM,
466       XmNrightAttachment, XmATTACH_WIDGET,
467       XmNrightWidget, this->f_maxValue,
468       XmNrightOffset, 2,
469       XmNhighlightThickness, 0,
470       NULL);
471 
472     sprintf(text, "%g", this->current);
473     XmTextSetString(this->f_value, text);
474     XmTextSetCursorPosition(this->f_value, strlen(text));
475 
476     XtAddCallback(this->f_value, XmNactivateCallback,
477       SoXtSlider::value_cb, (XtPointer) this);
478     XtAddCallback(this->f_value, XmNlosingFocusCallback,
479       SoXtSlider::value_cb, (XtPointer) this);
480 
481     this->f_min = XtVaCreateManagedWidget("min",
482       xmPushButtonWidgetClass, this->f_form,
483       XmNleftAttachment, XmATTACH_FORM,
484       XmNtopAttachment, XmATTACH_WIDGET,
485       XmNtopWidget, this->f_minValue,
486       XmNtopOffset, 2,
487       XmNbottomOffset, 2,
488       XmNwidth, 50,
489       XmNtraversalOn, False,
490       NULL);
491 
492     XtAddCallback(this->f_min, XmNactivateCallback,
493       SoXtSlider::min_cb, (XtPointer) this);
494 
495     this->f_max = XtVaCreateManagedWidget("max",
496       xmPushButtonWidgetClass, this->f_form,
497       XmNtopAttachment, XmATTACH_WIDGET,
498       XmNtopWidget, this->f_maxValue,
499       XmNtopOffset, 2,
500       XmNrightAttachment, XmATTACH_FORM,
501       XmNbottomOffset, 2,
502       XmNwidth, 50,
503       XmNtraversalOn, False,
504       NULL);
505 
506     XtAddCallback(this->f_max, XmNactivateCallback,
507       SoXtSlider::max_cb, (XtPointer) this);
508 
509     this->f_slider = XtVaCreateManagedWidget("slider",
510       xmScaleWidgetClass, this->f_form,
511       XmNleftAttachment, XmATTACH_WIDGET,
512       XmNleftWidget, this->f_minValue,
513       XmNleftOffset, 2,
514       XmNtopAttachment, XmATTACH_WIDGET,
515       XmNtopWidget, this->f_value,
516       XmNtopOffset, 2,
517       XmNrightAttachment, XmATTACH_WIDGET,
518       XmNrightWidget, this->f_maxValue,
519       XmNrightOffset, 2,
520       XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET,
521       XmNbottomWidget, this->f_min,
522       XmNbottomOffset, 2,
523       XmNorientation, XmHORIZONTAL,
524       XmNtraversalOn, False,
525       XmNminimum, 0,
526       XmNvalue, 0,
527       XmNmaximum, 999,
528       XmNshowValue, False,
529       XmNhighlightThickness, 0,
530       NULL);
531 
532     XtAddCallback(this->f_slider, XmNdragCallback,
533       SoXtSlider::slider_cb, (XtPointer) this);
534     XtAddCallback(this->f_slider, XmNvalueChangedCallback,
535       SoXtSlider::slider_cb, (XtPointer) this);
536 
537     this->f_label = XtVaCreateManagedWidget("label",
538       xmLabelWidgetClass, this->f_form,
539       XmNleftAttachment, XmATTACH_WIDGET,
540       XmNleftWidget, this->f_min,
541       XmNtopAttachment, XmATTACH_WIDGET,
542       XmNtopWidget, this->f_slider,
543       XmNrightAttachment, XmATTACH_WIDGET,
544       XmNrightWidget, this->f_max,
545       XmNalignment, XmALIGNMENT_BEGINNING,
546       XtVaTypedArg,
547         XmNlabelString, XmRString,
548         this->title, strlen(this->title)+1,
549       NULL);
550 
551   }
552   return this->f_form;
553 } // buildFullWidget()
554 
555 /*!
556 */
557 
558 Widget
buildOrderlyWidget(const Widget parent)559 SoXtSlider::buildOrderlyWidget(
560   const Widget parent)
561 {
562   if (this->o_form == (Widget) NULL) {
563     this->o_form = XtVaCreateManagedWidget("orderly",
564       xmFormWidgetClass, parent,
565       NULL);
566 
567     this->o_value = XtVaCreateManagedWidget("value",
568       xmTextWidgetClass, this->o_form,
569       XmNleftAttachment, XmATTACH_FORM,
570       XmNtopAttachment, XmATTACH_FORM,
571       XmNrightAttachment, XmATTACH_FORM,
572       XmNhighlightThickness, 0,
573       NULL);
574 
575     char text[16];
576     sprintf(text, "%g", this->current);
577     XmTextSetString(this->o_value, text);
578     XmTextSetCursorPosition(this->o_value, strlen(text));
579 
580     XtAddCallback(this->o_value, XmNactivateCallback,
581       SoXtSlider::value_cb, (XtPointer) this);
582     XtAddCallback(this->o_value, XmNlosingFocusCallback,
583       SoXtSlider::value_cb, (XtPointer) this);
584 
585     this->o_slider = XtVaCreateManagedWidget("slider",
586       xmScaleWidgetClass, this->o_form,
587       XmNleftAttachment, XmATTACH_FORM,
588       XmNtopAttachment, XmATTACH_WIDGET,
589       XmNtopWidget, this->o_value,
590       XmNtopOffset, 2,
591       XmNrightAttachment, XmATTACH_FORM,
592       XmNorientation, XmHORIZONTAL,
593       XmNtraversalOn, False,
594       XmNminimum, 0,
595       XmNvalue, 0,
596       XmNmaximum, 999,
597       XmNshowValue, False,
598       XmNhighlightThickness, 0,
599       NULL);
600 
601     XtAddCallback(this->o_slider, XmNdragCallback,
602       SoXtSlider::slider_cb, (XtPointer) this);
603     XtAddCallback(this->o_slider, XmNvalueChangedCallback,
604       SoXtSlider::slider_cb, (XtPointer) this);
605 
606     this->o_label = XtVaCreateManagedWidget("label",
607       xmLabelWidgetClass, this->o_form,
608       XmNleftAttachment, XmATTACH_FORM,
609       XmNtopAttachment, XmATTACH_WIDGET,
610       XmNtopWidget, this->o_slider,
611       XmNrightAttachment, XmATTACH_FORM,
612       XmNbottomAttachment, XmATTACH_FORM,
613       XtVaTypedArg,
614         XmNlabelString, XmRString,
615         this->title, strlen(this->title)+1,
616       XmNalignment, XmALIGNMENT_BEGINNING,
617       NULL);
618   }
619   return this->o_form;
620 } // buildOrderlyWidget()
621 
622 // *************************************************************************
623 
624 /*!
625 */
626 
627 void
slider_cb(Widget widget,XtPointer closure,XtPointer call_data)628 SoXtSlider::slider_cb(
629   Widget widget,
630   XtPointer closure,
631   XtPointer call_data)
632 {
633   assert(closure != NULL);
634   SoXtSlider * slider = (SoXtSlider *) closure;
635   XmScaleCallbackStruct * data = (XmScaleCallbackStruct *) call_data;
636   float previous = slider->current;
637   slider->current = slider->minimum +
638     (slider->maximum - slider->minimum) / 999 * (float) data->value;
639   slider->current = SoXtMax(slider->current, slider->minimum);
640   slider->current = SoXtMin(slider->current, slider->maximum);
641   char text[16];
642 
643   sprintf(text, "%.2g", slider->current);
644   const int pos = strlen(text);
645   XmTextSetString(slider->s_value, text);
646   XmTextSetString(slider->r_value, text);
647   XmTextSetString(slider->f_value, text);
648   XmTextSetString(slider->o_value, text);
649   XmTextSetCursorPosition(slider->s_value, pos);
650   XmTextSetCursorPosition(slider->r_value, pos);
651   XmTextSetCursorPosition(slider->f_value, pos);
652   XmTextSetCursorPosition(slider->o_value, pos);
653   XmScaleSetValue(slider->s_slider, data->value);
654   XmScaleSetValue(slider->r_slider, data->value);
655   XmScaleSetValue(slider->f_slider, data->value);
656   XmScaleSetValue(slider->o_slider, data->value);
657 
658   if (previous != slider->current)
659     slider->invokeCallbacks();
660 } // slider_cb()
661 
662 /*!
663 */
664 
665 void
value_cb(Widget widget,XtPointer closure,XtPointer call_data)666 SoXtSlider::value_cb(
667   Widget widget,
668   XtPointer closure,
669   XtPointer call_data)
670 {
671   assert(closure != NULL);
672   SoXtSlider * slider = (SoXtSlider *) closure;
673 
674   float previous = slider->current;
675   slider->current = atof(XmTextGetString(widget));
676   slider->current = SoXtMax(slider->current, slider->minimum);
677   slider->current = SoXtMin(slider->current, slider->maximum);
678 
679   char text[16];
680   sprintf(text, "%.2g", slider->current);
681   const int cpos = strlen(text);
682   const int pos = (int) ((slider->current - slider->minimum) /
683     (slider->maximum - slider->minimum) * 999.0f);
684 
685   XmTextSetString(slider->s_value, text);
686   XmTextSetString(slider->r_value, text);
687   XmTextSetString(slider->f_value, text);
688   XmTextSetString(slider->o_value, text);
689   XmTextSetCursorPosition(slider->s_value, cpos);
690   XmTextSetCursorPosition(slider->r_value, cpos);
691   XmTextSetCursorPosition(slider->f_value, cpos);
692   XmTextSetCursorPosition(slider->o_value, cpos);
693   XmScaleSetValue(slider->s_slider, pos);
694   XmScaleSetValue(slider->r_slider, pos);
695   XmScaleSetValue(slider->f_slider, pos);
696   XmScaleSetValue(slider->o_slider, pos);
697 
698   if (previous != slider->current)
699     slider->invokeCallbacks();
700 } // value_cb()
701 
702 /*!
703 */
704 
705 void
min_cb(Widget widget,XtPointer closure,XtPointer call_data)706 SoXtSlider::min_cb(
707   Widget widget,
708   XtPointer closure,
709   XtPointer call_data)
710 {
711   assert(closure != NULL);
712   SoXtSlider * slider = (SoXtSlider *) closure;
713   slider->minimum = slider->current;
714   char text[16];
715   sprintf(text, "%.2g", slider->minimum);
716   const int cpos = strlen(text);
717 
718   XmTextSetString(slider->r_minValue, text);
719   XmTextSetString(slider->f_minValue, text);
720   XmTextSetCursorPosition(slider->r_minValue, cpos);
721   XmTextSetCursorPosition(slider->f_minValue, cpos);
722   XmScaleSetValue(slider->r_slider, 0);
723   XmScaleSetValue(slider->f_slider, 0);
724 } // min_cb()
725 
726 /*!
727 */
728 
729 void
min_value_cb(Widget widget,XtPointer closure,XtPointer call_data)730 SoXtSlider::min_value_cb(
731   Widget widget,
732   XtPointer closure,
733   XtPointer call_data)
734 {
735   assert(closure != NULL);
736   SoXtSlider * slider = (SoXtSlider *) closure;
737   float previous = slider->current;
738   float prevmax = slider->maximum;
739   slider->minimum = atof(XmTextGetString(widget));
740   slider->maximum = SoXtMax(slider->maximum, slider->minimum);
741   slider->current = SoXtMax(slider->current, slider->minimum);
742 
743 #if SOXT_DEBUG && 0
744   SoDebugError::postInfo("SoXtSlider::min_value_cb", "[invoked]");
745 #endif // SOXT_DEBUG
746 
747   char text[16];
748   sprintf(text, "%.2g", slider->minimum);
749   int cpos = strlen(text);
750   int pos = 0;
751   if (slider->minimum != slider->maximum)
752     pos = (int) ((slider->current - slider->minimum) /
753       (slider->maximum - slider->minimum) * 999.0f);
754 
755   XmTextSetString(slider->r_minValue, text);
756   XmTextSetString(slider->f_minValue, text);
757   XmTextSetCursorPosition(slider->r_minValue, cpos);
758   XmTextSetCursorPosition(slider->f_minValue, cpos);
759 
760   if (prevmax != slider->maximum) {
761     sprintf(text, "%.2g", slider->maximum);
762     cpos = strlen(text);
763     XmTextSetString(slider->r_maxValue, text);
764     XmTextSetString(slider->f_maxValue, text);
765     XmTextSetCursorPosition(slider->r_maxValue, cpos);
766     XmTextSetCursorPosition(slider->f_maxValue, cpos);
767   }
768 
769   XmScaleSetValue(slider->s_slider, pos);
770   XmScaleSetValue(slider->r_slider, pos);
771   XmScaleSetValue(slider->f_slider, pos);
772   XmScaleSetValue(slider->o_slider, pos);
773 
774   if (previous != slider->current) {
775     sprintf(text, "%.2g", slider->current);
776     cpos = strlen(text);
777     XmTextSetString(slider->s_value, text);
778     XmTextSetString(slider->r_value, text);
779     XmTextSetString(slider->f_value, text);
780     XmTextSetString(slider->o_value, text);
781     XmTextSetCursorPosition(slider->s_value, cpos);
782     XmTextSetCursorPosition(slider->r_value, cpos);
783     XmTextSetCursorPosition(slider->f_value, cpos);
784     XmTextSetCursorPosition(slider->o_value, cpos);
785   }
786   if (previous != slider->current)
787     slider->invokeCallbacks();
788 } // min_value_cb()
789 
790 /*!
791 */
792 
793 void
max_cb(Widget widget,XtPointer closure,XtPointer call_data)794 SoXtSlider::max_cb(
795   Widget widget,
796   XtPointer closure,
797   XtPointer call_data)
798 {
799   assert(closure != NULL);
800   SoXtSlider * slider = (SoXtSlider *) closure;
801   slider->maximum = slider->current;
802   char text[16];
803   sprintf(text, "%.2g", slider->maximum);
804   const int cpos = strlen(text);
805   int pos = 999;
806   if (slider->minimum == slider->maximum)
807     pos = 0;
808 
809   XmTextSetString(slider->r_maxValue, text);
810   XmTextSetString(slider->f_maxValue, text);
811   XmTextSetCursorPosition(slider->r_maxValue, cpos);
812   XmTextSetCursorPosition(slider->f_maxValue, cpos);
813   XmScaleSetValue(slider->r_slider, pos);
814   XmScaleSetValue(slider->f_slider, pos);
815 } // max_cb()
816 
817 /*!
818 */
819 
820 void
max_value_cb(Widget widget,XtPointer closure,XtPointer call_data)821 SoXtSlider::max_value_cb(
822   Widget widget,
823   XtPointer closure,
824   XtPointer call_data)
825 {
826   assert(closure != NULL);
827   SoXtSlider * slider = (SoXtSlider *) closure;
828   float previous = slider->current;
829   float prevmin = slider->minimum;
830   slider->maximum = atof(XmTextGetString(widget));
831   slider->minimum = SoXtMin(slider->minimum, slider->maximum);
832   slider->current = SoXtMin(slider->current, slider->maximum);
833 
834 #if SOXT_DEBUG && 0
835   SoDebugError::postInfo("SoXtSlider::max_value_cb", "[invoked]");
836 #endif // SOXT_DEBUG
837 
838   char text[16];
839   sprintf(text, "%.2g", slider->maximum);
840   int cpos = strlen(text);
841   int pos = 0;
842   if (slider->minimum != slider->maximum)
843     pos = (int) ((slider->current - slider->minimum) /
844       (slider->maximum - slider->minimum) * 999.0f);
845 
846   XmTextSetString(slider->r_maxValue, text);
847   XmTextSetString(slider->f_maxValue, text);
848   XmTextSetCursorPosition(slider->r_maxValue, cpos);
849   XmTextSetCursorPosition(slider->f_maxValue, cpos);
850 
851   if (prevmin != slider->minimum) {
852     sprintf(text, "%.2g", slider->minimum);
853     cpos = strlen(text);
854     XmTextSetString(slider->r_minValue, text);
855     XmTextSetString(slider->f_minValue, text);
856     XmTextSetCursorPosition(slider->r_minValue, cpos);
857     XmTextSetCursorPosition(slider->f_minValue, cpos);
858   }
859 
860   XmScaleSetValue(slider->s_slider, pos);
861   XmScaleSetValue(slider->r_slider, pos);
862   XmScaleSetValue(slider->f_slider, pos);
863   XmScaleSetValue(slider->o_slider, pos);
864 
865   if (previous != slider->current) {
866     sprintf(text, "%.2g", slider->current);
867     cpos = strlen(text);
868     XmTextSetString(slider->s_value, text);
869     XmTextSetString(slider->r_value, text);
870     XmTextSetString(slider->f_value, text);
871     XmTextSetString(slider->o_value, text);
872     XmTextSetCursorPosition(slider->s_value, cpos);
873     XmTextSetCursorPosition(slider->r_value, cpos);
874     XmTextSetCursorPosition(slider->f_value, cpos);
875     XmTextSetCursorPosition(slider->o_value, cpos);
876   }
877   if (previous != slider->current)
878     slider->invokeCallbacks();
879 } // max_value_cb()
880 
881 // *************************************************************************
882 
883