Another spinner gadget
BlitzMax Forums/MaxGUI Module/Another spinner gadget
| ||
To avoid floating-point errors this always uses integers. The SPINNER_DECIMAL style will use increments of 0.1. However, spinner values will still be stored as integers. The SPINNER_WRAP flag does not currently work. The float handling works perfectly in this, unlike some other implementations I have seen. Function CreateSpinner:TSpinner( x:Int, y:Int, w:Int, h:Int, group:TGadget, style:Int=0 ) Return TSpinner.Create(x,y,w,h,group,style) EndFunction Function SetSpinnerRange( spinner:TSpinner, low:Float, high:Float ) spinner.SetRange low,high End Function Function SetSpinnerValue( spinner:TSpinner, value:Int ) spinner.SetValue_ value EndFunction Function SpinnerValue:Int( spinner:TSpinner) Return spinner.getvalue() EndFunction Const SPINNER_DECIMAL=1 Const SPINNER_WRAP=2 Type TSpinner Extends TProxyGadget Field panel :TGadget Field textField:TGadget Field stepper:TGadget Field trackbar:TGadget Field range =10 Field precision#=1.0 Field value Field low=0,high=9 Function Create:TSpinner( x:Int, y:Int, w:Int, h:Int, group:TGadget, style:Int=0 ) Local spinner:TSpinner=New TSpinner spinner.panel = CreatePanel(x,y,w,h,group,PANEL_BORDER) spinner.stepper = CreateSlider(w-h+4,0,h-8,h-4,spinner.panel,SLIDER_STEPPER) spinner.textField = CreateTextField(-2,-2,w-h+8,h,spinner.panel) spinner.setrange spinner.low,spinner.high SetGadgetFilter spinner.textField,NumFilter spinner.SetProxy spinner.textField spinner.style=style AddHook EmitEventHook,SpinnerHook,spinner Return spinner EndFunction Method Free() RemoveHook EmitEventHook,SpinnerHook,Self 'textField is freed in super If stepper FreeGadget stepper If panel FreeGadget panel stepper=Null panel=Null Super.Free End Method Method SetRange( lo, hi) low=lo high=hi range=high-low+1 SetSliderRange stepper,0,range-1 SetValue low EndMethod Method FixValue:Int(i) 'If (SPINNER_WRAP & style) 'If i<low Notify i+", "+(( (i-low) Mod range )+low) ' i=( (i-low) Mod range )+low 'Else i=Max(i,low) i=Min(i,high) 'EndIf Return i EndMethod Method SetValue_( i,updatetext=1) value=FixValue(i) If SliderValue(stepper)<>value-low SetSliderValue stepper,value-low If updatetext If SPINNER_DECIMAL & style SetGadgetText textfield,String(PrettyFloat(value/10.0)) Else SetGadgetText textfield,String(value) EndIf EndIf EndMethod Method GetValue:Int() Return value EndMethod Function SpinnerHook:Object( id:Int, data:Object, context:Object ) Local spinner:TSpinner Local event:TEvent event=TEvent(data) If event spinner=TSpinner(context) If spinner Return spinner.HandleEvents(event) EndIf Return data EndFunction Method HandleEvents:TEvent( event:TEvent ) Select event.id Case EVENT_GADGETACTION If event.source = stepper If FixValue(event.data+low)<>value SetValue_ event.data+low,1 EmitEvent CreateEvent(EVENT_GADGETACTION,Self,event.data) SendMessageA QueryGadget(textfield,QUERY_HWND),177,0,-1 ActivateGadget textfield Return EndIf EndIf If event.source = Self Local i If SPINNER_DECIMAL & style i=Round(Float(TextFieldText(textfield))*10.0) Else i=Int(TextFieldText(textfield)) EndIf Local newvalue=FixValue(i) If newvalue<>value SetValue_ newvalue,0 EmitEvent CreateEvent(EVENT_GADGETACTION,Self) Return EndIf EndIf EndSelect Return event EndMethod Function NumFilter:Int(event:TEvent, context:Object) If event.ID = EVENT_KEYCHAR If event.data = KEY_BACKSPACE Return 1 If event.data = 47 Return If event.data < 45 Or event.data > 57 Return EndIf Return 1 End Function Function PrettyFloat:String(value:Float,places=1) Local s$ value=value*(10.0^places) s=Round(value) Local i$=Int(Left(s,s.length-1)) Return i+"."+Right(s,1) EndFunction EndType |
| ||
nevermind. |
| ||
Add thisMethod SetEnabled(_state:Int=True) If _state=False DisableGadget stepper DisableGadget panel Else EnableGadget stepper EnableGadget panel End If Super.setenabled(_state) End Method to make the Spinner gadget acts like standard MaxGUI gadgets. This means you can use DisableGadget myspinner:tspinner EnableGadget myspinner:tspinner to disable properly the gadget (spinner+textfied). And replace the method SetValue_ with this one Method SetValue_( i,updatetext=1) value=FixValue(i) If SliderValue(stepper)<>value-low SetSliderValue stepper,value-low If updatetext If SPINNER_DECIMAL & style SetGadgetText textfield,String(PrettyFloat(value/10.0)) Else SetGadgetText textfield,String(value) EndIf If value<0 SetGadgetColor textfield,220,20,20 Else SetGadgetColor textfield,255,255,255 Local temp$=" "+TextFieldText(textfield) temp=Right(temp,16+(Len(temp)>3)) SetGadgetText textfield,temp EndIf endMethod to have a 'visual' response on negative value: this could be useful. And I added an 'hack' for the right alignment, but I cant' guarantee if it will work well. |