Page 1 of 2

On_Events

Posted: Sat Mar 02, 2013 3:43 am
by idle
OnEvents.pbi
Implements a cross platform event callbacks framework
note where an event says it's valid for all gadgets it's only true for windows and linux

version 4.31a
Adapted for PB 6.02

version 4.3
changed to object

Version 4.2
Fixed bugs so it handles multiple windows properly
added ScreenCallback

Version 4.1
Added support for EventType_X prototypes to support any gadget, where noted as valid for any gadget
note this addition has no effect on OSX
Prototype EventType_Focus(*userdata=0) ;valid for any gadget
Prototype EventType_LostFocus(*userdata=0) ;valid for any gadget
Prototype EventType_SizeItem(*userdata=0) ;valid for any gadget
Prototype EventType_KeyDown(key.s="",*userdata=0) ;valid for any gadget
Prototype EventType_KeyUP(key.s="",*userdata=0) ;valid for any gadget
Prototype EventType_LeftButtonDown(*userdata=0) ;valid for any gadget
Prototype EventType_LeftButtonUp(*userdata=0) ;valid for any gadget
Prototype EventType_LeftClick(*userdata=0) ;valid for any gadget
Prototype EventType_leftDoubleClick(*userdata=0) ;valid for any gadget
Prototype EventType_MiddleButtonUp(*userdata=0) ;valid for any gadget
Prototype EventType_MiddleButtonDown(*userdata=0) ;valid for any gadget
Prototype EventType_MiddleButtonClick(*userdata=0) ;valid for any gadget
Prototype EventType_MiddleButtonDoubleClick(*userdata=0) ;valid for any gadget
Prototype EventType_MouseEnter(*userdata=0) ;valid for any gadget
Prototype EventType_MouseLeave(*userdata=0) ;valid for any gadget
Prototype EventType_MouseMove(x,y,*userdata=0) ;valid for any gadget
Prototype EventType_MouseWheel(direction,*userdata=0) ;valid for any gadget
Prototype EventType_RightButtonDown(*userdata=0) ;valid for any gadget
Prototype EventType_RightButtonUP(*userdata=0) ;valid for any gadget
Prototype EventType_RightClick(*userdata=0) ;valid for any gadget
Prototype EventType_RightDoubleClick(*userdata=0) ;valid for any gadget
Source

https://dnscope.io/idlefiles/On_Events.pbi

Re: WaitWindowEventCallBacks()

Posted: Sat Mar 02, 2013 10:34 pm
by Kiffi
Image Thanks for sharing!

Greetings ... Kiffi

Re: WaitWindowEventCallBacks()

Posted: Sun Mar 03, 2013 2:16 am
by said
Nice and very useful :D

thanks for sharing

Re: WaitWindowEventCallBacks()

Posted: Sun Mar 03, 2013 5:51 am
by idle
noticed I had a bug in SetEventWindowCallBack i V1
was adding an additional element to the list

I've made another version eliminating the foreach on the event list
It uses SetGadgetData so there is a potential a user of your code could overwrite a callback
You can only set one callback per gadget or window with this method

Could someone on OSX add the methods SetWindowData GetWindowData
Linux sometimes reports eventwindow() as -1 which seems a little odd

V2

Code: Select all

;WaitWindowEventCallBacks.pbi
;Implements a Cross platform Event CallBack Chain  
;for setting callbacks required to Impliment a custom user control where it needs to do some processing 
;Set Callbacks for gadgets and windows  
;Author Idle 2/3/13 PB 5.11 
;Version 2.0
;notes uses setgadgetdata to store the pointer to an eventcallback in a gadget 
;so it could get over written by a user of your code. 

Prototype protoEventCallBackGadget(EventType,*userdata=0)
Prototype protoEventCallBackWindow(Event,*userdata=0)

Structure PB_EventsCallbackFunction
   item.i
   *userdata
   EventType.i
   *cbGadget.protoEventCallBackGadget
   *cbWindow.protoEventCallBackWindow 
EndStructure 

Structure PB_EventsCallbacks
   List callbacks.PB_EventsCallbackFunction()
