[MAXGUI] How to make a "Voting Box"?

BlitzMax Forums/BlitzMax Beginners Area/[MAXGUI] How to make a "Voting Box"?

Grisu(Posted 2006) [#1]
Hi!

How to make a resizable "Voting Box" with maxgui?
Many of them can be found on the net.
You can use the mouse to exacly point where the slider should go.

Example from Gamespot (Range 0-10):

Before:


Maxed:


Grisu


CS_TBL(Posted 2006) [#2]
uhm... "vo-ting-box" hmm...

I don't quite get the idea :P

Is it just some progressbar with the value next to it orso?


Haramanai(Posted 2006) [#3]
I thing that as you do not want to use the systems gui you must create your own slider and display it in a canvas.


Grisu(Posted 2006) [#4]
Yes, but its muti-colored and you can use the mouse inside the canvas window to select the slider position. Plus it has to work (be resized) when the app window is resized as well.

Example in action:
http://www.gamespot.com/pc/adventure/condemned/review.html?sid=6147467


Haramanai(Posted 2006) [#5]
The colors of the example it's not something to worry about.
Looks like that they are playing with the percent of Red and Green.
About the position and the value.
Let's say that chooseble area it's from X1 = 10 , Y1 = 10 to X2 = 60 and Y2 = 40. You will have to check if the given EventX() and EventY() are inside this box and then to find the position of the cursor and the value.
Value = ( (EventX() - X1) / (X2 - X1) ) * 10
Beware to use floats.


CS_TBL(Posted 2006) [#6]
Grisu: do you want a smooth bar or a bar split-up in fixed units (like in the example) ?


Grisu(Posted 2006) [#7]
Fixed units as it does look better..imho.
But everything that works is fine.

I tried using pre-made images, but the results weren't that great, especially because I need to resize the canvas.


CS_TBL(Posted 2006) [#8]
boo!

methods are self-explaining I think .. 'ave fun

EventSource() contains the unitbar
EventID() contains one of two possible ID's
EventData() contains the value

Const EVENT_UNITBARCHANGE:Int=  $13370400
Const EVENT_UNITBARCHANGED:Int= $13370401

Type TUnitbar

Rem
	TUnitbar
	
	CS_TBL
	
	Usage:
	
	MyUnitbar:TUnitbar=CreateUnitbar:TUnitbar(x,y,unitsize, units, height, parent)
	
EndRem
	Field canvas:TGadget
	Field r:Int[]
	Field g:Int[]
	Field b:Int[]
	Field unitwidth:Int
	Field units:Int
	Field value:Int
	Field number:Int
	
	Field lmd:Int
	
	Field NewEvent:TEvent=New TEvent
	
	Function eventhook:Object(id:Int,data:Object,context:Object)
		If TUnitbar(context) TUnitbar(context).ev TEvent(data);Return data	
	EndFunction
	
	Method New()
		AddHook EmitEventHook,eventhook,Self
	End Method
	
	Method Free()
		RemoveHook EmitEventHook,eventhook
		GCCollect()
	End Method
	
	Method ev(event:TEvent)
		If event.source=canvas
			If event.id=EVENT_GADGETPAINT update
			
			If event.id=EVENT_MOUSEDOWN
				lmd=1
			EndIf
			If event.id=EVENT_MOUSEUP
				lmd=0
				NewEvent.id=EVENT_UNITBARCHANGED
				NewEvent.source=Self
				NewEvent.data=value
				EmitEvent NewEvent
			EndIf
			If lmd
				value=_Limit((EventX()-(number*12))/unitwidth,0,units-1)
				update
				NewEvent.id=EVENT_UNITBARCHANGE
				NewEvent.source=Self
				NewEvent.data=value
				EmitEvent NewEvent
			EndIf
			If event.id=EVENT_MOUSEENTER
				ActivateGadget canvas
			EndIf
			
		EndIf
	End Method
	
	Method _Limit(v:Int,l:Int,h:Int)
		If v<l Return l
		If v>h Return h
		Return v
	End Method
	
	Method update()
		Local t:Int
		Local mini:Int
		Local gh:Int=GadgetHeight(canvas)
		SetGraphics CanvasGraphics(canvas)
			SetClsColor 0,0,0;Cls
			
			For t=1 To value
				SetColor r[t],g[t],b[t]
				DrawRect (number*12)+t*unitwidth+1,1,unitwidth-2,gh-1-1
			Next
			SetColor 255,255,255
			DrawText value,number*12/2-TextWidth(value)/2,gh/2-TextHeight(value)/2
		Flip
	End Method
	
	Method Set(v:Int)
		value=_Limit(v,0,units-1)
		update
	End Method
	
	Method SetGradient(startR:Int,startG:Int,startB:Int,deltaR:Int,deltaG:Int,deltaB:Int)
		Local t:Int
		For t=0 To units-1
			r[t]=_Limit(startR,0,255)
			g[t]=_Limit(startG,0,255)
			b[t]=_Limit(startB,0,255)
			startR:+deltaR
			startG:+deltaG
			startB:+deltaB
		Next
		update
	End Method
	
	Method Color(index:Int,_r:Int,_g:Int,_b:Int)
		index=_Limit(index,0,units-1)
		r[index]=_r
		g[index]=_g
		b[index]=_b
		update
	End Method
	
EndType

Function CreateUnitbar:TUnitbar(x:Int, y:Int, unitwidth:Int, units:Int, h:Int, parent:TGadget)
	Local a:TUnitbar=New TUnitbar
	Local tmp$=units
	a.number=Len(tmp)	
	a.canvas=CreateCanvas(x,y,unitwidth*units+a.number*12,h,parent)
	a.unitwidth=unitwidth
	a.units=units
	a.r=a.r[..units]
	a.g=a.g[..units]
	a.b=a.b[..units]
	For Local t:Int=0 To units-1
		a.r[t]=160
		a.g[t]=160
		a.b[t]=160
	Next
	Return a
End Function





' example from here:


Local window:TGadget=CreateWindow("(^_^( 'TUnitbar'     )o_O) 'O RLY?'",200,200,600,400)
Local unitbar1:TUnitbar=CreateUnitbar(20,16,5,64,32,window)
Local unitbar2:TUnitbar=CreateUnitbar(20,64,16,16,16,window)
Local unitbar3:TUnitbar=CreateUnitbar(20,128,3,128,24,window)

unitbar1.SetGradient 0,-128,255,4,4,0
'unitbar2.SetGradient 128,255,-255,-16,-8,64
unitbar2.Color 4,255,255,255
unitbar3.SetGradient 128,64,32,4,2,1

unitbar3.Set 25

Repeat
	WaitEvent()
	If EventID()=EVENT_WINDOWCLOSE End
	
	If EventSource()=unitbar1 Or EventSource()=unitbar2 Or EventSource()=unitbar3
		If EventID()=EVENT_UNITBARCHANGE DebugLog "changing.."
		If EventID()=EVENT_UNITBARCHANGED DebugLog "changed.."
		DebugLog "value: "+EventData()
		DebugLog "--------------------------------"
	EndIf
	
Forever



Grisu(Posted 2006) [#9]
Ouch, thanks A LOT.

You should put this in the code archives!
I need time to understand the code.

btw: how do I set the gradient so I get a "green end" like in my example?

Is there a way to "fix" the value_range (0 to 100), no matter how big the window is...?


CS_TBL(Posted 2006) [#10]
I need time to understand the code.

Actually you don't, it's written so it works more or less like the internal gadgets, via the Event system.

btw: how do I set the gradient so I get a "green end" like in my example?


The gradient method is a simple one, which only works with deltas, the rainbow gradient isn't -afaik- directly possible with this, that's why I added the Color method to set these colors yourself.


Is there a way to "fix" the value_range (0 to 100), no matter how big the window is...?

Not in this setup, that's why I asked for smooth vs fixed units.. ofcourse you could scale the output mathematically..

If you have 32 units then Eventdata() is between 0..31, if '31' is to become '100' then you do Eventdata()*100/31.
(edit) uhm.... yes.. that would display the wrong number in that unitbar, wouldn't it? ^_^


CS_TBL(Posted 2006) [#11]
yay for heavy clipping!

red > yello > green!
unitbar3.SetGradient 512,0,0,-4,4,0


Grisu(Posted 2006) [#12]
Sorry to get on your nerves... :(

1.
If I want to "disable" a unitbar:
So that it only displays a certain vaule, but the user isn't allowed to change that.

How would I do that? The unitbar keeps on getting updated.

2.
*solved*

3.
These hooks only work on windows, right?


Updated code:
' Unitbar Example 2
Const EVENT_UNITBARCHANGE:Int=  $13370400
Const EVENT_UNITBARCHANGED:Int= $13370401

Type TUnitbar

Rem
	TUnitbar
	CS_TBL
	
	Usage:
	MyUnitbar:TUnitbar=CreateUnitbar:TUnitbar(x,y,unitsize, units, height, parent)	
EndRem

	Field canvas:TGadget
	Field r:Int[]
	Field g:Int[]
	Field b:Int[]
	Field unitwidth:Int
	Field units:Int
	Field value:Int
	Field number:Int
	
	Field lmd:Int
	
	Field NewEvent:TEvent=New TEvent
	
	Function eventhook:Object(id:Int,data:Object,context:Object)
		If TUnitbar(context) TUnitbar(context).ev TEvent(data);Return data	
	EndFunction
	
	Method New()
		AddHook EmitEventHook,eventhook,Self
	End Method
	
	Method Free()
		RemoveHook EmitEventHook,eventhook
		GCCollect()
	End Method
	
	Method ev(event:TEvent)
		If event.source=canvas
			If event.id=EVENT_GADGETPAINT update
			
			If event.id=EVENT_MOUSEDOWN
				lmd=1
			EndIf
			If event.id=EVENT_MOUSEUP
				lmd=0
				NewEvent.id=EVENT_UNITBARCHANGED
				NewEvent.source=Self
				NewEvent.data=value
				EmitEvent NewEvent
			EndIf
			If lmd
				value=_Limit((EventX()-(number*12))/unitwidth,0,units-1)
				update
				NewEvent.id=EVENT_UNITBARCHANGE
				NewEvent.source=Self
				NewEvent.data=value
				EmitEvent NewEvent
			EndIf
			If event.id=EVENT_MOUSEENTER
				ActivateGadget canvas
			EndIf
			
		EndIf
	End Method
	
	Method _Limit(v:Int,l:Int,h:Int)
		If v<l Return l
		If v>h Return h
		Return v
	End Method
	
	Method update()
		Local t:Int
		Local mini:Int
		Local gh:Int=GadgetHeight(canvas)
		    SetGraphics CanvasGraphics(canvas)
 		    SetClsColor 0,0,0;Cls
	        SetColor 80,80,80		
            For t=1 To units
				DrawRect (number*12)+t*unitwidth+1,1,unitwidth-2,gh-1-1
			Next
			For t=1 To value
				SetColor r[t],g[t],b[t]
				DrawRect (number*12)+t*unitwidth+1,1,unitwidth-2,gh-1-1
			Next
			SetColor 255,255,255
			DrawText value,number*12/2-TextWidth(value)/2,gh/2-TextHeight(value)/2
		Flip
	End Method
	
	Method Set(v:Int)
		value=_Limit(v,0,units-1)
		update
	End Method
	
	Method SetGradient(startR:Int,startG:Int,startB:Int,deltaR:Int,deltaG:Int,deltaB:Int)
		Local t:Int
		For t=0 To units-1
			r[t]=_Limit(startR,0,255)
			g[t]=_Limit(startG,0,255)
			b[t]=_Limit(startB,0,255)
			startR:+deltaR
			startG:+deltaG
			startB:+deltaB
		Next
		update
	End Method
	
	Method Color(index:Int,_r:Int,_g:Int,_b:Int)
		index=_Limit(index,0,units-1)
		r[index]=_r
		g[index]=_g
		b[index]=_b
		update
	End Method
	
EndType

Function CreateUnitbar:TUnitbar(x:Int, y:Int, unitwidth:Int, units:Int, h:Int, parent:TGadget)
	Local a:TUnitbar=New TUnitbar
	Local tmp$=units
	a.number=Len(tmp)	
	a.canvas=CreateCanvas(x,y,unitwidth*units+a.number*12,h,parent)
	a.unitwidth=unitwidth
	a.units=units
	a.r=a.r[..units]
	a.g=a.g[..units]
	a.b=a.b[..units]
	For Local t:Int=0 To units-1
		a.r[t]=160
		a.g[t]=160
		a.b[t]=160
	Next
	Return a
End Function


' Example from here:
Local window:TGadget=CreateWindow("TUnitbar Example",200,200,600,400)
Local unitbar1:TUnitbar=CreateUnitbar(20,16,5,101,32,window)
Local unitbar2:TUnitbar=CreateUnitbar(20,64,10,11,16,window)
Local unitbar3:TUnitbar=CreateUnitbar(20,128,3,101,24,window)

unitbar1.SetGradient 450,0,0,-3,4,0 
unitbar2.SetGradient 400,0,0,-35,4,0 
unitbar3.SetGradient 450,0,0,-3,4,0 

unitbar1.Set 5
unitbar2.Set 2
unitbar3.Set 35

Repeat
	WaitEvent()
	If EventID()=EVENT_WINDOWCLOSE End
	
	If EventSource()=unitbar1 Or EventSource()=unitbar2 Or EventSource()=unitbar3
		If EventID()=EVENT_UNITBARCHANGE DebugLog "changing.."
		If EventID()=EVENT_UNITBARCHANGED DebugLog "changed.."
		DebugLog "value: "+EventData()
		DebugLog "--------------------------------"
	EndIf
	
Forever



Grisu(Posted 2006) [#13]
*some hours later*

After several attempts I only found a workaround by setting a gobal var "DrawUnitbar" to disable the unitbar output...

	Method update()
		Local t:Int
		Local mini:Int
		Local gh:Int=GadgetHeight(canvas)
		    SetGraphics CanvasGraphics(canvas)
			SetClsColor 0,0,0;Cls

            If DrawUnitbar=True Then ' Draw an enabled Unitbar
 
            SetColor 100,100,100 
			For t=value To units
				DrawRect (number*12)+t*unitwidth+1,1,unitwidth-2,gh-1-1
			Next
						
			For t=1 To value
				SetColor r[t],g[t],b[t]
				DrawRect (number*12)+t*unitwidth+1,1,unitwidth-2,gh-1-1
			Next

			SetColor 255,255,255
			DrawText value,number*12/2-TextWidth(value)/2,gh/2-TextHeight(value)/2

            Else ' Draw an empty Unitbar

            SetColor 100,100,100 
			For t=1 To units
				DrawRect (number*12)+t*unitwidth+1,1,unitwidth-2,gh-1-1
			Next
					
			value=0 				
			SetColor 255,255,255
			DrawText value,number*12/2-TextWidth(value)/2,gh/2-TextHeight(value)/2

            EndIf 
			Flip
	End Method


The only thing that is breaking my head now is how to resize the unitbar width on runtime? = Setgadgetshape


CS_TBL(Posted 2006) [#14]
The 'gadget' you'll use is in fact the canvas.

Don't expect 'everything' from these custom gadgets.

Also, globals are nasty, imho.

It's better to have a field with an activity state so you could set this per unitbar. If you want all unitbars to change at once you could try to make each unitbar react on an event that triggers activity/unactivity.


Grisu(Posted 2006) [#15]
Yeah I know its not the best way of coding!
Will try again... at least its working.. :)

Any hint how I can "enlarge" the unitbar y-wise when the app windowsize is changed?!?

See my app:
http://grisu.roxr.com/dfa.zip (2 MB)


CS_TBL(Posted 2006) [#16]
	Method Resizeheight(h:Int)
		SetGadgetShape canvas,GadgetX(canvas),GadgetY(canvas),GadgetWidth(canvas),h
		update
	End Method


Bugs here in 1.16 ... maybe it works @ 1.18 .. dunno. For some reason it doesn't draw anything into the newly acquired area. Anyone an idea?


Grisu(Posted 2006) [#17]
Yepp, I have.

The only thing one can do this is to initially create a "maxed" canavas. And then resize it "down" to the size used (Setgadgetshape to the createcanvas state).
This is the only way you can use Setgadgetshape as I have found out so far.

I do the same with the image canvas I use in my app.


Grisu(Posted 2006) [#18]
Haven't be successfull on the the custom canvas height by now... :(

But I have changed the type to have 2 more states, i.e: disabled and hidden.

Type TUnitbar

Rem
	TUnitbar
	CS_TBL, Grisu
	
	Last modified: 15.04.06
	
	Usage:	
	MyUnitbar:TUnitbar=CreateUnitbar:TUnitbar(x,y,unitsize, units, height, hidden, disabled, parent)
	
EndRem
	Field canvas:TGadget
	Field r:Int[]
	Field g:Int[]
	Field b:Int[]
	Field unitwidth:Int
	Field units:Int
	Field value:Int
	Field number:Int
	Field hidden  : Byte ' Unitbar is invisible
	Field disabled: Byte ' Unitbar is diabled
	
	Field lmd:Int
	
	Field NewEvent:TEvent=New TEvent
	
	Function eventhook:Object(id:Int,data:Object,context:Object)
		If TUnitbar(context) TUnitbar(context).ev TEvent(data);Return data	
	EndFunction
	
	Method New()
		AddHook EmitEventHook,eventhook,Self
	End Method
	
	Method Free()
		RemoveHook EmitEventHook,eventhook
		GCCollect()
	End Method

	Method Resizeheight(h:Int)
	SetGadgetShape canvas,GadgetX(canvas),GadgetY(canvas),GadgetWidth(canvas),h
	update
	End Method	

	Method ev(event:TEvent)
		If event.source=canvas
			If event.id=EVENT_GADGETPAINT update
			
			If event.id=EVENT_MOUSEDOWN
				lmd=1
			EndIf
			If event.id=EVENT_MOUSEUP
				lmd=0
				NewEvent.id=EVENT_UNITBARCHANGED
				NewEvent.source=Self
				NewEvent.data=value
				EmitEvent NewEvent
			EndIf
			If lmd
				value=_Limit((EventX()-(number*12))/unitwidth,0,units-1)
				update
				NewEvent.id=EVENT_UNITBARCHANGE
				NewEvent.source=Self
				NewEvent.data=value
				EmitEvent NewEvent
			EndIf
			If event.id=EVENT_MOUSEENTER
				ActivateGadget canvas
			EndIf
			
		EndIf
	End Method
	
	Method _Limit(v:Int,l:Int,h:Int)
		If v<l Return l
		If v>h Return h
		Return v
	End Method
	
	Method update()
		Local t:Int
		Local mini:Int
		Local gh:Int=GadgetHeight(canvas)

            If hidden=False Then ' Unitbar hidden completely?

            ShowGadget (canvas) 

		    SetGraphics CanvasGraphics(canvas)
			SetClsColor 0,0,0;Cls
            
            If disabled=False Then ' Draw an enabled Unitbar only
 
            SetColor 100,100,100 
			For t=value To units
				DrawRect (number*12)+t*unitwidth+1,1,unitwidth-2,gh-1-1
			Next
						
			For t=1 To value
				SetColor r[t],g[t],b[t]
				DrawRect (number*12)+t*unitwidth+1,1,unitwidth-2,gh-1-1
			Next

			SetColor 255,255,255
			DrawText value,number*12/2-TextWidth(value)/2,gh/2-TextHeight(value)/2

            Else ' Draw an empty Unitbar

            SetColor 100,100,100 
			For t=1 To units
				DrawRect (number*12)+t*unitwidth+1,1,unitwidth-2,gh-1-1
			Next
					
			value=0 				
			SetColor 255,255,255
			DrawText value,number*12/2-TextWidth(value)/2,gh/2-TextHeight(value)/2

            EndIf ' Disabled

            Else
             HideGadget (canvas)
            EndIf ' Hidden
			Flip
	End Method
	
	Method Set(v:Int)
		value=_Limit(v,0,units-1)
		update
	End Method
	
	Method SetGradient(startR:Int,startG:Int,startB:Int,deltaR:Int,deltaG:Int,deltaB:Int)
		Local t:Int
		For t=0 To units-1
			r[t]=_Limit(startR,0,255)
			g[t]=_Limit(startG,0,255)
			b[t]=_Limit(startB,0,255)
			startR:+deltaR
			startG:+deltaG
			startB:+deltaB
		Next
		update
	End Method
	
	Method Color(index:Int,_r:Int,_g:Int,_b:Int)
		index=_Limit(index,0,units-1)
		r[index]=_r
		g[index]=_g
		b[index]=_b
		update
	End Method
	
EndType

Function CreateUnitbar:TUnitbar(x:Int, y:Int, unitwidth:Int, units:Int, h:Int, hidden:Byte, disabled:Byte, parent:TGadget)
	Local a:TUnitbar=New TUnitbar
	Local tmp$=units
	a.number=Len(tmp)	
	a.canvas=CreateCanvas(x,y,1+unitwidth*units+a.number*12,h,parent)
	a.unitwidth=unitwidth
	a.units=units
	a.r=a.r[..units]
	a.g=a.g[..units]
	a.b=a.b[..units]
	For Local t:Int=0 To units-1
		a.r[t]=160
		a.g[t]=160
		a.b[t]=160
	Next
	a.hidden=hidden
	a.disabled=disabled
	Return a
End Function



CS_TBL(Posted 2006) [#19]
hm.. you need more practice with coding :P

Don't do the showgadget/hidegadget in that update method, make seperate methods for it, remember that the update method is performed everytime a canvas event happens, including hoovering with the mouse on it..


Grisu(Posted 2006) [#20]
This whole method stuff is new to me.

	Method Hide()
    	HideGadget (canvas)
        hidden=True 
    End Method 

    Method Show()
        ShowGadget (canvas) 
        hidden=False 
    End Method 

	Method update()
		Local t:Int
		Local mini:Int
		Local gh:Int=GadgetHeight(canvas)

            If hidden=False Then ' Unitbar hidden completely?

		    SetGraphics CanvasGraphics(canvas)
			SetClsColor 0,0,0;Cls
            
            If disabled=False Then ' Draw an enabled Unitbar only
 
            SetColor 100,100,100 
			For t=value To units
				DrawRect (number*12)+t*unitwidth+1,1,unitwidth-2,gh-1-1
			Next
						
			For t=1 To value
				SetColor r[t],g[t],b[t]
				DrawRect (number*12)+t*unitwidth+1,1,unitwidth-2,gh-1-1
			Next

			SetColor 255,255,255
			DrawText value,number*12/2-TextWidth(value)/2,gh/2-TextHeight(value)/2

            Else ' Draw an empty Unitbar

            SetColor 100,100,100 
			For t=1 To units
				DrawRect (number*12)+t*unitwidth+1,1,unitwidth-2,gh-1-1
			Next
					
			value=0 				
			SetColor 255,255,255
			DrawText value,number*12/2-TextWidth(value)/2,gh/2-TextHeight(value)/2

            EndIf ' Disabled

            EndIf ' Hidden
			Flip
	End Method


Better this way?!?^^

This canvas stuff drives me crazy. Why can't one simply resize it. Is it a bug or has it to be that way? 1.18


Grisu(Posted 2006) [#21]
Ok, I added a new method called "MoveTo":

Method MoveTo(x,y:Int)
	SetGadgetShape canvas,x,y,GadgetWidth(canvas),GadgetHeight(canvas)
	Update
End Method	

I'm sure you can't find any tweaks for this one... ;)))))))))))))


Grisu(Posted 2006) [#22]
I'm a genius... :))))))))))))))))))))))))))))))))))))))))))))

Brute force is with me.... muhahahahahaha
	Method Resizeheight(h:Int, parent:TGadget)
		Local gx:Int=GadgetX(canvas)
		Local gy:Int=GadgetY(canvas)
		Local gw:Int=GadgetWidth(canvas)

                FreeGadget(canvas)
                GCCollect()
                canvas=CreateCanvas(gx,gy,gw,h,parent)
		Update
	End Method	



Grisu(Posted 2006) [#23]
Resizing the Unitbar works now in width terms as well.
But there is a problem with ints / floats so it isn't
100% nice looking in all situations.

Do you have a better idea for Method ResizeFull?

Complete updated source:

Type TUnitbar

Rem
	TUnitbar: 
	CS_TBL, Grisu
	
	Version:  
	1.0.2 [16.04.06] 
	
	Usage:	
	MyUnitbar:TUnitbar=CreateUnitbar:TUnitbar(x,y,unitsize, units, height, hidden, disabled, parent)
	
EndRem
	Field canvas:TGadget
	Field r:Int[]
	Field g:Int[]
	Field b:Int[]
	Field unitwidth:Float
	Field units:Int
	Field value:Int
	Field number:Int
	Field hidden  : Byte ' Unitbar is invisible
	Field disabled: Byte ' Unitbar is diabled
	
	Field lmd:Int
	
	Field NewEvent:TEvent=New TEvent
	
	Function eventhook:Object(id:Int,data:Object,context:Object)
		If TUnitbar(context) TUnitbar(context).ev TEvent(data);Return data	
	EndFunction
	
	Method New()
		AddHook EmitEventHook,eventhook,Self
	End Method
	
	Method Free()
		RemoveHook EmitEventHook,eventhook
		GCCollect()
	End Method

	Method ResizeHeight(h:Int, parent:TGadget) ' Resize Unitbarheight
		Local gx:Int=GadgetX(canvas)
		Local gy:Int=GadgetY(canvas)
		Local gw:Int=GadgetWidth(canvas)

        FreeGadget(canvas)
        GCCollect()
        canvas=CreateCanvas(gx,gy,gw,h,parent)
		Update
	End Method	

	Method ResizeFull(h,w:Int, parent:TGadget) ' Resize Unitbar both w + h wise, needs tweaking
		Local gx:Int=GadgetX(canvas)
		Local gy:Int=GadgetY(canvas)
		Local gw:Int=GadgetWidth(canvas)
        Local bakunitwidth:Float=unitwidth
        Local bakunits:Int=units
        Local baknumber:Int=number*12

        FreeGadget(canvas)
        GCCollect()
        
       ' unitwidth=bakunitwidth+(w-gw)/bakunits
        unitwidth=(w-baknumber)/bakunits

        canvas=CreateCanvas(gx,gy,w,h,parent)
		Update
	End Method
	
	Method ev(event:TEvent)
		If event.source=canvas
			If event.id=EVENT_GADGETPAINT Then Update
			
			If event.id=EVENT_MOUSEDOWN
				lmd=1
			EndIf
			If event.id=EVENT_MOUSEUP
				lmd=0
				NewEvent.id=EVENT_UNITBARCHANGED
				NewEvent.source=Self
				NewEvent.data=value
				EmitEvent NewEvent
			EndIf
			If lmd
				value=_Limit((EventX()-(number*12))/unitwidth,0,units-1)
				Update
				NewEvent.id=EVENT_UNITBARCHANGE
				NewEvent.source=Self
				NewEvent.data=value
				EmitEvent NewEvent
			EndIf
			If event.id=EVENT_MOUSEENTER
				ActivateGadget canvas
			EndIf
			
		EndIf
	End Method

	Method _Limit(v:Int,l:Int,h:Int)
		If v<l Return l
		If v>h Return h
		Return v
	End Method
	
	Method MoveTo(x,y:Int)  ' Move the Unitbar 
		SetGadgetShape canvas,x,y,GadgetWidth(canvas),GadgetHeight(canvas)
		Update
	End Method	

	Method Hide()   		' Hide the Unitbar
    	HideGadget (canvas)
        hidden=True 
    End Method 

    Method Show()   		' Show the Unitbar
        ShowGadget (canvas) 
        hidden=False 
    End Method 

	Method Update() 		' Update the Unitbar

        If hidden=False Then ' Unitbar hidden completely?

		Local t:Int
		Local mini:Int
		Local gh:Int=GadgetHeight(canvas)

		    SetGraphics CanvasGraphics(canvas)
			SetClsColor 0,0,0;Cls
            
            If disabled=False Then ' Draw an enabled Unitbar only
 
            SetColor 100,100,100 
			For t=value To units-2
				DrawRect (number*12)+t*unitwidth+1,1,unitwidth-2,gh-1-1
			Next
						
			For t=0 To value-1
				SetColor r[t],g[t],b[t]
				DrawRect (number*12)+t*unitwidth+1,1,unitwidth-2,gh-1-1
			Next

			SetColor 255,255,255
			DrawText value,number*12/2-TextWidth(value)/2,gh/2-TextHeight(value)/2

            Else ' Draw an empty Unitbar

            SetColor 100,100,100 
			For t=0 To units-1
				DrawRect (number*12)+t*unitwidth+1,1,unitwidth-2,gh-1-1
			Next
					
			value=0 				
			SetColor 255,255,255
			DrawText value,number*12/2-TextWidth(value)/2,gh/2-TextHeight(value)/2

            EndIf ' Disabled

			Flip

		EndIf ' Hidden
			
	End Method
	
	Method Set(v:Int)
		value=_Limit(v,0,units-1)
		Update
	End Method
	
	Method SetGradient(startR:Int,startG:Int,startB:Int,deltaR:Int,deltaG:Int,deltaB:Int)
		Local t:Int
		For t=0 To units-1
			r[t]=_Limit(startR,0,255)
			g[t]=_Limit(startG,0,255)
			b[t]=_Limit(startB,0,255)
			startR:+deltaR
			startG:+deltaG
			startB:+deltaB
		Next
		Update
	End Method
	
	Method Color(index:Int,_r:Int,_g:Int,_b:Int)
		index=_Limit(index,0,units-1)
		r[index]=_r
		g[index]=_g
		b[index]=_b
		Update
	End Method
	
EndType

Function CreateUnitbar:TUnitbar(x:Int, y:Int, unitwidth:Int, units:Int, h:Int, hidden:Byte, disabled:Byte, parent:TGadget)
	Local a:TUnitbar=New TUnitbar
	Local tmp$=units
	a.number=Len(tmp)	
	a.canvas=CreateCanvas(x,y,unitwidth*units+a.number*12,h,parent)
	a.unitwidth=unitwidth
	a.units=units
	a.r=a.r[..units]
	a.g=a.g[..units]
	a.b=a.b[..units]
	For Local t:Int=0 To units-1
		a.r[t]=160
		a.g[t]=160
		a.b[t]=160
	Next
	a.hidden=hidden
	a.disabled=disabled
	Return a
End Function