Page 1 of 1

Custom Gadget Hack

Posted: Sun Sep 13, 2009 4:32 pm
by Erlend
Just thought I'd fling this out there and hope someone else could add the included features for MacOS and make sure Windows implementation is working as I run Linux exclusive. I use cairo for drawing as it is multiplatform and we don't have a gadgetoutput() function in purebasic...

As always my code lacks documentation.. Sorry....

Code: Select all

XIncludeFile "cairo180.pbi"
ImportC "/usr/lib/libgdk-x11-2.0.so.0"
    gdk_cairo_create(*wid)
EndImport 

#CanvasBorder     =%0010
#CanvasScrollable=%0001
Enumeration
   #CanvasPaint
   #CanvasSize
   #CanvasMouseLeave
   #CanvasMouseEnter 
   #CanvasMouseMove
   #CanvasMouseButtonUp
   #CanvasMouseButtonDown
   #CanvasMouseWheel
   #CanvasKeyPress
   #CanvasKeyRelease
EndEnumeration
Structure CanvasRect
   X.l
   Y.l
   Width.l
   Height.l
EndStructure 
Structure CanvasMouse
   X.l
   Y.l
   Button.b
   Wheel.b
   Delta.l
   Outside.b
EndStructure 
Structure CanvasStruct
   Widget.i
   WidgetRect.CanvasRect
   PaintRect.CanvasRect
   Mouse.CanvasMouse
   Message.i
   Key.i
   Callback.i
   Surface.i
   Update.b
EndStructure

