allows for negative and floating point
windows only.... needs to be modified quite a bit for the mac
windows only.... needs to be modified quite a bit for the mac
SuperStrict '----------------------------------------------------------------------------------------------------- ' Example program '----------------------------------------------------------------------------------------------------- Local Window:TGadget=CreateWindow("My Window",0,0,240,240,Null,WINDOW_TITLEBAR) ' default spinner (0 to 10 step 1) with trackbar CreateSpinner(15,15,65,30,Window,SLIDER_TRACKBAR) ' spinner (-10 to 10 step .1) Local spinner:TSpinner = CreateSpinner(15,65,65,20,Window) SetSpinnerRange spinner,-10,10 SetSpinnerPrecision spinner,.1 SetSpinnerValue spinner,-5 ' % spinner (0 to 1 step .01) Local spinner2:TSpinner = CreateSpinner(15,100,65,20,Window) SetSpinnerRange spinner2,0,1 SetSpinnerPrecision spinner2,.01 SetSpinnerValue spinner2,.5 While WaitEvent() Local event:TEvent = CurrentEvent Print event.ToString() Select event.id Case EVENT_GADGETACTION Print "GadgetText: " + GadgetText(TGadget(event.source)) + "~tEventExtra: " + String(event.extra) Case EVENT_WINDOWCLOSE End End Select Wend '----------------------------------------------------------------------------------------------------- ' TSpinner Gadget ' by dmaz '----------------------------------------------------------------------------------------------------- Function CreateSpinner:TSpinner( x:Int, y:Int, w:Int, h:Int, group:TGadget, style:Int=0 ) Return New TSpinner.Create(x,y,w,h,group,style) End Function Function SetSpinnerRange( spinner:TSpinner, low:Double, high:Double ) spinner.SetSpinnerRange low,high End Function Function SetSpinnerPrecision( spinner:TSpinner, precision:Double ) spinner.SetSpinnerPrecision precision End Function Function SetSpinnerValue( spinner:TSpinner, value:Double ) spinner.SetSpinnerValue value End Function Type TSpinner Extends TProxyGadget Field panel :TGadget Field textField:TGadget Field stepper :TGadget Field trackbar :TGadget Field range :Double Field value :Double = 0.0 Field low :Double = 0.0 Field high :Double = 10.0 Field precision:Double = 1.0 Method New() AddHook EmitEventHook,MyEventHook,Self End Method Method Create:TSpinner( x:Int, y:Int, w:Int, h:Int, group:TGadget, style:Int=0 ) panel = CreatePanel(x,y,w,h,group,PANEL_BORDER) If style & SLIDER_TRACKBAR stepper = CreateSlider(w-h+14,0,h-18,h-14,panel,SLIDER_STEPPER) textField = CreateTextField(-2,-2,w-h+18,h-10,panel) trackbar = CreateSlider(-2,h-12,w+1,10,panel,SLIDER_HORIZONTAL|SLIDER_TRACKBAR) Else stepper = CreateSlider(w-h+4,0,h-8,h-4,panel,SLIDER_STEPPER) textField = CreateTextField(-2,-2,w-h+8,h,panel) EndIf SetGadgetFilter textField,NumFilter SetProxy textField SetSpinnerRange low,high SetSpinnerPrecision precision SetSpinnerValue low Return Self End Method Method Free() RemoveHook EmitEventHook,MyEventHook,Self 'textField is freed in super If trackbar Then FreeGadget trackbar FreeGadget stepper FreeGadget panel Super.Free End Method Method SetSpinnerRange( low:Double, high:Double ) Self.low = low Self.high = high range = Round((high-low)/precision) SetSpinnerValue low SetSliderRange stepper,0,range SetSliderValue stepper,0 If trackbar SetSliderRange trackbar,0,range SetSliderValue trackbar,0 EndIf End Method Method SetSpinnerPrecision( precision:Double ) Self.precision = precision range = Round((high-low)/precision) SetSliderRange stepper,0,range If trackbar Then SetSliderRange trackbar,0,range End Method Method SetSpinnerValue:Int( value:Double ) Self.value = Min(Max(low,value),high) SetSliderValue stepper,Round((Self.value-low)/precision) If trackbar Then SetSliderValue trackbar,Round((Self.value-low)/precision) SetGadgetText Self,PrettyFloat(Self.value) If value < low Or value > high Then Return False Else Return True End Method Method GetSpinnerValue:String() Return PrettyFloat(value) End Method '------------------------------------------------------------------------------------------------ Function MyEventHook:Object( id:Int, data:Object, context:Object ) If TSpinner(context) Then data=TSpinner(context).MyEvents(TEvent(data)) Return data End Function Method MyEvents:TEvent( event:TEvent ) If event Select event.id Case EVENT_GADGETACTION If event.source = stepper Or event.source = trackbar ActivateGadget TGadget(event.source) If low+(event.data/precision) <> value SetSpinnerValue low+(event.data*precision) EmitEvent CreateEvent(EVENT_GADGETACTION,Self,0,0,0,0,GetSpinnerValue()) EndIf event = Null EndIf Case EVENT_GADGETLOSTFOCUS If event.source = Self If GadgetText(Self).ToDouble() <> value SetSpinnerValue GadgetText(Self).ToDouble() EmitEvent CreateEvent(EVENT_GADGETACTION,Self,0,0,0,0,GetSpinnerValue()) EndIf EndIf End Select EndIf Return event End Method '------------------------------------------------------------------------------------------------ Function NumFilter:Int(event:TEvent, context:Object) If event.ID = EVENT_KEYCHAR If event.data = KEY_BACKSPACE Then Return True If event.data = 47 Then Return False If event.data < 45 Or event.data > 57 Then Return False EndIf Return True End Function Function PrettyFloat:String( value:Double ) 'by grable Extern "C" Function modf:Double( value:Double, intpart:Double Var) Function snprintf_i:Int( buf:Byte Ptr, szbuf:Int, fmtstr$z, val:Int) = "snprintf" Function snprintf_f:Int( buf:Byte Ptr, szbuf:Int, fmtstr$z, val:Double) = "snprintf" EndExtern Local i:Double Local buf:Byte[32] Local l:Int ' check for whole number If modf( value, i) = 0.0 Then l = snprintf_i( buf, SizeOf(buf), "%d", i) Return String.FromBytes( buf, l) Else ' eliminate ending zeros except the one after "." l = snprintf_f( buf, SizeOf(buf), "%f", value) While (l > 0) And (buf[l-1] = Asc("0")) And (buf[l-2] <> Asc(".")) l :- 1 Wend ' terminate it, just in case buf[l+1] = 0 Return String.FromBytes( buf, l) EndIf EndFunction Function Round:Double(x:Double) Return Int(x + (Sgn(x) * 0.5)) End Function End Type