1 /*----------------------------------------------------------------------------
2 --
3 --  Module:           XmUbTimeSlider
4 --
5 --  Project:          XmUb - Ulle's Motif widgets
6 --  System:
7 --    Subsystem:      <>
8 --    Function block: <>
9 --
10 --  Description:
11 --    This is the implementation of the widget.
12 --
13 --    For the geometry management, the text widget is set to the width it
14 --    requests, and the scale widths are adjusted depending on the current
15 --    width of the widget.
16 --
17 --  Filename:         XmUbTimeSl.c
18 --
19 --  Authors:          Roger Larsson, Ulrika Bornetun
20 --  Creation date:    1993-09-21
21 --
22 --
23 --  (C) Copyright Ulrika Bornetun, Roger Larsson (1995)
24 --      All rights reserved
25 --
26 --  Permission to use, copy, modify, and distribute this software and its
27 --  documentation for any purpose and without fee is hereby granted,
28 --  provided that the above copyright notice appear in all copies. Ulrika
29 --  Bornetun and Roger Larsson make no representations about the usability
30 --  of this software for any purpose. It is provided "as is" without express
31 --  or implied warranty.
32 ----------------------------------------------------------------------------*/
33 
34 /* SCCS module identifier. */
35 static char SCCSID[] = "@(#) Module: XmUbTimeSl.c, Version: 1.1, Date: 95/02/18 15:10:16";
36 
37 
38 /*----------------------------------------------------------------------------
39 --  Include files
40 ----------------------------------------------------------------------------*/
41 
42 #include <stdio.h>
43 #include <string.h>
44 #include <X11/Intrinsic.h>
45 #include <X11/StringDefs.h>
46 #include <Xm/XmP.h>
47 
48 #include <Xm/Scale.h>
49 #include <Xm/Text.h>
50 
51 /* Rogge's tools. */
52 #include "TimDate.h"
53 
54 /* Private widget header file. */
55 #include "XmUbTimeSlP.h"
56 
57 /*----------------------------------------------------------------------------
58 --  Macro definitions
59 ----------------------------------------------------------------------------*/
60 
61 #ifdef MAX
62 #undef MAX
63 #endif
64 
65 #ifdef MIN
66 #undef MIN
67 #endif
68 
69 #define MAX( x, y )  ( ( x ) > ( y ) ? ( x ) : ( y ) )
70 #define MIN( x, y )  ( ( x ) < ( y ) ? ( x ) : ( y ) )
71 
72 #define XmUbTS_CHILD_ERROR  -1
73 
74 #define TEXT_BUFFER_LENGTH  20
75 
76 /*----------------------------------------------------------------------------
77 --  Type declarations
78 ----------------------------------------------------------------------------*/
79 
80 typedef struct {
81 
82   Dimension  width;
83   Dimension  height;
84   Position   x;
85   Position   y;
86 
87 } KidDimensionRec;
88 
89 /*----------------------------------------------------------------------------
90 --  Global definitions
91 ----------------------------------------------------------------------------*/
92 
93 /* Internal Motif functions (how do we know about this....?) */
94 extern void
95   _XmBackgroundColorDefault();
96 
97 
98 /* The time slider resource list. */
99 static XtResource resources[] = {
100   {
101     XmNactivateCallback,
102     XmCCallback,
103     XmRCallback, sizeof( XtCallbackList ),
104     XtOffset( XmUbTimeSliderWidget, sl.activate_callback ),
105     XmRCallback,
106     NULL
107   },
108   {
109     XmNvalueChangedCallback,
110     XmCCallback,
111     XmRCallback, sizeof( XtCallbackList ),
112     XtOffset( XmUbTimeSliderWidget, sl.value_changed_callback ),
113     XmRCallback,
114     NULL
115   },
116   {
117     XmNmarginHeight,
118     XmCMarginHeight,
119     XtRDimension, sizeof( Dimension ),
120     XtOffset( XmUbTimeSliderWidget, sl.margin_height ),
121     XtRImmediate,
122     (XtPointer) 0
123   },
124   {
125     XmNmarginWidth,
126     XmCMarginWidth,
127     XtRDimension, sizeof( Dimension ),
128     XtOffset( XmUbTimeSliderWidget, sl.margin_width ),
129     XtRImmediate,
130     (XtPointer) 0
131   },
132   {
133     XmUbNtslRecomputeHeight,
134     XmUbCTslRecomputeHeight,
135     XtRBoolean, sizeof( Boolean ),
136     XtOffset( XmUbTimeSliderWidget, sl.recompute_height ),
137     XtRImmediate,
138     (XtPointer) True
139   },
140   {
141     XmUbNtslRecomputeWidth,
142     XmUbCTslRecomputeWidth,
143     XtRBoolean, sizeof( Boolean ),
144     XtOffset( XmUbTimeSliderWidget, sl.recompute_width ),
145     XtRImmediate,
146     (XtPointer) True
147   },
148   {
149     XmUbNtslSpacing,
150     XmCSpacing,
151     XtRDimension, sizeof( Dimension ),
152     XtOffset( XmUbTimeSliderWidget, sl.slider_spacing ),
153     XtRImmediate,
154     (XtPointer) 4
155   },
156   {
157     XmUbNtslTextSpacing,
158     XmCSpacing,
159     XtRDimension, sizeof( Dimension ),
160     XtOffset( XmUbTimeSliderWidget, sl.text_spacing ),
161     XtRImmediate,
162     (XtPointer) 8
163   },
164 
165 };  /* resources */
166 
167 
168 
169 
170 /*----------------------------------------------------------------------------
171 --  Function prototypes
172 ----------------------------------------------------------------------------*/
173 
174 /* Core methods. */
175 static void
176   ChangeManaged( Widget  widget );
177 
178 static void
179   DeleteChild( Widget  widget );
180 
181 static void
182   Destroy( Widget   widget );
183 
184 static XtGeometryResult
185   GeometryManager( Widget            widget,
186                    XtWidgetGeometry  *request,
187                    XtWidgetGeometry  *reply );
188 
189 static void
190   Initialize( Widget     treq,
191               Widget     tnew,
192               ArgList    args,
193               Cardinal   *num_args );
194 
195 static void
196   InsertChild( Widget  widget );
197 
198 static XtGeometryResult
199   QueryGeometry( Widget             widget,
200                  XtWidgetGeometry  *proposed,
201                  XtWidgetGeometry  *answer );
202 
203 static void
204   Resize( Widget    widget );
205 
206 static Boolean
207   SetValues( Widget     current,
208              Widget     request,
209              Widget     new,
210              ArgList    args,
211              Cardinal   *num_args );
212 
213 
214 /* Internal functions. */
215 
216 
217 static void
218   ActivateCB( Widget                tw,
219               XmUbTimeSliderWidget  tbox,
220               XmAnyCallbackStruct   *call_data );
221 
222 /* If not in the child list, returns XmUbTS_CHILD_ERROR. */
223 static int
224   ChildIndex( XmUbTimeSliderWidget  tsl,
225               Widget                child );
226 
227 static Widget
228   CreateSlider( XmUbTimeSliderWidget  tsl,
229                 char                  *name,
230                 int                   maximum );
231 
232 /* Fills in the width and height fields in the kids dimension recs. */
233 static void
234   GetChildPrefSizes( XmUbTimeSliderWidget  tsl,
235                      Widget                initiator,
236                      XtWidgetGeometry      *request,
237                      KidDimensionRec       sizes[] );
238 
239 
240 /* The sizes array must have been prepared by GetChildPrefSizes before this
241    function is called. */
242 static void
243   GetOwnPreferredSize( XmUbTimeSliderWidget  tsl,
244                        KidDimensionRec       sizes[],
245                        Dimension             *pref_width,
246                        Dimension             *pref_height );
247 
248 /* The sizes array  must have been processed by GetChildPrefSizes
249    before DoLayout is called. */
250 static void
251   DoLayout( XmUbTimeSliderWidget  tsl,
252             Widget                initiator,
253             XtWidgetGeometry      *request,
254             KidDimensionRec       sizes[] );
255 
256 static void
257   KidsPreferredGeometry( Widget            kid,
258                          Widget            initiator,
259                          XtWidgetGeometry  *request,
260                          XtWidgetGeometry  *desired );
261 
262 static void
263   ScaleValueChangedCB( Widget                 scale,
264                        XmUbTimeSliderWidget   tsl,
265                        XmScaleCallbackStruct  *call_data );
266 
267 /* ResizeIfNeeded fills in the sizes array. Does not have to be initialized. */
268 static Boolean
269   ResizeIfNeeded( XmUbTimeSliderWidget  tsl,
270                   KidDimensionRec    sizes[] );
271 
272 static void
273   SelectAllTextCB( Widget                tw,
274                    XmUbTimeSliderWidget  tsl,
275                    XmAnyCallbackStruct   *call_data );
276 
277 static void
278   TextChangedCB( Widget                textw,
279                  XmUbTimeSliderWidget  tsl,
280                  XmAnyCallbackStruct   *call_data );
281 
282 static void
283   UpdateScales( XmUbTimeSliderWidget  tsl,
284                 int                   hour,
285                 int                   minute );
286 
287 static void
288   UpdateTextField( XmUbTimeSliderWidget  tsl );
289 
290 static void
291   ValueChangedCB( Widget                tw,
292                   XmUbTimeSliderWidget  tsl,
293                   XmAnyCallbackStruct   *call_data );
294 
295 static void
296   WarningNoResourceChange( XmUbTimeSliderWidget  tsl,
297                            String                resource );
298 
299 /*----------------------------------------------------------------------------
300 --  Initialization of the class record.
301 ----------------------------------------------------------------------------*/
302 
303 /* This initialization has to be done after the methods have been declared. */
304 XmUbTimeSliderClassRec xmUbTimeSliderClassRec = {
305 
306   { /* Core class fields. */
307     /* superclass */                    (WidgetClass) &xmManagerClassRec,
308     /* class_name */                    "XmUbTimeSlider",
309     /* widget_size */                   sizeof( XmUbTimeSliderRec ),
310     /* class_initialize */              NULL,
311     /* class_part_initialize */         NULL,
312     /* class_inited */                  False,
313     /* initialize */                    Initialize,
314     /* initialize_hook */               NULL,
315     /* realize */                       XtInheritRealize,
316     /* actions */                       NULL,
317     /* num_actions */                   0,
318     /* resources */                     resources,
319     /* num_resources */                 XtNumber( resources ),
320     /* xrm_class */                     NULLQUARK,
321     /* compress_motion */               True,
322     /* compress_exposure */             True,
323     /* compress_enterleave */           True,
324     /* visible_interest */              False,
325     /* destroy */                       Destroy,
326     /* resize */                        Resize,
327     /* expose */                        NULL,
328     /* set_values */                    SetValues,
329     /* set_values_hook */               NULL,
330     /* set_values_almost */             XtInheritSetValuesAlmost,
331     /* get_values_hook */               NULL,
332     /* accept_focus */                  NULL,
333     /* version */                       XtVersion,
334     /* callback_private */              NULL,
335     /* tm_table */                      NULL,
336     /* query_geometry */                QueryGeometry,
337     /* display_accelerator */           XtInheritDisplayAccelerator,
338     /* extension */                     NULL
339   },
340   { /* Composite class part. */
341     /* geometry_manager */              GeometryManager,
342     /* change_managed */                ChangeManaged,
343     /* insert_child */                  InsertChild,
344     /* delete_child */                  DeleteChild,
345     /* extension */                     NULL
346   },
347   { /* Constraint class fields. */
348     /* subresources */                  NULL,
349     /* subresource_count */             0,
350     /* constraint_size */               sizeof( XmUbTimeSliderConstraintsRec ),
351     /* initialize */                    NULL,
352     /* destroy */                       NULL,
353     /* set_values */                    NULL,
354     /* extension */                     NULL
355   },
356   { /* XmManager class part. */
357     /* translations */                  NULL,
358     /* get_resources */                 NULL,
359     /* num_get_resources */             0,
360     /* get_constraint_resources */      NULL,
361     /* num_get_constraint_resources */  0,
362     /* extension */                     NULL
363   },
364   { /* Time slider class part. */
365     /* extension */                     NULL
366   },
367 
368 };
369 
370 
371 /* Class record pointer. */
372 WidgetClass
373   xmUbTimeSliderWidgetClass = (WidgetClass) &xmUbTimeSliderClassRec;
374 
375 
376 
377 /*----------------------------------------------------------------------------
378 --  Functions
379 ----------------------------------------------------------------------------*/
380 
381 static void
ActivateCB(Widget tw,XmUbTimeSliderWidget tsl,XmAnyCallbackStruct * call_data)382   ActivateCB( Widget                tw,
383               XmUbTimeSliderWidget  tsl,
384               XmAnyCallbackStruct   *call_data )
385 {
386   /* Variables. */
387   XmUbTimeSliderCallbackStruct  cb;
388 
389   /* Code. */
390 
391   if( tsl -> sl.activate_callback == NULL )
392     return;
393 
394   /* Set up callback structure. */
395 
396   cb.reason      = XmCR_ACTIVATE;
397   cb.event       = call_data -> event;
398   cb.child_index = ChildIndex( tsl, tw );
399   cb.child       = tw;
400 
401   XtCallCallbackList( (Widget) tsl, tsl -> sl.activate_callback,
402                       (XtPointer) &cb );
403 
404 
405   return;
406 
407 } /* ActivateCB */
408 
409 
410 /*----------------------------------------------------------------------*/
411 
412 static void
ChangeManaged(Widget widget)413   ChangeManaged( Widget  widget )
414 {
415   /* Variables. */
416   Boolean               layout_done;
417   KidDimensionRec       kids_sizes[ NO_INTERNAL_CHILDREN ];
418   XmUbTimeSliderWidget  tsl;
419 
420 
421   /* Code. */
422 
423   tsl = (XmUbTimeSliderWidget) widget;
424 
425   /* ResizeIfNeeded checks the size of all children and resizes the widget. */
426   layout_done = ResizeIfNeeded( tsl, kids_sizes );
427 
428   /* Do the layout. */
429   if( !layout_done )
430     DoLayout( tsl, NULL, NULL, kids_sizes );
431 
432 
433   return;
434 
435 } /* ChangeManaged */
436 
437 
438 /*----------------------------------------------------------------------*/
439 
440 static int
ChildIndex(XmUbTimeSliderWidget tsl,Widget child)441   ChildIndex( XmUbTimeSliderWidget  tsl,
442               Widget                child )
443 {
444   /* Variables. */
445   int  index;
446 
447   /* Code. */
448 
449   for( index = 0; index < NO_INTERNAL_CHILDREN; index ++ ){
450 
451     if( tsl -> sl.internal_children[ index ] == child )
452       return index;
453 
454   } /* for */
455 
456 
457   /* Specified child not found. */
458   return XmUbTS_CHILD_ERROR;
459 
460 } /* ChildIndex */
461 
462 
463 /*----------------------------------------------------------------------*/
464 
465 static void
CreateInternalWidgets(XmUbTimeSliderWidget tsl)466   CreateInternalWidgets( XmUbTimeSliderWidget  tsl )
467 {
468   /* Variables. */
469   Arg           args[ 5 ];
470   short         columns;
471   int           index;
472   Cardinal      n;
473   char          *name_buffer;
474   char          text_buffer[ TEXT_BUFFER_LENGTH ];
475   TIM_TIME_REF  time;
476   String        wname;
477 
478   /* Code. */
479 
480   /* Get the name of the "parent" widget. */
481   wname = XtName( (Widget)tsl );
482 
483   name_buffer = XtMalloc( strlen( wname ) + 4 );
484 
485   /* Create the sliders. */
486 
487   /* Hour slider. */
488   sprintf( name_buffer, "%sHSL", wname );
489 
490   tsl -> sl.internal_children[ XmUbTS_CHILD_HOUR_SLIDER ] =
491     CreateSlider( tsl, name_buffer, 23 );
492 
493   /* Minute slider. */
494   sprintf( name_buffer, "%sMSL", wname );
495 
496   tsl -> sl.internal_children[ XmUbTS_CHILD_MINUTE_SLIDER ] =
497     CreateSlider( tsl, name_buffer, 59 );
498 
499   /* Create the text field. */
500   sprintf( name_buffer, "%sTX", wname );
501 
502   /* Find out how many columns wide we should make the widget. */
503   time = TimMakeTime( 1990, 1, 1, 23, 59, 59 );
504   TimFormatTime( time, text_buffer, TEXT_BUFFER_LENGTH );
505   columns = (short) ( strlen( text_buffer ) + 1 );
506 
507   n = 0;
508   XtSetArg( args[ n ], XmNcolumns, columns ); n++;
509   XtSetArg( args[ n ], XmNmaxLength, columns ); n++;
510   tsl -> sl.internal_children[ XmUbTS_CHILD_TEXT_FIELD ] =
511     XmCreateText( (Widget) tsl, name_buffer, args, n );
512 
513   XtAddCallback( tsl -> sl.internal_children[ XmUbTS_CHILD_TEXT_FIELD ],
514                  XmNvalueChangedCallback,
515                  (XtCallbackProc) TextChangedCB, (XtPointer) tsl );
516 
517   XtAddCallback( tsl -> sl.internal_children[ XmUbTS_CHILD_TEXT_FIELD ],
518                  XmNactivateCallback,
519                  (XtCallbackProc) ActivateCB, (XtPointer) tsl );
520 
521   XtAddCallback( tsl -> sl.internal_children[ XmUbTS_CHILD_TEXT_FIELD ],
522                  XmNvalueChangedCallback,
523                  (XtCallbackProc) ValueChangedCB, (XtPointer) tsl );
524 
525   XtAddCallback( tsl -> sl.internal_children[ XmUbTS_CHILD_TEXT_FIELD ],
526                  XmNfocusCallback,
527                  (XtCallbackProc) SelectAllTextCB, (XtPointer) tsl );
528 
529   /* Manage the created children. */
530   for( index = XmUbTS_FIRST_CHILD; index < NO_INTERNAL_CHILDREN; index ++ ){
531     if( tsl -> sl.internal_children[ index ] != NULL )
532       XtManageChild( tsl -> sl.internal_children[ index ] );
533   }
534 
535 
536   XtFree( name_buffer );
537 
538 
539   return;
540 
541 } /* CreateInternalWidgets */
542 
543 
544 /*----------------------------------------------------------------------*/
545 
546 static Widget
CreateSlider(XmUbTimeSliderWidget tsl,char * name,int maximum)547   CreateSlider( XmUbTimeSliderWidget  tsl,
548                 char                  *name,
549                 int                   maximum )
550 {
551   /* Variables. */
552   Arg       args[ 5 ];
553   Cardinal  n;
554   Widget    scale;
555 
556   /* Code. */
557 
558   n = 0;
559   XtSetArg( args[ n ], XmNorientation, XmHORIZONTAL ); n++;
560   XtSetArg( args[ n ], XmNshowValue, False ); n++;
561   XtSetArg( args[ n ], XmNminimum, 0 ); n++;
562   XtSetArg( args[ n ], XmNmaximum, maximum ); n++;
563   scale = XmCreateScale( (Widget) tsl, name, args, n );
564 
565   XtAddCallback( scale, XmNvalueChangedCallback,
566                  (XtCallbackProc) ScaleValueChangedCB, (XtPointer) tsl );
567   XtAddCallback( scale, XmNdragCallback,
568                  (XtCallbackProc) ScaleValueChangedCB, (XtPointer) tsl );
569 
570 
571   return( scale );
572 
573 } /* CreateSlider */
574 
575 
576 /*----------------------------------------------------------------------*/
577 
578 static void
DeleteChild(Widget widget)579   DeleteChild( Widget  widget )
580 {
581 
582   /* Variables. */
583   int                   index;
584   XmUbTimeSliderWidget  tsl;
585 
586   /* Code. */
587 
588   tsl = (XmUbTimeSliderWidget) XtParent( widget );
589 
590   /* Clear the internal reference. */
591   for( index = 0; index < NO_INTERNAL_CHILDREN; index ++ ){
592     if( tsl -> sl.internal_children[ index ] == widget ){
593       tsl -> sl.internal_children[ index ] = NULL;
594       break;
595     }
596   }
597 
598   /* Perform the actual operation */
599   (* ( (CompositeWidgetClass) (xmUbTimeSliderWidgetClass ->
600      core_class.superclass) ) -> composite_class.delete_child ) ( widget );
601 
602 
603   return;
604 
605 } /* DeleteChild */
606 
607 
608 /*----------------------------------------------------------------------*/
609 
610 static void
Destroy(Widget widget)611   Destroy( Widget   widget )
612 {
613   /* Code. */
614 
615   /* Remove callbacks. */
616   XtRemoveAllCallbacks( widget, XmNactivateCallback );
617   XtRemoveAllCallbacks( widget, XmNvalueChangedCallback );
618 
619 
620   return;
621 
622 } /* Destroy */
623 
624 
625 /*----------------------------------------------------------------------*/
626 
627 static void
DoLayout(XmUbTimeSliderWidget tsl,Widget initiator,XtWidgetGeometry * request,KidDimensionRec sizes[])628   DoLayout( XmUbTimeSliderWidget  tsl,
629             Widget                initiator,
630             XtWidgetGeometry      *request,
631             KidDimensionRec       sizes[] )
632 {
633   /* Variables. */
634   int        index;
635   Widget     kid;
636   int        no_managed;
637   Dimension  scale_width;
638   Position   scale_x_pos;
639   Position   scale_y_offset;
640   Dimension  total_height;
641   Position   y_pos;
642 
643   /* Code. */
644 
645   /* Start with the text widget, let it keep its requested size. */
646   if( ( sizes[ XmUbTS_CHILD_TEXT_FIELD ].width + tsl -> sl.margin_width ) >
647       tsl -> core.width )
648     sizes[ XmUbTS_CHILD_TEXT_FIELD ].x = 0;
649   else
650     sizes[ XmUbTS_CHILD_TEXT_FIELD ].x = (Position) ( tsl -> core.width -
651       tsl -> sl.margin_width - sizes[ XmUbTS_CHILD_TEXT_FIELD ].width );
652 
653   /* Get the total height of the scales. */
654   no_managed   = 0;
655   total_height = 0;
656   for( index = XmUbTS_CHILD_HOUR_SLIDER;
657        index < XmUbTS_CHILD_MINUTE_SLIDER + 1; index ++ ){
658 
659     /* If not managed, width and height are zero. */
660     if( sizes[ index ].width > 0 ){
661       no_managed ++;
662       total_height += sizes[ index ].height;
663     }
664   } /* for */
665 
666   if( no_managed > 1 )
667     total_height += tsl -> sl.slider_spacing;
668 
669   /* Center the scales and the text field vertically. */
670   if( total_height > sizes[ XmUbTS_CHILD_TEXT_FIELD ].height ){
671     sizes[ XmUbTS_CHILD_TEXT_FIELD ].y = (Position) ( tsl -> sl.margin_height +
672       ( total_height - sizes[ XmUbTS_CHILD_TEXT_FIELD ].height ) / 2 );
673     scale_y_offset = 0;
674   } else {
675     sizes[ XmUbTS_CHILD_TEXT_FIELD ].y =
676       (Position) ( tsl -> sl.margin_height );
677     scale_y_offset = (Position) ( sizes[ XmUbTS_CHILD_TEXT_FIELD ].height -
678                                   total_height ) / 2;
679   }
680 
681   /* Let the scales do with the width that is left. */
682   if( ( sizes[ XmUbTS_CHILD_TEXT_FIELD ].width + 2 * tsl -> sl.margin_width ) >
683       tsl -> core.width ){
684     scale_width = 1;
685     scale_x_pos = 0;
686 
687   } else {
688 
689     scale_width = tsl -> core.width - sizes[ XmUbTS_CHILD_TEXT_FIELD ].width -
690       2 * tsl -> sl.margin_width;
691     scale_x_pos = tsl -> sl.margin_width;
692   }
693 
694   y_pos = tsl -> sl.margin_height + scale_y_offset;
695   for( index = XmUbTS_CHILD_HOUR_SLIDER;
696        index < XmUbTS_CHILD_MINUTE_SLIDER + 1; index ++ ){
697 
698     kid = tsl -> sl.internal_children[ index ];
699 
700     if( ( kid != NULL ) && XtIsManaged( kid ) ){
701       sizes[ index ].width = scale_width;
702       sizes[ index ].x     = scale_x_pos;
703       sizes[ index ].y     = y_pos;
704 
705       y_pos += (Position) ( sizes[ index ].height + tsl -> sl.slider_spacing );
706     }
707   } /* for */
708 
709 
710   /* Configure the children. */
711   /* All positions and dimensions are now in the sizes array. */
712   for( index = XmUbTS_FIRST_CHILD; index < NO_INTERNAL_CHILDREN; index ++ ){
713 
714     kid = tsl -> sl.internal_children[ index ];
715 
716     if( ( kid != NULL ) && XtIsManaged( kid ) )
717       XtConfigureWidget( kid, sizes[ index ].x, sizes[ index ].y,
718         sizes[ index ].width, sizes[ index ].height,
719         kid -> core.border_width );
720   }
721 
722 
723   return;
724 
725 } /* DoLayout */
726 
727 
728 /*----------------------------------------------------------------------*/
729 
730 static XtGeometryResult
GeometryManager(Widget widget,XtWidgetGeometry * request,XtWidgetGeometry * reply)731   GeometryManager( Widget            widget,
732                    XtWidgetGeometry  *request,
733                    XtWidgetGeometry  *reply )
734 {
735 
736   XtWidgetGeometry      own_request;
737   Dimension             old_width, old_height;
738   Dimension             pref_height;
739   Dimension             pref_width;
740   KidDimensionRec       kids_sizes[ NO_INTERNAL_CHILDREN ];
741   XtGeometryResult      result;
742   XmUbTimeSliderWidget  tsl;
743 
744   /* Code. */
745 
746   tsl = (XmUbTimeSliderWidget) XtParent( widget );
747 
748   /* Find out how big the widget would be if the resize were allowed. */
749   GetChildPrefSizes( tsl, NULL, request, kids_sizes );
750   GetOwnPreferredSize( tsl, kids_sizes, &pref_width, &pref_height );
751 
752   /* If no change in dimensions, allow the request. */
753   if( ( pref_width == tsl -> core.width ) &&
754       ( pref_height == tsl -> core.height )){
755     DoLayout( tsl, widget, request, kids_sizes );
756     return XtGeometryYes;
757   }
758 
759   /* We must ask our parent to resize us. */
760   own_request.request_mode = CWWidth | CWHeight;
761   own_request.width  = pref_width;
762   own_request.height = pref_height;
763 
764   /* Save dimensions. */
765   old_width  = tsl -> core.width;
766   old_height = tsl -> core.height;
767 
768   tsl -> sl.resize_called = False;
769 
770   /* We are not interested in any compromise geometry. */
771   result = XtMakeGeometryRequest( (Widget) tsl, &own_request, NULL );
772 
773   /* Reset to old dimensions if request not granted. */
774   if( result != XtGeometryYes ){
775     tsl -> core.width  = old_width;
776     tsl -> core.height = old_height;
777 
778   } else {
779     if( !tsl -> sl.resize_called )
780       Resize( (Widget) tsl );
781   }
782 
783   /* Always grant child's request. */
784   return XtGeometryYes;
785 
786 } /* GeometryManager */
787 
788 
789 /*----------------------------------------------------------------------*/
790 
791 static void
GetChildPrefSizes(XmUbTimeSliderWidget tsl,Widget initiator,XtWidgetGeometry * request,KidDimensionRec sizes[])792   GetChildPrefSizes( XmUbTimeSliderWidget  tsl,
793                      Widget                initiator,
794                      XtWidgetGeometry      *request,
795                      KidDimensionRec       sizes[] )
796 {
797   /* Variables. */
798   XtWidgetGeometry  desired;
799   int               index;
800   Widget            kid;
801 
802   /* Code. */
803 
804   /* Initialize. */
805   for( index = 0; index < NO_INTERNAL_CHILDREN; index ++ ){
806     sizes[ index ].width  = 0;
807     sizes[ index ].height = 0;
808     sizes[ index ].x      = 0;
809     sizes[ index ].y      = 0;
810   }
811 
812   /* Get the preferred sizes for the children. */
813   for( index = XmUbTS_FIRST_CHILD; index < NO_INTERNAL_CHILDREN; index ++ ){
814 
815     kid = tsl -> sl.internal_children[ index ];
816 
817     if( ( kid != NULL ) && XtIsManaged( kid ) ){
818 
819       KidsPreferredGeometry( kid, initiator, request, &desired );
820 
821       sizes[ index ].width  = desired.width;
822       sizes[ index ].height = desired.height;
823 
824     }
825 
826   } /* for */
827 
828 
829   return;
830 
831 } /* GetChildPrefSizes */
832 
833 
834 /*----------------------------------------------------------------------*/
835 
836 static void
GetOwnPreferredSize(XmUbTimeSliderWidget tsl,KidDimensionRec sizes[],Dimension * pref_width,Dimension * pref_height)837   GetOwnPreferredSize( XmUbTimeSliderWidget  tsl,
838                        KidDimensionRec       sizes[],
839                        Dimension             *pref_width,
840                        Dimension             *pref_height )
841 {
842   /* Variables. */
843   int        index;
844   Widget     kid;
845   Dimension  max_scale_width = 0;
846   int        no_managed = 0;
847   Dimension  total_scale_height = 0;
848 
849   /* Code. */
850 
851   /* Check out the dimension of the scales. */
852   for( index = XmUbTS_CHILD_HOUR_SLIDER;
853        index < XmUbTS_CHILD_MINUTE_SLIDER + 1; index ++ ){
854 
855     kid = tsl -> sl.internal_children[ index ];
856 
857     if( ( kid != NULL ) && XtIsManaged( kid ) ){
858 
859       total_scale_height += sizes[ index ].height;
860 
861       if( sizes[ index ].width > max_scale_width )
862         max_scale_width = sizes[ index ].width;
863 
864       no_managed ++;
865     }
866   } /* for */
867 
868   if( no_managed > 1 )
869     total_scale_height += tsl -> sl.slider_spacing;
870 
871   /* We may not be allowed to request the size the children would like. */
872   if( tsl -> sl.recompute_width )
873     *pref_width  = max_scale_width + sizes[ XmUbTS_CHILD_TEXT_FIELD ].width +
874                    2 * tsl -> sl.margin_width + tsl -> sl.text_spacing;
875   else
876     *pref_width = tsl -> core.width;
877 
878   if( tsl -> sl.recompute_height )
879     *pref_height = MAX( total_scale_height,
880                         sizes[ XmUbTS_CHILD_TEXT_FIELD ].height ) +
881                    2 * tsl -> sl.margin_height;
882   else
883     *pref_height = tsl -> core.height;
884 
885 
886   return;
887 
888 } /* GetOwnPreferredSize */
889 
890 
891 /*----------------------------------------------------------------------*/
892 
893 static void
Initialize(Widget treq,Widget tnew,ArgList args,Cardinal * num_args)894   Initialize( Widget     treq,
895               Widget     tnew,
896               ArgList    args,
897               Cardinal   *num_args )
898 {
899   /* Variables. */
900   int                   index;
901   XmUbTimeSliderWidget  new;
902 
903   /* Code. */
904 
905   new = (XmUbTimeSliderWidget) tnew;
906 
907   /* Initialize private fields. */
908   for( index = XmUbTS_FIRST_CHILD; index < NO_INTERNAL_CHILDREN; index ++ )
909     new -> sl.internal_children[ index ] = NULL;
910 
911   /* Start size if none supplied. */
912   if( new -> core.width == 0 )
913     new -> core.width = 300;
914   else
915     new -> sl.recompute_width = False;
916 
917   if( new -> core.height == 0 )
918     new -> core.height = 100;
919   else
920     new -> sl.recompute_height = False;
921 
922   /* Create the internal widgets. */
923   new -> sl.internal_widgets_created = False;
924 
925   CreateInternalWidgets( new );
926 
927   new -> sl.internal_widgets_created = True;
928 
929   /* Set the initial value in the text field. */
930   UpdateTextField( new );
931 
932 
933   return;
934 
935 } /* Initialize */
936 
937 
938 /*----------------------------------------------------------------------*/
939 
940 static void
InsertChild(Widget widget)941   InsertChild( Widget  widget )
942 {
943 
944   /* Variables. */
945   Cardinal              num_params;
946   String                params[ 1 ];
947   XmUbTimeSliderWidget  tsl;
948 
949   /* Code. */
950 
951   tsl = (XmUbTimeSliderWidget) XtParent( widget );
952 
953   /* We do not allow the application to create children. */
954   if( tsl -> sl.internal_widgets_created ){
955 
956     params[ 0 ] = XtClass( (Widget) tsl ) -> core_class.class_name;
957     num_params  = 1;
958     XtAppErrorMsg( XtWidgetToApplicationContext( widget ),
959                    "childError", "number", "WidgetError",
960                    "Applications cannot add children to %s widgets.",
961                    params, &num_params );
962   }
963 
964   /* This is an internal child. Adding it is OK. */
965   (* ( (CompositeWidgetClass) (xmUbTimeSliderWidgetClass ->
966      core_class.superclass) ) -> composite_class.insert_child ) ( widget );
967 
968 
969   return;
970 
971 } /* InsertChild */
972 
973 
974 /*----------------------------------------------------------------------*/
975 
976 static void
KidsPreferredGeometry(Widget kid,Widget initiator,XtWidgetGeometry * request,XtWidgetGeometry * desired)977   KidsPreferredGeometry( Widget            kid,
978                          Widget            initiator,
979                          XtWidgetGeometry  *request,
980                          XtWidgetGeometry  *desired )
981 {
982 
983   /* Code. */
984 
985   if( ( kid == initiator ) && ( request != NULL ) ){
986     /* The initiator should not be queried. */
987     if( request -> request_mode & CWWidth )
988       desired -> width = request -> width;
989     else
990       desired -> width = (Dimension) kid -> core.width;
991 
992     if( request -> request_mode & CWHeight )
993       desired -> height = request -> height;
994     else
995       desired -> height = (Dimension) kid -> core.height;
996 
997   } else
998     (void) XtQueryGeometry( kid, NULL, desired );
999 
1000 
1001   return;
1002 
1003 } /* KidsPreferredGeometry */
1004 
1005 
1006 /*----------------------------------------------------------------------*/
1007 
1008 static void
Resize(Widget widget)1009   Resize( Widget    widget )
1010 {
1011   /* Variables. */
1012   KidDimensionRec       kids_sizes[ NO_INTERNAL_CHILDREN ];
1013   XmUbTimeSliderWidget  tsl;
1014 
1015   /* Code. */
1016 
1017   tsl = (XmUbTimeSliderWidget) widget;
1018 
1019   tsl -> sl.resize_called = True;
1020 
1021   /* We have to get the preferred size of the children before we organize
1022      the layout. */
1023   GetChildPrefSizes( tsl, NULL, NULL, kids_sizes );
1024   DoLayout( tsl, NULL, NULL, kids_sizes );
1025 
1026 
1027   return;
1028 
1029 } /* Resize */
1030 
1031 
1032 /*----------------------------------------------------------------------*/
1033 
1034 static Boolean
ResizeIfNeeded(XmUbTimeSliderWidget tsl,KidDimensionRec sizes[])1035   ResizeIfNeeded( XmUbTimeSliderWidget  tsl,
1036                   KidDimensionRec       sizes[] )
1037 {
1038 
1039   /* Variables. */
1040   Boolean           layout_done;
1041   Dimension         pref_height;
1042   Dimension         pref_width;
1043   XtWidgetGeometry  request;
1044   XtGeometryResult  result;
1045 
1046   /* Code. */
1047 
1048   /* Initialize. */
1049   layout_done = False;
1050 
1051   /* Get the preferred dimensions of the time box widget. */
1052   GetChildPrefSizes( tsl, NULL, NULL, sizes );
1053   GetOwnPreferredSize( tsl, sizes, &pref_width, &pref_height );
1054 
1055   /* If we want the same dimensions, no resizing is needed. */
1056   if(( pref_width  == tsl -> core.width ) &&
1057      ( pref_height == tsl -> core.height ))
1058     return False;
1059 
1060   /* Dimensions are different. Try to resize. */
1061   request.request_mode = CWWidth | CWHeight;
1062 
1063   request.width  = pref_width;
1064   request.height = pref_height;
1065 
1066   tsl -> sl.resize_called = False;
1067 
1068   do {
1069 
1070     result = XtMakeGeometryRequest( (Widget) tsl, &request, &request );
1071 
1072   } while( result == XtGeometryAlmost );
1073 
1074   if( result == XtGeometryNo )
1075     return False;
1076 
1077   /* Resize done. Core fields have already been updated. */
1078   return( tsl -> sl.resize_called );
1079 
1080 } /* ResizeIfNeeded */
1081 
1082 
1083 /*----------------------------------------------------------------------*/
1084 
1085 static XtGeometryResult
QueryGeometry(Widget widget,XtWidgetGeometry * proposed,XtWidgetGeometry * answer)1086   QueryGeometry( Widget             widget,
1087                  XtWidgetGeometry  *proposed,
1088                  XtWidgetGeometry  *answer )
1089 {
1090 
1091   KidDimensionRec       kids_sizes[ NO_INTERNAL_CHILDREN ];
1092   Dimension             pref_height;
1093   Dimension             pref_width;
1094   XmUbTimeSliderWidget  tsl;
1095 
1096   /* Code. */
1097 
1098 
1099   tsl = (XmUbTimeSliderWidget) widget;
1100 
1101   /* Get dimensions that we *really* want. */
1102   GetChildPrefSizes( tsl, NULL, NULL, kids_sizes );
1103   GetOwnPreferredSize( tsl, kids_sizes, &pref_width, &pref_height );
1104 
1105   answer -> request_mode = CWWidth | CWHeight;
1106   answer -> width  = pref_width;
1107   answer -> height = pref_height;
1108 
1109 
1110   if( proposed == NULL ){
1111     /* This is a query for the requested geometry. */
1112 
1113     if(( answer -> height == (int) tsl -> core.height ) &&
1114        ( answer -> width  == (int) tsl -> core.width ))
1115       return XtGeometryNo;
1116     else
1117       return XtGeometryAlmost;
1118   }
1119 
1120   /* The parent supplied a geometry suggestion. */
1121   if(( answer -> height == proposed -> height ) &&
1122      ( answer -> width  == proposed -> width ))
1123     return XtGeometryYes;
1124 
1125   if( ( proposed -> height <= 1 ) ||
1126       ( proposed -> width  <= 1 ) )
1127     /* That's too small ! */
1128     return XtGeometryNo;
1129 
1130 
1131   /* Only a compromise left. */
1132   return XtGeometryAlmost;
1133 
1134 } /* QueryGeometry */
1135 
1136 
1137 /*----------------------------------------------------------------------*/
1138 
1139 static void
ScaleValueChangedCB(Widget scale,XmUbTimeSliderWidget tsl,XmScaleCallbackStruct * call_data)1140   ScaleValueChangedCB( Widget                 scale,
1141                        XmUbTimeSliderWidget   tsl,
1142                        XmScaleCallbackStruct  *call_data )
1143 {
1144   /* Code. */
1145 
1146   UpdateTextField( tsl );
1147 
1148 
1149   return;
1150 
1151 } /* ScaleValueChangedCB */
1152 
1153 
1154 /*----------------------------------------------------------------------*/
1155 
1156 static void
SelectAllTextCB(Widget tw,XmUbTimeSliderWidget tsl,XmAnyCallbackStruct * call_data)1157   SelectAllTextCB( Widget                tw,
1158                    XmUbTimeSliderWidget  tsl,
1159                    XmAnyCallbackStruct   *call_data )
1160 {
1161   /* Variables. */
1162   XmTextPosition  last;
1163 
1164   /* Code. */
1165 
1166   /* Select all text in the text widget. */
1167 
1168   last = XmTextGetLastPosition( tw );
1169 
1170   if( last > 0 )
1171     XmTextSetSelection( tw, 0, last, CurrentTime );
1172 
1173   /* Set the insertion position to the start of the widget. */
1174   XmTextSetInsertionPosition( tw, 0 );
1175 
1176 
1177   return;
1178 
1179 } /* SelectAllTextCB */
1180 
1181 
1182 /*----------------------------------------------------------------------*/
1183 
1184 static Boolean
SetValues(Widget current,Widget request,Widget new,ArgList args,Cardinal * num_args)1185   SetValues( Widget     current,
1186              Widget     request,
1187              Widget     new,
1188              ArgList    args,
1189              Cardinal   *num_args )
1190 {
1191 #ifdef Differs
1192 #undef Differs
1193 #endif
1194 
1195 #define Differs( field )  ( curW -> field != newW -> field )
1196 
1197   /* Variables. */
1198   XmUbTimeSliderWidget  curW;
1199   Arg                   local_args[ 2 ];
1200   Cardinal              n;
1201   XmUbTimeSliderWidget  newW;
1202   Boolean               visual_changed = False;
1203 
1204   /* Code. */
1205 
1206   curW = (XmUbTimeSliderWidget) current;
1207   newW = (XmUbTimeSliderWidget) new;
1208 
1209   /* Width and height. */
1210   /* Resizing is handled higher up. */
1211 
1212   if( Differs( sl.recompute_width ) && newW -> sl.recompute_width )
1213     visual_changed = True;
1214   else if( Differs( core.width ) )
1215     newW -> sl.recompute_width = False;
1216 
1217   if( Differs( sl.recompute_height ) && newW -> sl.recompute_height )
1218     visual_changed = True;
1219   else if( Differs( core.height ) )
1220     newW -> sl.recompute_height = False;
1221 
1222   /* Margins and spacings. */
1223   if( Differs( sl.slider_spacing ) ||
1224       Differs( sl.text_spacing )   ||
1225       Differs( sl.margin_width )   ||
1226       Differs( sl.margin_height ) )
1227     visual_changed = True;
1228 
1229   /* These changes affect the child widgets. */
1230   if( Differs( manager.foreground ) ||
1231       Differs( core.background_pixel ) ){
1232 
1233     n = 0;
1234 
1235     if( Differs( manager.foreground ) ){
1236       XtSetArg( local_args[ n ], XmNforeground,
1237                                  newW -> manager.foreground ); n++;
1238     }
1239     if( Differs( core.background_pixel ) ){
1240       XtSetArg( local_args[ n ], XmNbackground,
1241                                  newW -> core.background_pixel ); n++;
1242     }
1243 
1244     XtSetValues( newW -> sl.internal_children[ XmUbTS_CHILD_HOUR_SLIDER ],
1245                  local_args, n );
1246     XtSetValues( newW -> sl.internal_children[ XmUbTS_CHILD_MINUTE_SLIDER ],
1247                  local_args, n );
1248     XtSetValues( newW -> sl.internal_children[ XmUbTS_CHILD_TEXT_FIELD ],
1249                  local_args, n );
1250   }
1251 
1252 
1253   if( visual_changed ){
1254 
1255     KidDimensionRec  kids_sizes[ NO_INTERNAL_CHILDREN ];
1256     Boolean          resized;
1257 
1258     /* Code. */
1259 
1260     resized = ResizeIfNeeded( newW, kids_sizes );
1261 
1262     /* If the widget was resized, the layout has already been done. */
1263     if( !resized )
1264       DoLayout( newW, NULL, NULL, kids_sizes );
1265 
1266   }
1267 
1268   return( visual_changed );
1269 
1270 #undef Differs
1271 
1272 } /* SetValues */
1273 
1274 
1275 /*----------------------------------------------------------------------*/
1276 
1277 static void
TextChangedCB(Widget textw,XmUbTimeSliderWidget tsl,XmAnyCallbackStruct * call_data)1278   TextChangedCB( Widget                textw,
1279                  XmUbTimeSliderWidget  tsl,
1280                  XmAnyCallbackStruct   *call_data )
1281 {
1282   /* Variables. */
1283   int              hour;
1284   int              minute;
1285   TIM_STATUS_TYPE  status;
1286   String           str;
1287   TIM_TIME_REF     time;
1288 
1289   /* Code. */
1290 
1291   /* Get the current text string. */
1292   str = XmTextGetString(
1293           XmUbTimeSliderGetChild( (Widget) tsl, XmUbTS_CHILD_TEXT_FIELD ) );
1294 
1295   /* Get the hour and minute values. */
1296   status = TimMakeTimeFromString( &time, str );
1297 
1298   if( status == TIM_OK ){
1299 
1300     hour   = TimHour( time );
1301     minute = TimMinute( time );
1302 
1303     UpdateScales( tsl, hour, minute );
1304   }
1305 
1306   /* Cleanup.*/
1307   XtFree( str );
1308 
1309 
1310   return;
1311 
1312 } /* TextChangedCB */
1313 
1314 
1315 /*----------------------------------------------------------------------*/
1316 
1317 static void
UpdateScales(XmUbTimeSliderWidget tsl,int hour,int minute)1318   UpdateScales( XmUbTimeSliderWidget  tsl,
1319                 int                   hour,
1320                 int                   minute )
1321 {
1322   /* Variables. */
1323   Widget  scale;
1324 
1325   /* Code. */
1326 
1327   /* Set the scale values. */
1328   scale = XmUbTimeSliderGetChild( (Widget) tsl, XmUbTS_CHILD_HOUR_SLIDER );
1329   if( scale != NULL )
1330     XmScaleSetValue( scale, hour );
1331 
1332   scale = XmUbTimeSliderGetChild( (Widget) tsl, XmUbTS_CHILD_MINUTE_SLIDER );
1333   if( scale != NULL )
1334     XmScaleSetValue( scale, minute );
1335 
1336 
1337   return;
1338 
1339 } /* UpdateScales */
1340 
1341 
1342 /*----------------------------------------------------------------------*/
1343 
1344 static void
UpdateTextField(XmUbTimeSliderWidget tsl)1345   UpdateTextField( XmUbTimeSliderWidget  tsl )
1346 {
1347   /* Variables. */
1348   int           hour = 0;
1349   int           minute = 0;
1350   char          text_buffer[ TEXT_BUFFER_LENGTH ];
1351   TIM_TIME_REF  time;
1352   Widget        tmp_widget;
1353 
1354   /* Code. */
1355 
1356   /* Get the value from the sliders one at a time. */
1357 
1358   tmp_widget = XmUbTimeSliderGetChild( (Widget) tsl,
1359                                        XmUbTS_CHILD_HOUR_SLIDER );
1360   if( tmp_widget != NULL )
1361     XmScaleGetValue( tmp_widget, &hour );
1362 
1363   tmp_widget = XmUbTimeSliderGetChild( (Widget) tsl,
1364                                        XmUbTS_CHILD_MINUTE_SLIDER );
1365   if( tmp_widget != NULL )
1366     XmScaleGetValue( tmp_widget, &minute );
1367 
1368 
1369   /* Create a time string to display in the text field. */
1370   time = TimMakeTime( 1990, 1, 1, hour, minute, 0 );
1371   TimFormatTime( time, text_buffer, TEXT_BUFFER_LENGTH );
1372 
1373   XmTextSetString(
1374     XmUbTimeSliderGetChild( (Widget) tsl, XmUbTS_CHILD_TEXT_FIELD ),
1375     text_buffer );
1376 
1377 
1378   return;
1379 
1380 } /* UpdateTextField */
1381 
1382 
1383 /*----------------------------------------------------------------------*/
1384 
1385 static void
ValueChangedCB(Widget tw,XmUbTimeSliderWidget tsl,XmAnyCallbackStruct * call_data)1386   ValueChangedCB( Widget                tw,
1387                   XmUbTimeSliderWidget  tsl,
1388                   XmAnyCallbackStruct   *call_data )
1389 {
1390   /* Variables. */
1391   XmUbTimeSliderCallbackStruct  cb;
1392 
1393   /* Code. */
1394 
1395   if( tsl -> sl.value_changed_callback == NULL )
1396     return;
1397 
1398   /* Set up callback structure. */
1399 
1400   cb.reason      = XmCR_VALUE_CHANGED;
1401   cb.event       = call_data -> event;
1402   cb.child_index = ChildIndex( tsl, tw );
1403   cb.child       = tw;
1404 
1405   XtCallCallbackList( (Widget) tsl, tsl -> sl.value_changed_callback,
1406                       (XtPointer) &cb );
1407 
1408 
1409   return;
1410 
1411 } /* ValueChangedCB */
1412 
1413 
1414 /*----------------------------------------------------------------------*/
1415 
1416 static void
WarningNoResourceChange(XmUbTimeSliderWidget tsl,String resource)1417   WarningNoResourceChange( XmUbTimeSliderWidget  tsl,
1418                            String                resource )
1419 {
1420   /* Variables. */
1421   Cardinal  num_params;
1422   String    params[ 2 ];
1423 
1424   /* Code. */
1425 
1426   params[ 0 ] = resource;
1427   params[ 1 ] = XtClass( tsl ) -> core_class.class_name;
1428   num_params  = 2;
1429   XtAppWarningMsg( XtWidgetToApplicationContext( (Widget) tsl ),
1430 		   "resourceError", "setValues", "WidgetError",
1431 		   "Resource %s may not be changed in %s widgets.",
1432 		   params, &num_params );
1433 
1434   return;
1435 
1436 } /* WarningNoResourceChange */
1437 
1438 
1439 /*----------------------------------------------------------------------*/
1440 
1441 Widget
XmUbCreateTimeSlider(Widget parent,String name,ArgList arglist,Cardinal argcount)1442   XmUbCreateTimeSlider( Widget    parent,
1443                         String    name,
1444                         ArgList   arglist,
1445                         Cardinal  argcount )
1446 {
1447 
1448   /* Code. */
1449 
1450   return XtCreateWidget( name, xmUbTimeSliderWidgetClass,
1451                          parent, arglist, argcount );
1452 
1453 } /* XmUbCreateTimeSlider */
1454 
1455 
1456 /*----------------------------------------------------------------------*/
1457 
1458 Widget
XmUbTimeSliderGetChild(Widget widget,int child)1459   XmUbTimeSliderGetChild( Widget  widget,
1460                           int     child )
1461 {
1462 
1463   /* Variables. */
1464   XmUbTimeSliderWidget  tsl;
1465 
1466   /* Code. */
1467 
1468   tsl = (XmUbTimeSliderWidget) widget;
1469 
1470 
1471   return( tsl -> sl.internal_children[ child ] );
1472 
1473 } /* XmUbTimeSliderGetChild */
1474 
1475 
1476 /*----------------------------------------------------------------------*/
1477 
1478 time_t
XmUbTimeSliderGetTime(Widget widget)1479   XmUbTimeSliderGetTime( Widget  widget )
1480 {
1481   /* Variables. */
1482   int           hour = 0;
1483   int           minute = 0;
1484   TIM_TIME_REF  time;
1485   Widget        tmp_widget;
1486 
1487   /* Code. */
1488 
1489   /* Get the value from the sliders one at a time. */
1490 
1491   tmp_widget = XmUbTimeSliderGetChild( widget, XmUbTS_CHILD_HOUR_SLIDER );
1492   if( tmp_widget != NULL )
1493     XmScaleGetValue( tmp_widget, &hour );
1494 
1495   tmp_widget = XmUbTimeSliderGetChild( widget, XmUbTS_CHILD_MINUTE_SLIDER );
1496   if( tmp_widget != NULL )
1497     XmScaleGetValue( tmp_widget, &minute );
1498 
1499   /* Create the time from the fetched values. */
1500   time = TimMakeTime( 1970, 1, 1, hour, minute, 0 );
1501 
1502 
1503   return time;
1504 
1505 } /* XmUbTimeSliderGetTime */
1506 
1507 
1508 /*----------------------------------------------------------------------*/
1509 
1510 char
XmUbTimeSliderGetTimeString(Widget widget)1511   *XmUbTimeSliderGetTimeString( Widget  widget )
1512 {
1513   /* Variables. */
1514   Widget  textw;
1515 
1516   /* Code. */
1517   textw = XmUbTimeSliderGetChild( widget, XmUbTS_CHILD_TEXT_FIELD );
1518   if( textw == NULL )
1519     return( NULL );
1520 
1521 
1522   return( XmTextGetString( textw ) );
1523 
1524 } /* XmUbTimeSliderGetTimeString */
1525 
1526 
1527 /*----------------------------------------------------------------------*/
1528 
1529 void
XmUbTimeSliderSetTime(Widget widget,time_t time)1530   XmUbTimeSliderSetTime( Widget  widget,
1531                          time_t  time )
1532 {
1533   /* Variables. */
1534   int                   hour;
1535   int                   minute;
1536   XmUbTimeSliderWidget  tsl;
1537 
1538   /* Code. */
1539 
1540   tsl = (XmUbTimeSliderWidget) widget;
1541 
1542   hour   = TimHour( time );
1543   minute = TimMinute( time );
1544 
1545   UpdateScales( tsl, hour, minute );
1546 
1547   /* If the widget is not mapped, the value changed callback will
1548      not be called. */
1549   UpdateTextField( tsl );
1550 
1551   return;
1552 
1553 } /* XmUbTimeSliderSetTime */
1554