events

BlitzMax Forums/BlitzMax Beginners Area/events

CS_TBL(Posted 2005) [#1]
I'm trying to figure out things like eventhooks 'n stuff.. can someone explain it a bit, for example by adding such a mechanism to the small example-source below?
So, the idea is that I don't need that t.ev in the mainloop anymore, everything should become transparent, just like the standard built-in GUI objects..
It should also emit some new events I could read out with EventSource()..

MaxGUI really needs more examples.., as good as B+ was, as minimalistic/sober MaxGUI is .. ._.




degac(Posted 2005) [#2]
Try this...
Strict

Type test

	Field canvas:TGadget
	
	Method ev(event:TEvent)
		
		Select event.ID
			Case EVENT_MOUSEENTER
			 	update 1
		
			Case EVENT_MOUSELEAVE,EVENT_GADGETPAINT
				update
		End Select
		
	End Method

	Method update(state:Byte=0)
		SetGraphics CanvasGraphics(canvas)
			SetClsColor 128+state*127,128+state*127,128+state*127
			Cls
		Flip
	End Method
	
	Function create:test(parent:tgadget)
		Local a:test=New test
	a.canvas=CreateCanvas(10,10,20,20,parent)
	Return a
	End Function 

End Type


Local win:TGadget=CreateWindow("o_O",0,0,400,120)

Global t:test=test.create(win)

AddHook EmitEventHook,EventHook

Repeat
	WaitEvent()
	't.ev
	If EventID()=EVENT_WINDOWCLOSE End
Forever

Function EventHook:Object(iId,tData:Object,tContext:Object)
'event is in TDATA
'source --> event.Source (method)
'event ID (EVENT_MOUSEENTER...) --> event.ID

    Local Event:TEvent=TEvent(tData)

	Print "Event : "+event.tostring()
	Print "Source: "+String(event.source)

    Select Event.Source
      Case t.canvas
		t.ev(event)
		Print "event catched..."
        Return Null      
		Default
		Print "No event..."
      End Select
    Return Event         'Event pass through (nothing thats been captured)
End Function

I modified some thing to reach the goal...I extended your TEST type to catch the event, the EventHook function is from this forum - I don't remember who wrote it.


degac(Posted 2005) [#3]
Strict

Type test

	Field canvas:TGadget
	
	Method ev(event:TEvent)
		
		Select event.ID
			Case EVENT_MOUSEENTER
			 	update 1
		
			Case EVENT_MOUSELEAVE,EVENT_GADGETPAINT
				update
		End Select
		
	End Method

	Method update(state:Byte=0)
		SetGraphics CanvasGraphics(canvas)
			SetClsColor 128+state*127,128+state*127,128+state*127
			Cls
		Flip
	End Method
	
	Function create:test(parent:tgadget)
		Local a:test=New test
	a.canvas=CreateCanvas(10,10,20,20,parent)
	
	AddHook EmitEventHook,a.EventHook
	Return a
	End Function 
	
	Function EventHook:Object(iId,tData:Object,tContext:Object)
'event is in TDATA
'source --> event.Source (method)



    Local Event:TEvent=TEvent(tData)

	Print "Event : "+event.tostring()
	Print "Source: "+String(event.source)

    Select Event.Source
      Case t.canvas
		t.ev(event)
		Print "event catched..."
        Return Null      
		Default
		Print "No event..."
      End Select
    Return Event         'Event pass through (nothing thats been captured)
End Function
End Type


Local win:TGadget=CreateWindow("o_O",0,0,400,120)
Global t:test=test.create(win)

'AddHook EmitEventHook,t.EventHook

Repeat
	WaitEvent()
	't.ev
	If EventID()=EVENT_WINDOWCLOSE End
Forever

Just now I realized that I can 'inglobe' all the function - even EventHook - in the type...
[edit]: modified again: now when you create a TEST type you add the eventhook


CS_TBL(Posted 2006) [#4]
That example is not that useful to me..

Globals are evil and should be avoided.. :(

it should be like this:

Local t:test=test.create(win)

And obviously in the EventHook function there can't be a reference to that global t ..


klepto2(Posted 2006) [#5]
Strict

Type Test
	Global test_List:TList = New TList
	Global Act_Can:Test = Null

	Field canvas:TGadget
	
	Function Hook:Object(id,data:Object,context:Object)
	Local ev:TEvent=TEvent(data)
	If Not ev Return data
	'Print ev.toString()
		Select ev.id
			Case Event_MouseEnter
				Act_Can = GetSelectedCanvas(Ev)
					If Act_Can <> Null Then
						Act_Can.Update(1)
					EndIf
			Case Event_MouseLeave
					If Act_Can <> Null 
						Act_Can.Update(0) 
						Act_Can = Null
					EndIf
			Case Event_TimerTick
				For Local T:Test = EachIn Test.Test_List
					RedrawGadget T.Canvas
				Next
		End Select
			
	Return data
	
	End Function
	
	Function GetSelectedCanvas:Test(Event:TEvent)
		For Local T:Test = EachIn Test.Test_List
			If T.Canvas = Event.Source Then
			Return T
			End If
		Next
		Return Null
	End Function

	Method update(state:Byte=0)
		SetGraphics CanvasGraphics(canvas)
			SetClsColor 128+state*127,128+state*127,128+state*127
			Cls
		Flip
	End Method
	
	Function create:Test(x,y,w,h,parent:TGadget)
		Local a:Test=New Test
		a.canvas=CreateCanvas(x,y,w,h,parent)
		a.Update(0)
		Test.Test_List.Addlast(A)
		AddHook EmitEventHook,Test.Hook,A,0
		Return a
	End Function

End Type

Function createtest:Test(x,y,w,h,parent:TGadget)
	Return Test.Create(x,y,w,h,parent)
End Function

Local win:TGadget=CreateWindow("o_O",0,0,640,480)

Local t:Test=createtest(32,32,48,24,win)
t:Test=createtest(32,60,48,24,win)
t:Test=createtest(32,88,48,24,win)




Repeat
	WaitEvent()
	If EventID()=EVENT_WINDOWCLOSE End
Forever



This is a small workaround, I hope this helps you


CS_TBL(Posted 2006) [#6]
Also not what I mean .. sorry ..

It may even all work, but I really wonder why it isn't possible to have it all a bit more transparent like the rest.

A hook for each instance, without instances even knowing other instances.. like it is now.. since they're in the same list.

So create them like this:
local t:createtest(10,20,30,40,win)
local t2:createtest(30,40,50,60,win)
local doggy:createtest(50,60,70,80,win)
local helloworld:createtest(150,160,170,180,win)
local bratwurst:createtest(150,160,170,180,win)

.. and each one should work indepentently..

All these, not being in any list, and each with its own private hook. No globals, no type-globals, no lists.. It should look/feel just like the first sample I posted, but then automated with hooks..

With degac's last one I'd be done, except for the global..

Yes, sorry for my anti-globalism-campaign, but uhm.. I hate them.. :D

Any new suggestions? :P


klepto2(Posted 2006) [#7]
Strict

Type Test

	Field canvas:TGadget
	
	Function Hook:Object(id,data:Object,context:Object)
	Local ev:TEvent=TEvent(data)
	If Not ev Return data
	'Print ev.toString()
	Local Act_Can:Test = Test(TGadget(ev.source).Context)
	If Act_Can <> Null Then
		Select ev.id
			Case Event_MouseEnter
					Act_Can.Update(1)
			Case Event_MouseLeave
						Act_Can.Update(0) 
			Case Event_TimerTick
					RedrawGadget Act_Can.Canvas
		End Select
	EndIf		
	Return data
	
	End Function
	
	Method update(state:Byte=0)
		SetGraphics CanvasGraphics(canvas)
			SetClsColor 128+state*127,128+state*127,128+state*127
			Cls
		Flip
	End Method
	
	Function create:Test(x,y,w,h,parent:TGadget)
		Local a:Test=New Test
		a.canvas=CreateCanvas(x,y,w,h,parent)
		a.canvas.Context = a
		a.Update(0)
		AddHook EmitEventHook,Test.Hook,Null,0
		Return a
	End Function

End Type

Function createtest:Test(x,y,w,h,parent:TGadget)
	Return Test.Create(x,y,w,h,parent)
End Function

Local win:TGadget=CreateWindow("o_O",0,0,640,480)

Local t:Test=createtest(32,32,48,24,win)
t:Test=createtest(32,60,48,24,win)
t:Test=createtest(32,88,48,24,win)


Repeat
	WaitEvent()
	If EventID()=EVENT_WINDOWCLOSE End
Forever


This is my new suggestion, as you can add context objects to
each Gadget you could attach the actual Test Type to the cnavas. With Local Act_Can:Test = Test(TGadget(ev.source).Context) you can receive the Test Type attached with the event.source. and use this to update your things.


CS_TBL(Posted 2006) [#8]
almost ..

..but not yet :D

I think there should simply be an events-method. And the only thing the hook should do is call that events-method. The hook function shouldn't do the actual events itself.

This event function would look like this:

Method Events()

  If EventSource()=gadget1
    If EventID()=id1
    EndIf
    If EventID()=id2
    EndIf
  Endif

  If EventID()=id3 ; just for this order-swapping I'm not much a fan of Select-Case constructions..
    If EventSource()=gadget2
    EndIf
    If EventSource()=gadget3
    EndIf
  Endif
  ; And yes, you can assume there's more than 1 gadget for an object like this..

End Method



Actually I'm surprised this baby takes so long to deliver :P The idea isn't that strange I'd say.

- create independent unlisted local object
- create event-function for object
- create eventhook that calls that event-function

- and next step: emit new unique events so I can use this object everywhere


The endgoal is that there's a means to create new GUI gadgets and other self-contained objects that look 100% transparent with the rest of the gadgets. So it must work in a 100% similar way.