EndStructure 

Global gEventCallbacks.PB_EventsCallbacks

CompilerIf #PB_Compiler_OS = #PB_OS_Windows
   #GWLP_USERDATA =-21
 CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux 
   ImportC  "-gtk"
     gtk_widget_get_parent_(*widget) As " gtk_widget_get_parent"
     g_object_set_data_(*Widget.GtkWidget,strData.p-ascii,*userdata) As "g_object_set_data"
     g_object_get_data_(*Widget.GtkWidget,strData.p-ascii) As "g_object_get_data"
  EndImport  
   
CompilerEndIf 

Procedure SetWindowData(window,value) 
   Protected win 
   CompilerIf #PB_Compiler_OS = #PB_OS_Windows
        SetWindowLongPtr_(WindowID(window),#GWLP_USERDATA,Value)
   CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux 
       win = WindowID(window)
       g_object_set_data_(win,"wev",value)
   CompilerElse 
       ;for osx
   CompilerEndIf 
         
EndProcedure   

Procedure GetWindowData(window) 
   Protected win  
   CompilerIf #PB_Compiler_OS = #PB_OS_Windows
       ProcedureReturn  GetWindowLongPtr_(WindowID(window),#GWLP_USERDATA)
   CompilerElseIf #PB_Compiler_OS = #PB_OS_Linux 
     If window =-1 
        win = GetActiveWindow() 
        If IsWindow(win) 
           win = WindowID(win)
           ProcedureReturn  g_object_get_data_(win,"wev")
        EndIf   
     Else 
        Win = WindowID(window)
        ProcedureReturn g_object_get_data_(win,"wev")
    EndIf
   
   CompilerElse 
       ;osx
    CompilerEndIf 
     
EndProcedure    

;=============================================================================
; SetEventCallBackGadget(Gadget,*Function.protoEventCallBackGadget,*UserData=0) 
; Set a Gadgets Event Callback 
; Parameters 
; Gadget : Gadget Number 
; *Function : Address of the Callback Function in the form of MyEventCallBackGadget(EventType,*userdata=0)
; *UserData=0 : optional : A pointer to data you want to pass to the callback procedure eg a *this pointer for an Interface call 
; Returns 
;  Returns a EventCallback pointer or 0 if function fails 
; Notes 
;  The CallBack only Processes PB Events it doesn't process platform events  
;=============================================================================

Procedure SetEventCallBackGadget(Gadget,*Function.protoEventCallBackGadget,*UserData=0) 
   Protected CallBack 
   CallBack = AddElement(gEventCallbacks\callbacks())
   If  CallBack 
      gEventCallbacks\callbacks()\item = Gadget 
      gEventCallbacks\callbacks()\userdata = *userdata 
      gEventCallbacks\callbacks()\cbGadget = *function
      SetGadgetData(Gadget,CallBack) 
      ProcedureReturn CallBack  
  EndIf     
EndProcedure 

;=============================================================================
; ChangeEventCallBackGadget(EventCallBack,*Function.protoEventCallBackGadget,*UserData=0) 
; Change an existing EventCallback   
; Parameters 
; EventCallback : An Existing EventCallBack set from SetEventCallBackGadget 
; *Function : Address of the Callback Function in the form of MyEventCallBackGadget(EventType,*userdata=0)
; *UserData=0 : optional : A pointer to data you want to pass to the callback procedure eg a *this pointer for an Interface call 
; Returns 
;  Returns #True if sucessful  
;=============================================================================

Procedure ChangeEventCallBackGadget(EventCallback,*Function.protoEventCallBackGadget,*UserData=0) 
   Protected *EventCallBack.PB_EventsCallbackFunction
   If EventCallback
       *EventCallBack = EventCallback 
       *EventCallBack\cbGadget = *Function 
       *EventCallBack\userdata = *UserData 
       ProcedureReturn #True    
    EndIf    
 EndProcedure 

;=============================================================================
; SetEventCallBackWindow(Window,*Function.protoEventCallBackWindow,*UserData=0)
; Set a Windows Event Callback 
; Parameters 
; Window  : Window  Number 
; *Function : Address of the Callback Function in the form of MyEventCallBackWindow(Event,*userdata=0)
; *UserData=0 : optional : A pointer to data you want to pass to the callback procedure eg a *this pointer for an Interface call 
; Returns 
;  Returns a EventCallBack pointer or 0 if function fails 
; Notes 
;  The CallBack only Processes PB Events it doesn't process platform events  
;=============================================================================

Procedure SetEventCallBackWindow(Window,*Function.protoEventCallBackWindow,*UserData=0) 
   Protected CallBack 
   CallBack = AddElement(gEventCallbacks\callbacks())
   If  CallBack 
       gEventCallbacks\callbacks()\item = Window 
      gEventCallbacks\callbacks()\userdata = *UserData 
      gEventCallbacks\callbacks()\cbWindow = *Function
      SetWindowData(Window,CallBack) 
      ProcedureReturn CallBack  
  EndIf     
   
EndProcedure 

;=============================================================================
; ChangeEventCallBackWindow(EventCallBack,*Function.protoEventCallBackWindow,*UserData=0) 
; Change an existing EventCallback   
; Parameters 
; EventCallback : An Existing EventCallBack set from SetEventCallBackWindow 
; *Function : Address of the Callback Function in the form of MyEventCallBackWindow(Event,*userdata=0)
; *UserData=0 : optional : A pointer to data you want to pass to the callback procedure eg a *this pointer for an Interface call 
; Returns 
;  Returns #True if sucessful  
;=============================================================================

Procedure ChangeEventCallBackWindow(EventCallback,*Function.protoEventCallBackGadget,*UserData=0) 
   Protected *EventCallBack.PB_EventsCallbackFunction
   If EventCallback
       *EventCallBack = EventCallback 
       *EventCallBack\cbWindow = *Function 
       *EventCallBack\userdata = *UserData 
        ProcedureReturn #True    
    EndIf    
 EndProcedure 

;============================================================================
;RemoveEventCallBack(EventCallBack) 
;Removes an EventCallBack from the EventsCallBack Chain
;Parameters 
; EventCallBack the pointer to an EventCallback recieved from calling a SetEventCallBackGadget or  SetEventCallBackWindow
;==============================================================================

Procedure RemoveEventCallBack(EventCallBack) 
   Protected *EventCallBack.PB_EventsCallbackFunction
   If EventCallBack 
     ChangeCurrentElement( gEventCallbacks\callbacks(),EventCallBack) 
     *EventCallBack = @gEventCallbacks\callbacks()
     If *EventCallBack\cbGadget 
        SetGadgetData(*EventCallBack\item,0)
     Else 
        SetWindowData(*EventCallBack\item,0)
     EndIf    
     DeleteElement(gEventCallbacks\callbacks()) 
   EndIf   
EndProcedure 
 
  
;===============================================================================
;WaitWindowEventCallBacks(timeout=-1)
;Same as WaitWindowEvent()but additionally processes EventCallBack requests for Gadgets or Windows 
;set by SetEventCallBackGadget() or SetEventCallBackWindow() 
;note it uses setgadgetdata so it's only posible to trap all events to a gadget or window
;=============================================================================== 
  
  Procedure WaitWindowEventCallBacks(timeout=-1)
   Protected Event,EventType,window,*EventCallBack.PB_EventsCallbackFunction
   Event = WaitWindowEvent(timeout)
   If Event 
      If Event = #PB_Event_Gadget
         *EventCallBack = GetGadgetData(EventGadget())
         If *EventCallBack
            If *EventCallBack\cbGadget 
               *EventCallBack\cbGadget(EventType(),*EventCallBack\userdata) 
            EndIf
          EndIf   
       Else     
         *EventCallBack = GetWindowData(EventWindow())
         If *EventCallBack
            If *EventCallBack\cbWindow 
               *EventCallBack\cbWindow(Event,*EventCallBack\userdata) 
            EndIf
        EndIf   
      EndIf 
   EndIf     
   ProcedureReturn Event 
   
EndProcedure 
  

;================================================================= 


;=================================================================
;Test WaitWindowEventCallBack()

Procedure Gadget1_Events(EventType,*userdata) 
   
   If EventType = #PB_EventType_LeftClick
         Debug "Button 1 Clicked" 
   EndIf
           
EndProcedure 

Procedure Gadget2_OnRightClick(EventType,*userdata)  
    If EventType = #PB_EventType_RightClick 
       Debug "Right Button Clicked" 
    EndIf    
 EndProcedure       
  
 Procedure Window1_Events(Event,*userdata) 
    If event = #PB_Event_Repaint
       Debug "Event Repaint "
    EndIf   
  EndProcedure   
  
  
 
OpenWindow(1,0,0,200,100,"1") 
ButtonGadget(1,5,5,60,30,"click me") 
CanvasGadget(2,70,5,110,30)
ButtonGadget(3,5,40,60,30,"Click me") 
;Set a callback for the gadget to trap it's events 
Callback1 = SetEventCallBackGadget(1,@Gadget1_Events())
;Set a callback to trap a specific event 
Callback2 = SetEventCallBackGadget(2,@Gadget2_OnRightClick())
;set a callback to the PB events for the window
Callback3 = SetEventCallBackWindow(1,@Window1_Events()) 
StartDrawing(CanvasOutput(2))
DrawText(5,5,"Right click me") 
StopDrawing() 


Repeat
  
   Select WaitWindowEventCallBacks() 
      Case #PB_Event_CloseWindow 
         RemoveEventCallBack(CallBack1)
         RemoveEventCallBack(CallBack2) 
         RemoveEventCallBack(CallBack3) 
         End 
      Case #PB_Event_Gadget 
         If EventGadget() = 3 
            If EventType() = #PB_EventType_LeftClick 
               Debug "Not in Call Back Chain" 
            EndIf 
         EndIf    
   EndSelect 
ForEver 


Re: WaitWindowEventCallBacks()

Posted: Sun Mar 03, 2013 5:39 pm
by jassing
Nice work! Thanks.

Re: WaitWindowEventCallBacks()

Posted: Sun Mar 03, 2013 11:58 pm
by idle
Version 3
[edit] removed

Re: WaitWindowEventCallBacks()

Posted: Fri Mar 08, 2013 1:55 am
by idle
Added V4
Changed to using prototypes

Re: WaitWindowEventCallBacks()

Posted: Fri Mar 08, 2013 4:58 am
by kvitaliy
idle wrote:Added V3
Line 212
Error - Invalid memory access
idle wrote:Added V4
Line 640

Code: Select all

   If (*EventCallBack\cbGadget And Result = 1)
Error - Pointer is null.

Re: WaitWindowEventCallBacks()

Posted: Fri Mar 08, 2013 7:58 am
by idle
what OS and PB version are you using kvitaliy?

Ok fixed was missing the *userdata pointer in the callbacks, Linux didn't seem to mind
windows didn't like it.

Re: WaitWindowEventCallBacks()

Posted: Fri Mar 08, 2013 8:12 am
by flaith
Same issue on Windows XP and PB 5.11 :?

Re: WaitWindowEventCallBacks()

Posted: Fri Mar 08, 2013 8:15 am
by idle
yes I was missing the *userdata pointer in the callback functions in the example
Linux didn't mind the omission of.

I removed V3 Thanks for letting me know.

Re: WaitWindowEventCallBacks()

Posted: Fri Mar 08, 2013 9:47 am
by flaith
It works now, thanks idle :D

Re: WaitWindowEventCallBacks()

Posted: Fri Mar 08, 2013 10:03 am
by kvitaliy
Ok! It works now :D

Re: WaitWindowEventCallBacks()

Posted: Fri Mar 08, 2013 11:08 am
by idle
Thanks, I really should take the time to check and test code in the vm

Re: WaitWindowEventCallBacks()

Posted: Fri Mar 08, 2013 11:42 am
by Joris
Thanks for sharing.
I'm still learning PB but this might become quit useful.