Custom Gadget Hack
Posted: Sun Sep 13, 2009 4:32 pm
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....
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