1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/motif/gauge.cpp
3// Purpose:     wxGauge class
4// Author:      Julian Smart
5// Modified by:
6// Created:     17/09/98
7// RCS-ID:      $Id: gauge.cpp 40024 2006-07-06 09:09:09Z ABX $
8// Copyright:   (c) Julian Smart
9// Licence:     wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __VMS
16#include "wx/vms_x_fix.h"
17#undef XtDisplay
18#undef XtScreen
19#undef XtWindow
20#undef XtIsRealized
21#undef XtParent
22#undef XtClass
23#endif
24
25#include "wx/gauge.h"
26
27#ifndef WX_PRECOMP
28    #include "wx/math.h"
29#endif
30
31#ifdef __OS2__
32#include <types.h>
33#endif
34
35#ifdef __VMS__
36#pragma message disable nosimpint
37#endif
38#include <Xm/Xm.h>
39#ifdef __WXMOTIF20__
40#include <Xm/Scale.h>
41#endif // __WXMOTIF20__
42#ifdef __VMS__
43#pragma message enable nosimpint
44#endif
45#include "wx/motif/private.h"
46
47IMPLEMENT_DYNAMIC_CLASS(wxGauge, wxControl)
48
49#if !wxCHECK_MOTIF_VERSION( 2, 0 ) || wxCHECK_LESSTIF()
50
51// XmGauge copyright notice:
52
53/*
54* Copyright 1994 GROUPE BULL
55*
56* Permission to use, copy, modify, and distribute this software and its
57* documentation for any purpose and without fee is hereby granted, provided
58* that the above copyright notice appear in all copies and that both that
59* copyright notice and this permission notice appear in supporting
60* documentation, and that the name of GROUPE BULL not be used in advertising
61* or publicity pertaining to distribution of the software without specific,
62* written prior permission.  GROUPE BULL makes no representations about the
63* suitability of this software for any purpose.  It is provided "as is"
64* without express or implied warranty.
65*
66* GROUPE BULL disclaims all warranties with regard to this software,
67* including all implied warranties of merchantability and fitness,
68* in no event shall GROUPE BULL be liable for any special,
69* indirect or consequential damages or any damages
70* whatsoever resulting from loss of use, data or profits,
71* whether in an action of contract, negligence or other tortious
72* action, arising out of or in connection with the use
73* or performance of this software.
74*
75*/
76
77//// PUBLIC XMGAUGE DECLARATIONS
78typedef struct _XmGaugeClassRec*  XmGaugeWidgetClass;
79typedef struct _XmGaugeRec*       XmGaugeWidget;
80
81#ifdef __cplusplus
82extern "C" WidgetClass xmGaugeWidgetClass;
83#else
84extern WidgetClass xmGaugeWidgetClass;
85#endif
86
87typedef struct _XmGaugeCallbackStruct{
88    int reason;
89    XEvent *event;
90    int value;
91} XmGaugeCallbackStruct;
92
93
94void
95XmGaugeSetValue(Widget w, int value);
96
97int
98XmGaugeGetValue(Widget w);
99
100#endif // !wxCHECK_MOTIF_VERSION( 2, 0 ) || wxCHECK_LESSTIF()
101
102bool wxGauge::Create(wxWindow *parent, wxWindowID id,
103                     int range,
104                     const wxPoint& pos,
105                     const wxSize& size,
106                     long style,
107                     const wxValidator& validator,
108                     const wxString& name)
109{
110    if( !CreateControl( parent, id, pos, size, style, validator, name ) )
111        return false;
112
113    Widget parentWidget = (Widget) parent->GetClientWidget();
114
115    Arg args[7];
116    int count = 4;
117    if (style & wxGA_HORIZONTAL)
118    {
119        XtSetArg (args[0], XmNorientation, XmHORIZONTAL);
120        XtSetArg (args[1], XmNprocessingDirection, XmMAX_ON_RIGHT);
121    }
122    else
123    {
124        XtSetArg (args[0], XmNorientation, XmVERTICAL);
125        XtSetArg (args[1], XmNprocessingDirection, XmMAX_ON_TOP);
126    }
127    XtSetArg(args[2], XmNminimum, 0);
128    XtSetArg(args[3], XmNmaximum, range);
129#if wxCHECK_MOTIF_VERSION( 2, 0 ) && !wxCHECK_LESSTIF()
130    XtSetArg(args[4], XmNeditable, False); ++count;
131    XtSetArg(args[5], XmNslidingMode, XmTHERMOMETER); ++count;
132    // XtSetArg(args[6], XmNsliderVisual, XmFOREGROUND_COLOR ); ++count;
133    Widget gaugeWidget =
134        XtCreateManagedWidget("gauge", xmScaleWidgetClass,
135                              parentWidget, args, count);
136#else
137    Widget gaugeWidget =
138        XtCreateManagedWidget("gauge", xmGaugeWidgetClass,
139                              parentWidget, args, count);
140#endif
141    m_mainWidget = (WXWidget) gaugeWidget ;
142
143    XtManageChild (gaugeWidget);
144
145    int x = pos.x; int y = pos.y;
146    wxSize best = GetBestSize();
147    if( size.x != wxDefaultCoord ) best.x = size.x;
148    if( size.y != wxDefaultCoord ) best.y = size.y;
149
150    ChangeFont(false);
151
152    AttachWidget (parent, m_mainWidget, (WXWidget) NULL, x, y,
153                  best.x, best.y);
154
155    ChangeBackgroundColour();
156
157    return true;
158}
159
160wxSize wxGauge::DoGetBestSize() const
161{
162    if( HasFlag(wxGA_HORIZONTAL) )
163        return wxSize( 100, 18 );
164    else
165        return wxSize( 18, 100 );
166}
167
168void wxGauge::SetShadowWidth(int w)
169{
170    if (w == 0)
171        w = 1;
172    XtVaSetValues((Widget) m_mainWidget, XmNshadowThickness, w, NULL);
173}
174
175void wxGauge::SetRange(int r)
176{
177    XtVaSetValues((Widget) m_mainWidget, XmNmaximum, r, NULL);
178}
179
180void wxGauge::SetValue(int pos)
181{
182    XtVaSetValues((Widget) m_mainWidget, XmNvalue, pos, NULL);
183}
184
185int wxGauge::GetShadowWidth() const
186{
187    Dimension w;
188    XtVaGetValues((Widget) m_mainWidget, XmNshadowThickness, &w, NULL);
189    return (int)w;
190}
191
192int wxGauge::GetRange() const
193{
194    int r;
195    XtVaGetValues((Widget) m_mainWidget, XmNmaximum, &r, NULL);
196    return (int)r;
197}
198
199int wxGauge::GetValue() const
200{
201    int pos;
202    XtVaGetValues((Widget) m_mainWidget, XmNvalue, &pos, NULL);
203    return pos;
204}
205
206void wxGauge::DoMoveWindow(int x, int y, int width, int height)
207{
208    wxGaugeBase::DoMoveWindow( x, y, width, height );
209#ifdef __WXMOTIF20__
210    XtVaSetValues( (Widget)m_mainWidget,
211                   XmNscaleHeight, height,
212                   NULL );
213#endif
214}
215
216#if !wxCHECK_MOTIF_VERSION( 2, 0 ) || wxCHECK_LESSTIF()
217
218//// PRIVATE DECLARATIONS FOR XMGAUGE
219
220#include <Xm/PrimitiveP.h>
221#include <Xm/DrawP.h>
222
223typedef struct {
224    int empty;
225} XmGaugeClassPart;
226
227typedef struct _XmGaugeClassRec {
228    CoreClassPart         core_class;
229    XmPrimitiveClassPart  primitive_class;
230    XmGaugeClassPart      gauge_class;
231} XmGaugeClassRec;
232
233
234typedef struct _XmGaugePart{
235    int value;
236    int minimum;
237    int maximum;
238    unsigned char orientation;
239    unsigned char processingDirection;
240
241    XtCallbackList dragCallback;
242    XtCallbackList valueChangedCallback;
243
244    /* private fields */
245    Boolean dragging; /* drag in progress ? */
246    int oldx, oldy;
247    GC gc;
248} XmGaugePart;
249
250
251typedef struct _XmGaugeRec {
252    CorePart         core;
253    XmPrimitivePart  primitive;
254    XmGaugePart      gauge;
255} XmGaugeRec;
256
257extern XmGaugeClassRec xmGaugeClassRec;
258
259/* Copyright 1994 GROUPE BULL -- See license conditions in file COPYRIGHT */
260
261//// XMGAUGE IMPLEMENTATION
262
263void
264GaugePick(Widget w, XEvent *e, String *args, Cardinal  *num_args);
265void
266GaugeDrag(Widget w, XEvent *e, String *args, Cardinal  *num_args);
267void
268GaugeDrop(Widget w, XEvent *e, String *args, Cardinal  *num_args);
269
270
271
272static char translations[] =
273"<Btn1Down>: GaugePick()\n\
274                            <Btn1Motion>: GaugeDrag()\n\
275                            <Btn1Up>: GaugeDrop()\n\
276                            ";
277
278
279
280static XtActionsRec actions[] = {
281    {"GaugePick", GaugePick},
282    {"GaugeDrag", GaugeDrag},
283    {"GaugeDrop", GaugeDrop},
284};
285
286static void
287DrawSlider(XmGaugeWidget gw, Boolean clear)
288{
289#define THIS gw->gauge
290    int size, sht;
291    float ratio;
292    /***chubraev
293    char string[20];
294    int len;
295    unsigned long backgr,foregr;
296    XRectangle rects[1];
297    ***/
298
299    sht = gw->primitive.shadow_thickness;
300
301    ratio =  (float)THIS.value/
302        (float)(THIS.maximum - THIS.minimum);
303        /***chubraev
304        sprintf(string,"%-d%%",(int)(ratio*100));
305        len=strlen(string);
306        XtVaGetValues(gw,XmNbackground,&backgr,XmNforeground,&foregr,NULL);
307    ***/
308
309    if(clear) {
310        XClearArea(XtDisplay(gw), XtWindow(gw), sht, sht,
311            gw->core.width - 2 * sht, gw->core.height - 2 * sht, False);
312    }
313    switch(THIS.orientation) {
314    case XmHORIZONTAL:
315        size = (int) ((gw->core.width - 2 * sht)*ratio);
316        /***chubraev
317        XDrawString(XtDisplay(gw), XtWindow(gw), THIS.gc, sht+gw->core.width/2,
318        gw->core.height - 2 * sht, string, len);
319        ***/
320        switch(THIS.processingDirection) {
321        case XmMAX_ON_RIGHT:
322        case XmMAX_ON_BOTTOM:
323            XFillRectangle(XtDisplay(gw), XtWindow(gw), THIS.gc,
324                sht, sht, size, gw->core.height - 2 * sht);
325
326                /***chubraev
327                rects[0].x = sht; rects[0].y = sht;
328                rects[0].width = size; rects[0].height = gw->core.height - 2 * sht;
329            ***/
330            break;
331        case XmMAX_ON_LEFT:
332        case XmMAX_ON_TOP:
333            XFillRectangle(XtDisplay(gw), XtWindow(gw), THIS.gc,
334                gw->core.width - size - sht, sht,
335                size, gw->core.height - 2 * sht);
336
337                /***chubraev
338                rects[0].x = gw->core.width - size - sht; rects[0].y = sht;
339                rects[0].width = size; rects[0].height = gw->core.height - 2 * sht;
340            ***/
341            break;
342        }
343        /***chubraev
344        XSetClipRectangles(XtDisplay(gw), THIS.gc, 0, 0, rects, 1, Unsorted);
345        XSetForeground(XtDisplay(gw), THIS.gc, backgr);
346        XDrawString(XtDisplay(gw), XtWindow(gw), THIS.gc, sht+gw->core.width/2,
347        gw->core.height - 2 * sht, string, len);
348        ***/
349
350        break;
351        case XmVERTICAL:
352            size = (int) ((gw->core.height - 2 * sht)*ratio);
353            /***chubraev
354            XDrawString(XtDisplay(gw), XtWindow(gw), THIS.gc, sht,
355            sht+gw->core.height/2, string,len);
356            ***/
357            switch(THIS.processingDirection) {
358            case XmMAX_ON_RIGHT:
359            case XmMAX_ON_BOTTOM:
360                XFillRectangle(XtDisplay(gw), XtWindow(gw), THIS.gc,
361                    sht, sht, gw->core.width - 2 * sht, size);
362
363                    /***chubraev
364                    rects[0].x = sht; rects[0].y = sht;
365                    rects[0].width = gw->core.width - 2 * sht; rects[0].height = size;
366                ***/
367                break;
368            case XmMAX_ON_LEFT:
369            case XmMAX_ON_TOP:
370                XFillRectangle(XtDisplay(gw), XtWindow(gw), THIS.gc,
371                    sht, gw->core.height - size - sht,
372                    gw->core.width - 2 * sht, size);
373
374                    /***chubraev
375                    rects[0].x = sht; rects[0].y = gw->core.height - size - sht;
376                    rects[0].width = gw->core.width - 2 * sht; rects[0].height = size;
377                ***/
378            }
379            /***chubraev
380            XSetClipRectangles(XtDisplay(gw), THIS.gc, 0, 0, rects, 1, Unsorted);
381            XSetForeground(XtDisplay(gw), THIS.gc, backgr);
382            XDrawString(XtDisplay(gw), XtWindow(gw), THIS.gc, sht,
383            sht+gw->core.height/2, string,len);
384            ***/
385            break;
386    }
387    /***chubraev
388    XSetClipMask(XtDisplay(gw), THIS.gc, None);
389    XSetForeground(XtDisplay(gw), THIS.gc, foregr);
390    ***/
391#undef THIS
392}
393
394/* Old code
395*/
396#if 0
397static void
398DrawSlider(XmGaugeWidget gw, Boolean clear)
399{
400#define THIS gw->gauge
401    int size, sht;
402    /*    float ratio; */
403
404    sht = gw->primitive.shadow_thickness;
405    /* See fix comment below: can cause divide by zero error.
406    ratio = (float)((float)THIS.maximum -
407    (float)THIS.minimum) / (float)THIS.value;
408    */
409    if(clear) {
410        XClearArea(XtDisplay(gw), XtWindow(gw), sht, sht,
411            gw->core.width - 2 * sht, gw->core.height - 2 * sht, False);
412    }
413    switch(THIS.orientation) {
414    case XmHORIZONTAL:
415        /* size = (gw->core.width - 2 * sht) / ratio; */
416        /* A fix suggested by Dmitri Chubraev */
417        size = (gw->core.width - 2 * sht) /((float)THIS.maximum-(float)THIS.minimum)*(float)THIS.value;
418        switch(THIS.processingDirection) {
419        case XmMAX_ON_RIGHT:
420        case XmMAX_ON_BOTTOM:
421            XFillRectangle(XtDisplay(gw), XtWindow(gw), THIS.gc,
422                sht, sht, size, gw->core.height - 2 * sht);
423            break;
424        case XmMAX_ON_LEFT:
425        case XmMAX_ON_TOP:
426            XFillRectangle(XtDisplay(gw), XtWindow(gw), THIS.gc,
427                gw->core.width - size - sht, sht,
428                size, gw->core.height - 2 * sht);
429            break;
430        }
431        break;
432        case XmVERTICAL:
433            size = (gw->core.height - 2 * sht) /((float)THIS.maximum-(float)THIS.minimum)*(float)THIS.value;
434            /* size = (gw->core.height - 2 * sht)/ ratio; */
435            switch(THIS.processingDirection) {
436            case XmMAX_ON_RIGHT:
437            case XmMAX_ON_BOTTOM:
438                XFillRectangle(XtDisplay(gw), XtWindow(gw), THIS.gc,
439                    sht, sht, gw->core.width - 2 * sht, size);
440                break;
441            case XmMAX_ON_LEFT:
442            case XmMAX_ON_TOP:
443                XFillRectangle(XtDisplay(gw), XtWindow(gw), THIS.gc,
444                    sht, gw->core.height - size - sht,
445                    gw->core.width - 2 * sht, size);
446            }
447            break;
448    }
449#undef THIS
450}
451#endif
452
453static void
454Initialize(Widget WXUNUSED(req), Widget new_w, ArgList WXUNUSED(args), Cardinal *WXUNUSED(num_args ))
455{
456    XmGaugeWidget gw = (XmGaugeWidget)new_w;
457#define THIS gw->gauge
458    XGCValues values;
459
460    values.foreground = gw->primitive.foreground;
461    THIS.gc = XtGetGC(new_w, GCForeground, &values);
462
463#undef THIS
464
465}
466
467
468
469static void
470Destroy(Widget w)
471{
472    XmGaugeWidget gw = (XmGaugeWidget)w;
473#define THIS gw->gauge
474    XtReleaseGC(w, THIS.gc);
475#undef THIS
476}
477
478
479
480
481static Boolean
482SetValues(
483          Widget cw,
484          Widget WXUNUSED(rw),
485          Widget nw,
486          ArgList WXUNUSED(args),
487          Cardinal *WXUNUSED(num_args) )
488{
489    XmGaugeWidget cgw = (XmGaugeWidget)cw;
490    XmGaugeWidget ngw = (XmGaugeWidget)nw;
491
492    Boolean redraw = False;
493    if(cgw->primitive.foreground != ngw->primitive.foreground) {
494        XGCValues values;
495
496        redraw = True;
497        XtReleaseGC(nw, ngw->gauge.gc);
498        values.foreground = ngw->primitive.foreground;
499        ngw->gauge.gc = XtGetGC(nw, GCForeground, &values);
500    }
501    if(cgw->gauge.value != ngw->gauge.value) {
502        redraw = True;
503    }
504    return redraw;
505}
506
507
508
509
510static void
511ExposeProc(Widget w, XEvent *WXUNUSED(event), Region WXUNUSED(r))
512{
513    XmGaugeWidget gw = (XmGaugeWidget)w;
514#define THIS gw->gauge
515    int sht;
516
517    sht = gw->primitive.shadow_thickness;
518    _XmDrawShadows(XtDisplay(w), XtWindow(w),
519        gw->primitive.top_shadow_GC,
520        gw->primitive.bottom_shadow_GC,
521        0, 0, w->core.width, w->core.height,
522        (Dimension)sht, XmSHADOW_IN);
523    DrawSlider(gw, False);
524#undef THIS
525}
526
527
528
529
530
531static XtResource
532resources[] = {
533#define offset(field) XtOffset(XmGaugeWidget, gauge.field)
534    {XmNvalue, XmCValue, XtRInt, sizeof(int),
535        offset(value), XtRImmediate, (caddr_t)10},
536
537    {XmNminimum, XmCValue, XtRInt, sizeof(int),
538    offset(minimum), XtRImmediate, (caddr_t)0},
539
540    {XmNmaximum, XmCValue, XtRInt, sizeof(int),
541    offset(maximum), XtRImmediate, (caddr_t)100},
542
543    {XmNorientation, XmCOrientation, XmROrientation, sizeof(unsigned char),
544    offset(orientation), XtRImmediate, (caddr_t)XmVERTICAL},
545
546    {XmNprocessingDirection, XmCProcessingDirection,
547    XmRProcessingDirection, sizeof(unsigned char),
548    offset(processingDirection), XtRImmediate, (caddr_t)XmMAX_ON_RIGHT},
549
550    {XmNdragCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
551    offset(dragCallback), XtRImmediate, (caddr_t)NULL},
552
553    {XmNvalueChangedCallback, XmCCallback, XmRCallback, sizeof(XtCallbackList),
554    offset(valueChangedCallback), XtRImmediate, (caddr_t)NULL},
555
556
557#undef offset
558};
559
560
561XmGaugeClassRec xmGaugeClassRec = {
562    {    /* core fields */
563        (WidgetClass) &xmPrimitiveClassRec, /* superclass */
564        "XmGauge",            /* class_name */
565        sizeof(XmGaugeRec),   /* widget_size */
566        NULL,                 /* class_initialize */
567        NULL,                 /* class_part_initialize */
568        False,                /* class_inited */
569        Initialize,           /* initialize */
570        NULL,                 /* initialize_hook */
571        XtInheritRealize,     /* realize */
572        actions,              /* actions */
573        XtNumber(actions),    /* num_actions */
574        resources,            /* resources */
575        XtNumber(resources),  /* num_resources */
576        NULLQUARK,            /* xrm_class */
577        True,                 /* compress_motion */
578        True,                 /* compress_exposure */
579        True,                 /* compress_enterleave */
580        False,                /* visible_interest */
581        Destroy,              /* destroy */
582        NULL,                 /* resize */
583        ExposeProc,           /* expose */
584        SetValues,            /* set_values */
585        NULL,                 /* set_values_hook */
586        XtInheritSetValuesAlmost, /* set_values_almost */
587        NULL,                 /* get_values_hook */
588        NULL,                 /* accept_focus */
589        XtVersion,            /* version */
590        NULL,                 /* callback_private */
591        translations,         /* tm_table */
592        NULL,                 /* query_geometry */
593        NULL,                 /* display_accelerator */
594        NULL                  /* extension */
595    },
596    /* primitive_class fields */
597    {
598        NULL,                 /* border_highlight */
599        NULL,                 /* border_unhighlight */
600        NULL,                 /* translations */
601        NULL,                 /* arm_and_activate */
602        NULL,                 /* syn_resources */
603        0,                    /* num_syn_resources */
604        NULL                  /* extension */
605    },
606    { /* gauge fields */
607        0                     /* empty */
608    }
609};
610
611WidgetClass xmGaugeWidgetClass = (WidgetClass)&xmGaugeClassRec;
612
613
614
615
616void
617GaugePick(Widget WXUNUSED(w), XEvent *WXUNUSED(e), String *WXUNUSED(args), Cardinal  *WXUNUSED(num_args))
618{
619    /* Commented out for a read-only gauge in wxWidgets */
620#if 0
621    XmGaugeWidget gw = (XmGaugeWidget)w;
622#define THIS gw->gauge
623    int size, sht;
624    float ratio;
625    Boolean dragging = False;
626    XButtonEvent *event = (XButtonEvent *)e;
627    int x, y;
628
629    x = event->x;
630    y = event->y;
631    sht = gw->primitive.shadow_thickness;
632    _XmDrawShadows(XtDisplay(w), XtWindow(w),
633        gw->primitive.top_shadow_GC,
634        gw->primitive.bottom_shadow_GC,
635        0, 0, w->core.width, w->core.height,
636        sht, XmSHADOW_IN);
637
638
639    ratio = (float)((float)THIS.maximum -
640        (float)THIS.minimum) / (float)THIS.value;
641    switch(THIS.orientation) {
642    case XmHORIZONTAL:
643        size = (w->core.width - 2 * sht) / ratio;
644        switch(THIS.processingDirection) {
645        case XmMAX_ON_RIGHT:
646        case XmMAX_ON_BOTTOM:
647            dragging = (x > sht) && (y > sht) &&
648                (x < sht + size) && (y < w->core.height - sht);
649            break;
650        case XmMAX_ON_LEFT:
651        case XmMAX_ON_TOP:
652            dragging = (x > w->core.width - size - sht) && (y > sht) &&
653                (x < w->core.width - sht) && (y < w->core.height + sht);
654            break;
655        }
656        break;
657        case XmVERTICAL:
658            size = (w->core.height - 2 * sht) / ratio;
659            switch(THIS.processingDirection) {
660            case XmMAX_ON_RIGHT:
661            case XmMAX_ON_BOTTOM:
662                dragging = (x > sht) && (y > sht) &&
663                    (x < w->core.width - sht) &&
664                    (y < w->core.width - 2 * sht + size);
665                break;
666            case XmMAX_ON_LEFT:
667            case XmMAX_ON_TOP:
668                dragging = (x > sht) && (y > w->core.height - size - sht) &&
669                    (x < w->core.width - sht) && (y < w->core.height - sht);
670            }
671            break;
672    }
673    THIS.dragging = dragging;
674    THIS.oldx = x;
675    THIS.oldy = y;
676#undef THIS
677#endif
678}
679
680void
681GaugeDrag(Widget WXUNUSED(w), XEvent *WXUNUSED(e), String *WXUNUSED(args), Cardinal  *WXUNUSED(num_args))
682{
683    /* Commented out for a read-only gauge in wxWidgets */
684#if 0
685    XmGaugeWidget gw = (XmGaugeWidget)w;
686#define THIS gw->gauge
687    int sht, x, y, max, value;
688    float ratio, nratio, size, nsize, fvalue, delta;
689    XMotionEvent *event = (XMotionEvent *)e;
690
691    if( ! THIS.dragging) return;
692
693    x = event->x;
694    y = event->y;
695    sht = gw->primitive.shadow_thickness;
696
697    ratio = (float)THIS.value / (float)((float)THIS.maximum -
698        (float)THIS.minimum);
699    switch(THIS.orientation) {
700    case XmHORIZONTAL:
701        max = (w->core.width - 2 * sht);
702        size = (float)max * ratio;
703        delta =  (float)x - (float)THIS.oldx;
704        break;
705    case XmVERTICAL:
706        max = (w->core.height - 2 * sht);
707        size = (float) max * ratio;
708        delta =  (float)y - (float)THIS.oldy;
709        break;
710    }
711    switch(THIS.processingDirection) {
712    case XmMAX_ON_RIGHT:
713    case XmMAX_ON_BOTTOM:
714        nsize = size + delta;
715        break;
716    default:
717        nsize = size - delta;
718    }
719    if(nsize > (float)max) nsize = (float)max;
720    if(nsize < (float)0 ) nsize = (float)0;
721    nratio =  nsize / (float)max;
722
723    fvalue = (int)((float)THIS.maximum -
724        (float)THIS.minimum) * (float)nsize / (float)max;
725    value = wxRound(fvalue);
726
727    THIS.value = value;
728    THIS.oldx = x;
729    THIS.oldy = y;
730
731    /* clear old slider only if it was larger */
732    DrawSlider(gw, (nsize < size));
733
734    {
735        XmGaugeCallbackStruct call;
736
737        if(NULL  != THIS.dragCallback) {
738            call.reason = XmCR_DRAG;
739            call.event = e;
740            call.value = THIS.value;
741            XtCallCallbacks(w, XmNdragCallback, &call);
742        }
743    }
744#undef THIS
745#endif
746}
747
748
749void
750GaugeDrop(Widget WXUNUSED(w), XEvent *WXUNUSED(e), String *WXUNUSED(args), Cardinal  *WXUNUSED(num_args))
751{
752    /* Commented out for a read-only gauge in wxWidgets */
753#if 0
754    XmGaugeWidget gw = (XmGaugeWidget)w;
755#define THIS gw->gauge
756    if( ! THIS.dragging) return;
757
758    if(NULL  != THIS.valueChangedCallback) {
759        XmGaugeCallbackStruct call;
760        call.reason = XmCR_VALUE_CHANGED;
761        call.event = e;
762        call.value = THIS.value;
763        XtCallCallbacks(w, XmNvalueChangedCallback, &call);
764    }
765    THIS.dragging = False;
766#undef THIS
767#endif
768}
769
770void
771XmGaugeSetValue(Widget w, int value)
772{
773    XmGaugeWidget gw = (XmGaugeWidget)w;
774
775    gw->gauge.value = value;
776    DrawSlider(gw, True);
777    XFlush(XtDisplay(w));
778}
779
780int
781XmGaugeGetValue(Widget w)
782{
783    XmGaugeWidget gw = (XmGaugeWidget)w;
784
785    return gw->gauge.value;
786}
787
788#endif // !wxCHECK_MOTIF_VERSION( 2, 0 ) || wxCHECK_LESSTIF()
789