;Canvas Mouse Cursor Constants
CompilerIf #PB_Compiler_OS=#PB_OS_Linux 
#CURSOR_NO=#GDK_X_CURSOR
#CURSOR_HELP=#GDK_QUESTION_ARROW
#CURSOR_HAND=#GDK_HAND2
#CURSOR_IBEAM=#GDK_XTERM
#CURSOR_NORMAL=#GDK_ARROW
#CURSOR_CROSSHAIR=#GDK_CROSSHAIR
#CURSOR_WAIT=#GDK_WATCH
#CURSOR_UPARROW=#GDK_CENTER_PTR
#CURSOR_MOVE=#GDK_FLEUR
#CURSOR_MOVE_HORIZONTAL=#GDK_SB_H_DOUBLE_ARROW
#CURSOR_MOVE_VERTICAL=#GDK_SB_V_DOUBLE_ARROW
#CURSOR_SIZE_RIGHT_SIDE=#GDK_RIGHT_SIDE
#CURSOR_SIZE_LEFT_SIDE=#GDK_LEFT_SIDE
#CURSOR_SIZE_TOP=#GDK_TOP_SIDE
#CURSOR_SIZE_BOTTOM=#GDK_BOTTOM_SIDE
#CURSOR_SIZE_TOP_LEFT=#GDK_TOP_LEFT_CORNER
#CURSOR_SIZE_TOP_RIGHT=#GDK_TOP_RIGHT_CORNER
#CURSOR_SIZE_BOTTOM_LEFT=#GDK_BOTTOM_LEFT_CORNER
#CURSOR_SIZE_BOTTOM_RIGHT=#GDK_BOTTOM_RIGHT_CORNER
CompilerElse
#CURSOR_NO=#IDC_NO
#CURSOR_HELP=#IDC_HELP
#CURSOR_HAND=#IDC_HAND
#CURSOR_IBEAM=#IDC_IBEAM
#CURSOR_NORMAL=#IDC_ARROW
#CURSOR_CROSSHAIR=#IDC_CROSS
#CURSOR_WAIT=#IDC_WAIT    
#CURSOR_UPARROW=#IDC_UPARROW      
#CURSOR_MOVE=#IDC_SIZEALL
#CURSOR_MOVE_HORIZONTAL=#IDC_SIZEWE
#CURSOR_MOVE_VERTICAL=#IDC_SIZENS
#CURSOR_SIZE_RIGHT_SIDE=#IDC_SIZEWE
#CURSOR_SIZE_LEFT_SIDE=#IDC_SIZEWE
#CURSOR_SIZE_TOP=#IDC_SIZENS
#CURSOR_SIZE_BOTTOM=#IDC_SIZENS
#CURSOR_SIZE_TOP_LEFT=#IDC_SIZENWSE
#CURSOR_SIZE_TOP_RIGHT=#IDC_SIZENESW
#CURSOR_SIZE_BOTTOM_LEFT=#IDC_SIZENESW
#CURSOR_SIZE_BOTTOM_RIGHT=#IDC_SIZENWSE
CompilerEndIf
;Missing Linux Structure
CompilerIf #PB_Compiler_OS=#PB_OS_Linux
CompilerIf Defined(GdkEvent,#PB_Structure)=#False
Structure GdkEvent
  gdktype.l
  StructureUnion
    any.GdkEventAny
    expose.GdkEventExpose	
    no_expose.GdkEventNoExpose	
    visibility.GdkEventVisibility	
    motion.GdkEventMotion
    button.GdkEventButton
    scroll.GdkEventScroll
    key.GdkEventKey
    crossing.GdkEventCrossing
    focus_change.GdkEventFocus		    
    configure.GdkEventConfigure	    
    property.GdkEventProperty	
    selection.GdkEventSelection	
    proximity.GdkEventProximity
    client.GdkEventClient	    
    dnd.GdkEventDND               
    window_state.GdkEventWindowState       
    setting.GdkEventSetting           
  EndStructureUnion
EndStructure
CompilerEndIf
CompilerEndIf
Procedure Canvas_CreateCursor(Image,x,y,fgcolor,bgcolor)
  ;*pixbuf=gdk_pixbuf_get_from_drawable_(#Null,Image,#Null,0,0,0,0,-1,-1)
  ;cursor = gdk_cursor_new_from_pixbuf_(gdk_display_get_default_(),*pixbuf,x,y)
  fg.gdkcolor
  bg.gdkcolor
  fg\red=255
  fg\green=0
  fg\blue=0
  bg\red=0
  bg\green=0
  bg\blue=0
  cursor = gdk_cursor_new_from_pixmap_(image,image,RGB(255,0,0),RGB(0,255,0),x,y)
  ProcedureReturn cursor
EndProcedure
Procedure Canvas_LoadCursor(Type)
CompilerIf  #PB_Compiler_OS=#PB_OS_Linux 
      ProcedureReturn gdk_cursor_new_(Type)
CompilerElse
      ProcedureReturn LoadCursor_(0,Type)
CompilerEndIf
EndProcedure
Procedure Canvas_SetCallback(Handle,CallbackFunction)
CompilerIf  #PB_Compiler_OS=#PB_OS_Linux 
 gtk_widget_add_events_(Handle,#GDK_ALL_EVENTS_MASK)
 gtk_widget_set_app_paintable_(Handle,#True)
 g_signal_connect_data_(Handle,"event",CallbackFunction,0,0,#G_CONNECT_AFTER)             
CompilerElse
  SetProp_(Handle,"OldProc",SetWindowLong_(Handle,#GWL_WNDPROC,CallbackFunction))
CompilerEndIf
EndProcedure
Procedure Canvas_ClipCursor(*Canvas.CanvasStruct,Cursor)
;Untested....
CompilerIf  #PB_Compiler_OS=#PB_OS_Linux 
 *Can.GtkWidget=*Canvas\Widget
 gdk_pointer_grab_(*Can,#True,#Null,*Can,Cursor,#Null)
CompilerElse
 *lpRect.RECT:*lpRect\left=*Canvas\Widgetrect\x:*lpRect\top=*Canvas\Widgetrect\y:*lpRect\right=*Canvas\Widgetrect\x2:*lpRect\bottom=*Canvas\Widgetrect\y2:ClipCursor_(*lpRect);
CompilerEndIf
EndProcedure
Procedure Canvas_UnclipCursor()
  gdk_pointer_ungrab_(#Null)
EndProcedure
Procedure Canvas_SetCursor(Handle,Cursor)
CompilerIf  #PB_Compiler_OS=#PB_OS_Linux 
    *widget.gtkwidget=handle
    gdk_window_set_cursor_(*widget\window, Cursor)    
CompilerElse
    SetCursor_(Cursor)
CompilerEndIf
EndProcedure
Procedure Canvas_SetProperty(Handle,Property.s,Value)
CompilerIf  #PB_Compiler_OS=#PB_OS_Linux 
      g_object_set_data_(Handle,Property,Value)
CompilerElse
      SetProp_(Handle,Property,Value) 
CompilerEndIf
EndProcedure
Procedure Canvas_GetProperty(Handle,Property)
CompilerIf  #PB_Compiler_OS=#PB_OS_Linux 
      g_object_get_data_(Handle,Property)
CompilerElse
      GetProp_(Handle,Property) 
CompilerEndIf
EndProcedure
Procedure Canvas_GetToplevel(Handle)
CompilerIf  #PB_Compiler_OS=#PB_OS_Linux 
      gtk_widget_get_toplevel_(Handle)
CompilerElse
      GetAncestor_(Handle,#GA_ROOT)
CompilerEndIf
EndProcedure
Macro Canvas_CallbackFunc(Name)
CompilerIf #PB_Compiler_OS=#PB_OS_Linux
ProcedureC.l Name(Handle,*Event.GdkEvent,Userdata) 
   *wid.gtkwidget=gtk_get_event_widget_(*Event)
   *canvas.CanvasStruct=g_object_get_data_(*wid,"info")
   If *canvas=0
     ;Most likely a keypress event....
     *canvas=g_object_get_data_(Handle,"info")
   EndIf
   Surface=*wid\window
   Select *event\gdktype
     Case #GDK_VISIBILITY_NOTIFY
        *canvas\Message=#Canvaspaint  
     Case #GDK_CONFIGURE
        *canvas\Message=#CanvasSize       
        *canvas\WidgetRect\x=*wid\allocation\x
        *canvas\WidgetRect\y=*wid\allocation\y
        *canvas\WidgetRect\Width=*wid\allocation\width
        *canvas\WidgetRect\Height=*wid\allocation\height
     Case #GDK_EXPOSE 
        *paint.GdkEventExpose=*Event
        *canvas\Message=#Canvaspaint
        *canvas\WidgetRect\x=*wid\allocation\x
        *canvas\WidgetRect\y=*wid\allocation\y
        *canvas\WidgetRect\Width=*wid\allocation\width
        *canvas\WidgetRect\Height=*wid\allocation\height
        *canvas\PaintRect\x=*paint\area\x
        *canvas\PaintRect\y=*paint\area\y
        *canvas\PaintRect\Width=*paint\area\width
        *canvas\PaintRect\Height=*paint\area\height
     Case #GDK_KEY_PRESS
        *canvas\Message=#Canvaskeypress
        *Keypress.GdkEventKey=*Event
        *canvas\Key=*Keypress\keyval
     Case #GDK_KEY_RELEASE
        *canvas\Message=#Canvaskeyrelease
        *Keypress.GdkEventKey=*Event
        *canvas\Key=*Keypress\keyval
     Case #GDK_LEAVE_NOTIFY 
        *canvas\Message=#CanvasMouseLeave
        *canvas\Mouse\Outside=#True
        gtk_grab_remove_(*wid)
     Case #GDK_ENTER_NOTIFY 
        *canvas\Message=#CanvasMouseEnter
        *canvas\Mouse\Outside=#False
        gtk_grab_add_(*wid)
     Case #GDK_MOTION_NOTIFY 
        *Motion.GdkEventMotion=*Event
        *canvas\Mouse\X=Int(*Motion\x)
        *canvas\Mouse\Y=Int(*Motion\y)
        *canvas\Message=#CanvasMouseMove
     Case #GDK_SCROLL 
        *Scroll.GdkEventScroll=*Event
        *canvas\Mouse\X=Int(*Scroll\x)
        *canvas\Mouse\Y=Int(*Scroll\y)
        *canvas\Mouse\Wheel=Int(*Scroll\direction)
        *canvas\Message=#CanvasMouseWheel
     Case #GDK_BUTTON_PRESS 
        *Button.GdkEventButton=*Event
        *canvas\Mouse\X=Int(*Button\x)
        *canvas\Mouse\Y=Int(*Button\y)
        *canvas\Mouse\Button=Int(*Button\Button)
        *canvas\Message=#CanvasMouseButtonDown
     Case #GDK_BUTTON_RELEASE 
       *Button.GdkEventButton=*Event 
        *canvas\Mouse\X=Int(*Button\x)
        *canvas\Mouse\Y=Int(*Button\y)
        *canvas\Mouse\Button=Int(*Button\Button)
        *canvas\Message=#CanvasMouseButtonUp
   EndSelect
CompilerElse
ProcedureC.l Name(Handle,Message,wParam,lParam) 
   *canvas.CanvasStruct=GetProp_(Handle,"Info")
   Select Message
    Case #WM_SIZE 
        *canvas\WidgetRect\Width=(lparam & $FFFF)
        *canvas\WidgetRect\Height=(lparam >> 16)
        *canvas\Message=#CanvasSize
    Case #WM_PAINT,#WM_ERASEBKGND;,#WM_NCPAINT
        *canvas\Message=#canvasPaint 
    Case #WM_MOUSELEAVE
        MouseOutside=#True 
        *canvas\Message=#canvasMouseLeave
    Case #WM_MOUSEMOVE 
        If MouseOutside=#True
            *canvas\Message=#canvasMouseEnter
        Else
            *canvas\Message=#canvasMouseMove
        EndIf
        *canvas\Mouse\X=(lparam & $FFFF)
        *canvas\Mouse\Y=(lparam >> 16) 
    Case #WM_SETCURSOR 
       SetCursor_(MouseCursor)
    Case #WM_MOUSEWHEEL
       *canvas\Mouse\X=(lparam & $FFFF)
       *canvas\Mouse\Y=(lparam >> 16)
       If wParam>0
          *canvas\Mouse\Wheel=0
       Else
          *canvas\Mouse\Wheel=1
       EndIf
       *canvas\Message=#canvasMouseWheel 
    Case #WM_LBUTTONDOWN
       *canvas\Mouse\Button=1
       *canvas\Message=#canvasMouseButtonDown
    Case #WM_LBUTTONUP 
       *canvas\Mouse\Button=1
       *canvas\Message=#canvasMouseButtonUp
    Case #WM_MBUTTONDOWN 
       *canvas\Mouse\Button=2
       *canvas\Message=#canvasMouseButtonDown
    Case #WM_MBUTTONUP 
       *canvas\Mouse\Button=2
       *canvas\Message=#canvasMouseButtonUp
    Case #WM_RBUTTONDOWN 
       *canvas\Mouse\Button=3
       *canvas\Message=#canvasMouseButtonDown
    Case #WM_RBUTTONUP 
       *canvas\Mouse\Button=3
       *canvas\Message=#canvasMouseButtonUp
   EndSelect
CompilerEndIf
EndMacro
Macro Canvas_EndCallbackFunc()
CompilerIf #PB_Compiler_OS=#PB_OS_Linux
     *canvas\message=0
     ProcedureReturn ReturnValue
     EndProcedure
CompilerElse
   If ReturnValue=#True
     *canvas\message=0
   ProcedureReturn ReturnValue
   Else
     *canvas\message=0
   ProcedureReturn CallWindowProc_(OSGetProperty(Handle,"OldProc"), Handle, Message, wParam, lParam)
   EndIf
  EndProcedure
CompilerEndIf
EndMacro
ProcedureC CanvasGadget(Gadget,x,y,width,height,Callback,flags)
    Static NewList CanvasList.CanvasStruct()
    If flags & #CanvasBorder
     If flags & #CanvasScrollable
         flag=#PB_ScrollArea_Single
       Else
         flag=#PB_Container_Single
     EndIf
     border=4   
    EndIf
    If Gadget=#PB_Any
      If flags & #CanvasScrollable
        Gadget=ScrollAreaGadget(#PB_Any,x,y,width,height,width*3,height*3,10,flag)
      Else
        Gadget=ContainerGadget(#PB_Any,x,y,width,height,flag)
       EndIf
    Else
      If flags & #CanvasScrollable
        Gadget=ScrollAreaGadget(Gadget,x,y,width,height,width*3,height*3,10,flag)
      Else
        Gadget=ContainerGadget(Gadget,x,y,width,height,flag)
      EndIf
    EndIf    
    CloseGadgetList()
    CompilerIf #PB_Compiler_OS=#PB_OS_Linux 
      If flags & #CanvasScrollable
       CompilerIf Defined(Listtype,#PB_Structure)=#False
          Structure Listtype
            CurrentItem.l
            NextItem.l
            PrevItem.l
          EndStructure
          CompilerEndIf
          *Lis.Listtype=gtk_container_get_children_(GadgetID(Gadget))
          *Lis2.Listtype=gtk_container_get_children_(*Lis\CurrentItem)
          handle=*Lis2\CurrentItem ; This is the fixed widget we need to connect to... 
          g_list_free_(*Lis) 
          g_list_free_(*Lis2)
     Else
        handle=GadgetID(Gadget)
    EndIf
    CompilerElse
        handle=GadgetID(Gadget)
    CompilerEndIf
    *lcanvas.CanvasStruct=AddElement(CanvasList())
    CompilerIf #PB_Compiler_OS=#PB_OS_Linux
    *wid.GtkWidget=handle
    *lcanvas\surface=*wid\window
    CompilerElse
    *lcanvas\surface=handle
    CompilerEndIf
    *lcanvas\Widget=handle
    Canvas_SetProperty(handle,"info",*lcanvas)   
    Canvas_SetCallback(handle,Callback)
    ProcedureReturn gadget
EndProcedure
Procedure Canvas_SetSize(Canvas,width,height)
  SetGadgetAttribute(Canvas,#PB_ScrollArea_InnerWidth,width)
  SetGadgetAttribute(Canvas,#PB_ScrollArea_InnerHeight,height)
EndProcedure

Procedure DrawGadgetContent(*canvas.CanvasStruct)
    w=*canvas\widgetrect\width
    h=*canvas\widgetrect\height
    CompilerIf #PB_Compiler_OS=#PB_OS_Linux
      cr=gdk_cairo_create(*canvas\surface)
    CompilerElse 
      cr=cairo_win32_surface_create_(GetDC_(*canvas\surface));
    CompilerEndIf
    cairo_set_source_rgb (cr, 0, 0, 0)
    For i=0 To w Step 10
      cairo_line_to (cr, i, y);
      If y=h:y=0:Else:y=h:EndIf
    Next 
    cairo_stroke (cr);
    cairo_destroy(cr)
EndProcedure



Canvas_CallbackFunc(CanvasCallback)
  Static b

  ;cur=Canvas_LoadCursor(#CURSOR_CROSSHAIR)

  Select *canvas\message
  
    Case #CanvasPaint
      DrawGadgetContent(*canvas)  
    
    Case #CanvasSize
     Debug "sadkjdflk"
    Case #CanvasMousewheel
    ;   Canvas_ClipCursor(*canvas,#Null)
       Debug *canvas\mouse\wheel
       If *canvas\mouse\wheel=0
       b=b-1
       ElseIf *canvas\mouse\wheel=1
       b=b+1
       EndIf
       If b>=255
         b=255
       ElseIf b<=0
         b=0
       EndIf
       update=#True
  
     Case #CanvasMouseMove
      ; Canvas_SetCursor(Handle,cur)
  
     Case #canvaskeypress 
        Debug *canvas\key
  
  EndSelect

Canvas_EndCallbackFunc()

OpenWindow(0,0,0,470,350,"CanvasGadgetTest")
img =CreateImage(0,16,16,1)
gadget1=Canvasgadget(#PB_Any,0,0,150,150,@CanvasCallback(),#CanvasScrollable)
gadget2=Canvasgadget(#PB_Any,160,0,150,150,@CanvasCallback(),#CanvasBorder)
gadget3=Canvasgadget(#PB_Any,320,0,150,150,@CanvasCallback(),#CanvasBorder|#CanvasScrollable)
SetGadgetColor(gadget1,#PB_Gadget_BackColor,RGB(0,150,150))
SetGadgetColor(gadget2,#PB_Gadget_BackColor,RGB(255,150,150))
SetGadgetColor(gadget3,#PB_Gadget_BackColor,RGB(0,150,255))
Canvas_SetSize(gadget3,15000,15000)
ContainerGadget(#PB_Any,0,150,200,100)
CloseGadgetList()

Repeat
  event=WaitWindowEvent()

  Select event
 
     Case #PB_Event_Menu
       
     Case #PB_Event_Gadget
       
     Case #PB_Event_Repaint
     
     Case #PB_Event_SizeWindow
        
     Case #PB_Event_CloseWindow
        CloseApp=#True
 
  EndSelect
  
Until CloseApp=#True