SplitterGadget+ dashed bar, border snap, thickness,grip,swap
Posted: Sun Feb 14, 2010 1:39 am
v2 For PB 4.41+
-SetSplitterDashed : enable dashed mode
-SetSplitterDoubleClick : enable auto snapping by double-click(disable If #False)
-SwapSplitter : Swap gadgets Or/And other options
-LockSplitter : lock splitter bar(unlock If #False)
-SplitterLocked : returns #True If the splitter is locked
-SplitterSnapped : returns 1 Or 2 If splitter snapped border 1 Or 2 is snapped (Not snapped If ZERO)
-event type: #PB_EventType_LeftDoubleClick
-event type: #PB_EventType_Change

-SetSplitterDashed : enable dashed mode
- you can specify the grip size(disable If ZERO)
- you can specify the bar thickness
- you can customize the grip images
-SetSplitterDoubleClick : enable auto snapping by double-click(disable If #False)
-SwapSplitter : Swap gadgets Or/And other options
-LockSplitter : lock splitter bar(unlock If #False)
-SplitterLocked : returns #True If the splitter is locked
-SplitterSnapped : returns 1 Or 2 If splitter snapped border 1 Or 2 is snapped (Not snapped If ZERO)
-event type: #PB_EventType_LeftDoubleClick
-event type: #PB_EventType_Change

Code: Select all
EnableExplicit
CompilerIf Defined(PB_Gadget_SendGadgetCommand, #PB_Procedure)=#False
Import ""
;send custom gadget event type
PB_Gadget_SendGadgetCommand(hwnd, EventType)
EndImport
CompilerEndIf
Prototype SGP_CreateImage(ID, Width, Height, Vertical, Focused)
Structure SGP_PARAMS
*CB ;stored original splittergadget Callback
ID.i ;stored original splittergadget ID
x.i ;Splitter Pos (for bar position calculation)
y.i ;Splitter Pos (for bar position calculation)
Thickness.i ;Bar Thickness
Flags.i ;stored original splittergadget flags
Parent.i ;gadget list
Vertical.b ;is vertical bar
Dashed.b ;is dashed bar
Locked.b ;is locked bar
UnsnapPos.i ;Unsnap position
Pos.i ;Bar position
*LineCB ;line Callback
Line.i ;line ID
LinePos.Rect ;line position
LineVisible.i ;line Visible
Limit.Rect ;Line Scroll limit
Snap.Rect ;Line Snap border
SnapFirst.i ;Snap distance (first gadget)
SnapSecond.i ;Snap distance (second gadget)
SnapDblClick.b ;Snap to fixed gadget border
Grip.i ;Grip ID
GripImg1.i ;Grip Image ID1
GripImg2.i ;Grip Image ID2
GripWidth.i ;Grip width
GripFocus.b ;Grip focus
;Grip drawing function
*GripImage.SGP_CreateImage
EndStructure
Global *SGP_PARAMS_LINE.SGP_PARAMS
Global SGP_Line
Global SGP_Cursor_Arrow=LoadCursor_(0, #IDC_ARROW)
Global SGP_Cursor_V=LoadCursor_(0, #IDC_SIZENS)
Global SGP_Cursor_H=LoadCursor_(0, #IDC_SIZEWE)
Enumeration
;custom windows message
#SGP_WM_FIXUP=#WM_USER
#SGP_WM_SENDEVENT
#SGP_WM_SAVEUNSNAPPOS
#SGP_WM_SHOWCURSOR
#SGP_WM_SHOWLINE
#SGP_WM_HIDELINE
#SGP_WM_SHOWGRIP
#SGP_WM_GRIPCHECKING
;custom constants
#SGP_Action_Snap=1
#SGP_Action_Unsnap
EndEnumeration
ProcedureDLL SGP_LineCB(Window, Message, wParam, lParam)
If *SGP_PARAMS_LINE And IsGadget(*SGP_PARAMS_LINE\ID)
Protected *SGP_PARAMS.SGP_PARAMS=*SGP_PARAMS_LINE
Protected ID=*SGP_PARAMS\ID
Select Message
Case #SGP_WM_SHOWCURSOR
;{/// SHOW CURSOR
If *SGP_PARAMS\Vertical
SetCursor_(SGP_Cursor_H)
Else
SetCursor_(SGP_Cursor_V)
EndIf
;}
Case #SGP_WM_SHOWLINE
;{/// SHOW DASHED LINE
*SGP_PARAMS\LineVisible=1
SetLayeredWindowAttributes_(WindowID(*SGP_PARAMS\Line), 0, 60, #LWA_ALPHA)
If *SGP_PARAMS\Vertical
ResizeWindow(*SGP_PARAMS\Line, #PB_Ignore, #PB_Ignore, *SGP_PARAMS\Thickness, GadgetHeight(ID))
Else
ResizeWindow(*SGP_PARAMS\Line, #PB_Ignore, #PB_Ignore, GadgetWidth(ID), *SGP_PARAMS\Thickness)
EndIf
;}
Case #SGP_WM_HIDELINE
;{/// SHOW DASHED LINE
*SGP_PARAMS\LineVisible=0
SetLayeredWindowAttributes_(WindowID(*SGP_PARAMS\Line), 0, 0, #LWA_ALPHA)
ResizeWindow(*SGP_PARAMS\Line, #PB_Ignore, #PB_Ignore, 0, 0)
;}
Case #WM_MOUSEMOVE
;{/// MOVE DASHED LINE
Protected x=(GetGadgetState(ID))+(DesktopMouseX()-*SGP_PARAMS\x)
Protected y=(GetGadgetState(ID))+(DesktopMouseY()-*SGP_PARAMS\y)
;snap auto
If y<*SGP_PARAMS\Snap\Top : y=*SGP_PARAMS\Limit\Top : EndIf
If x<*SGP_PARAMS\Snap\Left : x=*SGP_PARAMS\Limit\Left : EndIf
If x>*SGP_PARAMS\Snap\Right : x=*SGP_PARAMS\Limit\Right : EndIf
If y>*SGP_PARAMS\Snap\Bottom : y=*SGP_PARAMS\Limit\Bottom : EndIf
;move limits
If y<*SGP_PARAMS\Limit\Top : y=*SGP_PARAMS\Limit\Top : EndIf
If x<*SGP_PARAMS\Limit\Left : x=*SGP_PARAMS\Limit\Left : EndIf
If x>*SGP_PARAMS\Limit\Right : x=*SGP_PARAMS\Limit\Right : EndIf
If y>*SGP_PARAMS\Limit\Bottom : y=*SGP_PARAMS\Limit\Bottom : EndIf
If *SGP_PARAMS\Vertical
ResizeWindow(*SGP_PARAMS\Line, *SGP_PARAMS\LinePos\left+x, #PB_Ignore, #PB_Ignore, #PB_Ignore)
Else
ResizeWindow(*SGP_PARAMS\Line, #PB_Ignore, *SGP_PARAMS\LinePos\top+y, #PB_Ignore, #PB_Ignore)
EndIf
;show cursor
PostMessage_(WindowID(*SGP_PARAMS\Line), #SGP_WM_SHOWCURSOR, 0, 0)
;}
Case #WM_LBUTTONUP
;{/// RELEASE DASHED LINE
If *SGP_PARAMS\LineVisible
Protected LinePos
If *SGP_PARAMS\Vertical
LinePos=WindowX(*SGP_PARAMS\Line)-*SGP_PARAMS\LinePos\left
Else
LinePos=WindowY(*SGP_PARAMS\Line)-*SGP_PARAMS\LinePos\top
EndIf
PostMessage_(GadgetID(ID), #SGP_WM_SAVEUNSNAPPOS, 0, LinePos)
PostMessage_(WindowID(*SGP_PARAMS\Line), #SGP_WM_HIDELINE, 0, 0)
SetGadgetState(ID, LinePos)
;send PB event
PostMessage_(GadgetID(ID), #SGP_WM_SENDEVENT, 0, #PB_EventType_Change)
EndIf
;release captured line
ReleaseCapture_()
;}
EndSelect
EndIf
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
ProcedureDLL SGP_LineImages(colorRGBA=$1E000000)
Protected c=RGB(Red(colorRGBA), Green(colorRGBA), Blue(colorRGBA))
Protected alpha=Alpha(colorRGBA)
;create transparent windows
Protected style=#PB_Window_NoGadgets | #PB_Window_Invisible | #PB_Window_BorderLess
Protected parent=OpenWindow(#PB_Any, 0, 0, 0, 0, "", style)
SGP_Line=OpenWindow(#PB_Any, 0, 0, 0, 0, "", style, WindowID(parent))
SetWindowColor(SGP_Line, c)
DisableWindow(SGP_Line, 1)
StickyWindow(SGP_Line, 1)
ShowWindow_(WindowID(SGP_Line), #SW_SHOWNA)
;set transparent fx
Protected winLine=WindowID(SGP_Line)
Protected winstyle=GetWindowLongPtr_(winLine, #GWL_EXSTYLE) | #WS_EX_LAYERED
SetWindowLongPtr_(winLine, #GWL_EXSTYLE, winstyle)
SetLayeredWindowAttributes_(winLine, 0, alpha, #LWA_ALPHA)
;set callback
SetWindowCallback(@SGP_LineCB(), SGP_Line)
EndProcedure
ProcedureDLL SGP_GripImages(ID, Width, Height, Vertical, Focused)
; ====================
; Draw the default grip images
; ====================
Protected Img=CreateImage(#PB_Any, Width, Height, 32)
StartDrawing(ImageOutput(Img))
Protected dot
Protected f1=RGB(189, 204, 254)
Protected f2=GetSysColor_(#COLOR_BTNFACE)
Protected c1=GetSysColor_(#COLOR_BTNSHADOW)
Protected c2=GetSysColor_(#COLOR_BTNHILIGHT)
;background rectangle
If Focused
Box(0, 0, Width, Height, f1)
Else
Box(0, 0, Width, Height, f2)
EndIf
If Vertical
;borders
Line(0, 0, Width, 1, c1)
Line(0, 1, Width, 1, c2)
Line(0, Height-2, Width, 1, c1)
Line(0, Height-1, Width, 1, c2)
;dots
For dot=10 To Height-10 Step 3
Line(Width/2-1, dot, 2, 1, c1)
Next
Else
;borders
Line(0, 0, 1, Height, c1)
Line(1, 0, 1, Height, c2)
Line(Width-2, 0, 1, Height, c1)
Line(Width-1, 0, 1, Height, c2)
;dots
For dot=10 To Width-10 Step 3
Line(dot, Height/2-1, 1, 2, c1)
Line(dot, Height/2+1, 1, 1, c2)
Next
EndIf
StopDrawing()
ProcedureReturn Img
EndProcedure
ProcedureDLL SGP_CB(Window, Message, wParam, lParam)
Protected ID=GetProp_(Window, "SplitterGadgetPlus")
Protected *SGP_PARAMS.SGP_PARAMS=GetGadgetData(ID)
;{/// BAR LOCKED
Select Message
Case #WM_LBUTTONDOWN, #WM_LBUTTONUP, #WM_MOUSEMOVE, #WM_LBUTTONDBLCLK
If *SGP_PARAMS\Locked
SetCursor_(SGP_Cursor_Arrow)
;disable normal behaviour...
ProcedureReturn 1
EndIf
EndSelect
;}
Select Message
Case #WM_DESTROY
;{/// FREE GADGET
Protected CB=*SGP_PARAMS\CB
If *SGP_PARAMS_LINE=*SGP_PARAMS : *SGP_PARAMS_LINE=0 : EndIf
If IsGadget(*SGP_PARAMS\Grip) : FreeGadget(*SGP_PARAMS\Grip) : EndIf
If IsImage(*SGP_PARAMS\GripImg1) : FreeImage(*SGP_PARAMS\GripImg1) : EndIf
SetWindowLong_(GadgetID(ID), #GWL_WNDPROC, CB)
SetGadgetData(ID, 0)
FreeMemory(*SGP_PARAMS)
ProcedureReturn CallWindowProc_(CB, Window, Message, wParam, lParam)
;}
Case #WM_LBUTTONDOWN
;{/// CAPTURE LINE
;show cursor
SendMessage_(GadgetID(ID), #SGP_WM_SHOWCURSOR, 0, 0)
*SGP_PARAMS_LINE=*SGP_PARAMS
;line position
*SGP_PARAMS\Pos=GetGadgetState(ID)
;line limits
*SGP_PARAMS\Limit\Left=GetGadgetAttribute(ID, #PB_Splitter_FirstMinimumSize)
*SGP_PARAMS\Limit\Top=GetGadgetAttribute(ID, #PB_Splitter_FirstMinimumSize)
*SGP_PARAMS\Limit\Right=GadgetWidth(ID)-*SGP_PARAMS\Thickness-GetGadgetAttribute(ID, #PB_Splitter_SecondMinimumSize)
*SGP_PARAMS\Limit\Bottom=GadgetHeight(ID)-*SGP_PARAMS\Thickness-GetGadgetAttribute(ID, #PB_Splitter_SecondMinimumSize)
*SGP_PARAMS\Snap=*SGP_PARAMS\Limit
*SGP_PARAMS\Snap\Left+*SGP_PARAMS\SnapFirst
*SGP_PARAMS\Snap\Top+*SGP_PARAMS\SnapFirst
*SGP_PARAMS\Snap\Right-*SGP_PARAMS\SnapSecond
*SGP_PARAMS\Snap\Bottom-*SGP_PARAMS\SnapSecond
;line layout
If *SGP_PARAMS\Dashed=0 Or (*SGP_PARAMS\GripWidth=0 Or *SGP_PARAMS\GripFocus=1)
GetWindowRect_(GadgetID(ID), @*SGP_PARAMS\LinePos)
If *SGP_PARAMS\Vertical
*SGP_PARAMS\x=DesktopMouseX()
ResizeWindow(*SGP_PARAMS\Line, *SGP_PARAMS\LinePos\left+GetGadgetState(ID), *SGP_PARAMS\LinePos\top, *SGP_PARAMS\Thickness, GadgetHeight(ID))
Else
*SGP_PARAMS\y=DesktopMouseY()
ResizeWindow(*SGP_PARAMS\Line, *SGP_PARAMS\LinePos\left, *SGP_PARAMS\LinePos\top+GetGadgetState(ID), GadgetWidth(ID), *SGP_PARAMS\Thickness)
EndIf
EndIf
;line display
If *SGP_PARAMS\Dashed
If *SGP_PARAMS\LineVisible=0 And (*SGP_PARAMS\GripWidth=0 Or *SGP_PARAMS\GripFocus=1)
PostMessage_(WindowID(*SGP_PARAMS\Line), #SGP_WM_SHOWLINE, 0, 0)
SetCapture_(WindowID(*SGP_PARAMS\Line))
EndIf
ProcedureReturn 1
Else
If *SGP_PARAMS\LineVisible=0
PostMessage_(WindowID(*SGP_PARAMS\Line), #SGP_WM_SHOWLINE, 0, 0)
EndIf
EndIf
;}
Case #WM_LBUTTONUP
;{/// RELEASE LINE
;show cursor
SendMessage_(GadgetID(ID), #SGP_WM_SHOWCURSOR, 0, 0)
If *SGP_PARAMS\Dashed=0 And GetCapture_()=GadgetID(ID)
If *SGP_PARAMS\LineVisible
PostMessage_(WindowID(*SGP_PARAMS\Line), #WM_LBUTTONUP, 0, 0)
Else
PostMessage_(GadgetID(ID), #SGP_WM_SAVEUNSNAPPOS, 0, GetGadgetState(ID))
;send PB event
PostMessage_(GadgetID(ID), #SGP_WM_SENDEVENT, 0, #PB_EventType_Change)
EndIf
EndIf
;}
Case #WM_LBUTTONDBLCLK
;{/// DOUBLE-CLICK SNAP / UNSNAP
;show cursor
SendMessage_(GadgetID(ID), #SGP_WM_SHOWCURSOR, 0, 0)
Protected Pos=*SGP_PARAMS\Pos
Protected SnapAction
Protected Snap1, Snap2
If *SGP_PARAMS\Vertical
Snap1=*SGP_PARAMS\Limit\Left
Snap2=*SGP_PARAMS\Limit\Right
Else
Snap1=*SGP_PARAMS\Limit\Top
Snap2=*SGP_PARAMS\Limit\Bottom
EndIf
;fix pixel slide
If *SGP_PARAMS\Dashed=0 And Abs(Pos-Snap1)<2 : Pos=Snap1 : EndIf
If *SGP_PARAMS\Dashed=0 And Abs(Pos-Snap2)<2 : Pos=Snap2 : EndIf
;determine snap action
If (*SGP_PARAMS\GripWidth And *SGP_PARAMS\GripFocus=0)
SnapAction=0
ElseIf (Pos=Snap1 Or Pos=Snap2)
SnapAction=#SGP_Action_Unsnap
Else
SnapAction=#SGP_Action_Snap
EndIf
Select SnapAction
Case #SGP_Action_Snap
Select *SGP_PARAMS\SnapDblClick
Case 1
SetGadgetState(ID, Snap1)
*SGP_PARAMS\GripFocus=0
*SGP_PARAMS\UnsnapPos=*SGP_PARAMS\Pos
Case 2
SetGadgetState(ID, Snap2)
*SGP_PARAMS\GripFocus=0
*SGP_PARAMS\UnsnapPos=*SGP_PARAMS\Pos
Default
EndSelect
Case #SGP_Action_Unsnap
PostMessage_(WindowID(*SGP_PARAMS\Line), #SGP_WM_HIDELINE, 0, 0)
SetGadgetState(ID, *SGP_PARAMS\UnsnapPos)
*SGP_PARAMS\GripFocus=0
*SGP_PARAMS\UnsnapPos=#PB_Ignore
EndSelect
;send PB event
PostMessage_(GadgetID(ID), #SGP_WM_SENDEVENT, 0, #PB_EventType_LeftDoubleClick)
PostMessage_(GadgetID(ID), #SGP_WM_SENDEVENT, 0, #PB_EventType_Change)
;}
Case #WM_MOUSEMOVE
;{/// MOVE LINE
;show cursor
SendMessage_(GadgetID(ID), #SGP_WM_SHOWCURSOR, 0, 0)
If GetCapture_()=GadgetID(ID)
Protected Hide.b=1
;snap auto
If *SGP_PARAMS\Vertical
Protected x=GetGadgetState(ID)+GadgetX(ID)
If x<*SGP_PARAMS\Snap\Left : x=*SGP_PARAMS\Limit\Left : Hide=0 : EndIf
If x>*SGP_PARAMS\Snap\Right : x=*SGP_PARAMS\Limit\Right : Hide=0 : EndIf
ResizeWindow(*SGP_PARAMS\Line, *SGP_PARAMS\LinePos\Left+x, #PB_Ignore, #PB_Ignore, #PB_Ignore)
Else
Protected y=GetGadgetState(ID)+GadgetY(ID)
If y<*SGP_PARAMS\Snap\Top : y=*SGP_PARAMS\Limit\Top : Hide=0 : EndIf
If y>*SGP_PARAMS\Snap\Bottom : y=*SGP_PARAMS\Limit\Bottom : Hide=0 : EndIf
ResizeWindow(*SGP_PARAMS\Line, #PB_Ignore, *SGP_PARAMS\LinePos\Top+y, #PB_Ignore, #PB_Ignore)
EndIf
;snap position preview
If Hide
If *SGP_PARAMS\LineVisible
PostMessage_(WindowID(*SGP_PARAMS\Line), #SGP_WM_HIDELINE, 0, 0)
EndIf
Else
If *SGP_PARAMS\LineVisible=0
PostMessage_(WindowID(*SGP_PARAMS\Line), #SGP_WM_SHOWLINE, 0, 0)
EndIf
EndIf
EndIf
;start grip checking
PostMessage_(GadgetID(ID), #SGP_WM_GRIPCHECKING, 0, 0)
;}
Case #WM_PAINT;, #WM_ERASEBKGND
;{/// REDRAW SPLITTER
PostMessage_(GadgetID(ID), #SGP_WM_FIXUP, 0, 0)
PostMessage_(GadgetID(ID), #SGP_WM_SHOWGRIP, 0, 0)
;}
Case #SGP_WM_GRIPCHECKING, #WM_TIMER
;{/// GRIP CHECKING
If *SGP_PARAMS\Dashed And *SGP_PARAMS\GripWidth
Protected GripRect.RECT
GetWindowRect_(GadgetID(*SGP_PARAMS\Grip), @GripRect)
If DesktopMouseX()>=GripRect\Left And DesktopMouseX()<=GripRect\right And DesktopMouseY()>=GripRect\top And DesktopMouseY()<=GripRect\bottom
If *SGP_PARAMS\GripFocus=0
*SGP_PARAMS\GripFocus=1
;use timer to check grip automaticly
SetTimer_(GadgetID(ID), 2000, 100, 0)
PostMessage_(GadgetID(ID), #SGP_WM_SHOWGRIP, 0, 0)
EndIf
Else
If *SGP_PARAMS\GripFocus=1
*SGP_PARAMS\GripFocus=0
;stop grip checking (because mouse pointer is out of area)
KillTimer_(GadgetID(ID), 2000)
PostMessage_(GadgetID(ID), #SGP_WM_SHOWGRIP, 0, 0)
EndIf
EndIf
EndIf
;}
Case #SGP_WM_SHOWCURSOR
;{/// SHOW CURSOR
If *SGP_PARAMS\GripWidth And *SGP_PARAMS\GripFocus=0
;if out of grip area...
SetCursor_(SGP_Cursor_Arrow)
ElseIf *SGP_PARAMS\Vertical
SetCursor_(SGP_Cursor_H)
Else
SetCursor_(SGP_Cursor_V)
EndIf
;}
Case #SGP_WM_SHOWGRIP
;{/// SHOW GRIP
If *SGP_PARAMS\Dashed And *SGP_PARAMS\GripWidth
If *SGP_PARAMS\GripFocus
If GetGadgetState(*SGP_PARAMS\Grip)<>ImageID(*SGP_PARAMS\GripImg2)
SetGadgetState(*SGP_PARAMS\Grip, ImageID(*SGP_PARAMS\GripImg2))
EndIf
Else
If GetGadgetState(*SGP_PARAMS\Grip)<>ImageID(*SGP_PARAMS\GripImg1)
SetGadgetState(*SGP_PARAMS\Grip, ImageID(*SGP_PARAMS\GripImg1))
EndIf
EndIf
EndIf
;}
Case #SGP_WM_FIXUP
;{/// FIX BAR THICKNESS
Protected ModifiedThickness
ModifiedThickness+(#True And *SGP_PARAMS\Thickness=4 And (*SGP_PARAMS\Flags & #PB_Splitter_Separator)=0)
ModifiedThickness+(#True And *SGP_PARAMS\Thickness=7 And (*SGP_PARAMS\Flags & #PB_Splitter_Separator))
;fix bar thickness
If Not ModifiedThickness
Protected ID1=GetGadgetAttribute(ID, #PB_Splitter_FirstGadget)
Protected ID2=GetGadgetAttribute(ID, #PB_Splitter_SecondGadget)
If *SGP_PARAMS\Vertical
x=GadgetWidth(ID1)+*SGP_PARAMS\Thickness
Protected w=GadgetWidth(ID)-x
ResizeGadget(ID2, x, #PB_Ignore, w, #PB_Ignore)
Else
y=GadgetHeight(ID1)+*SGP_PARAMS\Thickness
Protected h=GadgetHeight(ID)-y
ResizeGadget(ID2, #PB_Ignore, y, #PB_Ignore, h)
EndIf
EndIf
;}
;{/// FIX GRIP SIZE AND IMAGES
If GetGadgetState(*SGP_PARAMS\Grip)
If *SGP_PARAMS\Vertical
;fix grip position
ResizeGadget(*SGP_PARAMS\Grip, GetGadgetState(ID), (GadgetHeight(ID)-*SGP_PARAMS\gripWidth)/2, #PB_Ignore, #PB_Ignore)
;fix grip images
If ImageWidth(*SGP_PARAMS\GripImg1)<>*SGP_PARAMS\Thickness Or ImageHeight(*SGP_PARAMS\GripImg1)<>*SGP_PARAMS\GripWidth
FreeImage(*SGP_PARAMS\GripImg1) : *SGP_PARAMS\GripImg1=*SGP_PARAMS\GripImage(ID, *SGP_PARAMS\Thickness, *SGP_PARAMS\GripWidth, *SGP_PARAMS\Vertical, #False)
FreeImage(*SGP_PARAMS\GripImg2) : *SGP_PARAMS\GripImg2=*SGP_PARAMS\GripImage(ID, *SGP_PARAMS\Thickness, *SGP_PARAMS\GripWidth, *SGP_PARAMS\Vertical, #True)
SetGadgetState(*SGP_PARAMS\Grip, ImageID(*SGP_PARAMS\GripImg1))
EndIf
Else
;fix grip position
ResizeGadget(*SGP_PARAMS\Grip, (GadgetWidth(ID)-*SGP_PARAMS\gripWidth)/2, GetGadgetState(ID), #PB_Ignore, #PB_Ignore)
;fix grip images
If ImageWidth(*SGP_PARAMS\GripImg1)<>*SGP_PARAMS\GripWidth Or ImageHeight(*SGP_PARAMS\GripImg1)<>*SGP_PARAMS\Thickness
FreeImage(*SGP_PARAMS\GripImg1) : *SGP_PARAMS\GripImg1=*SGP_PARAMS\GripImage(ID, *SGP_PARAMS\GripWidth, *SGP_PARAMS\Thickness, *SGP_PARAMS\Vertical, #False)
FreeImage(*SGP_PARAMS\GripImg2) : *SGP_PARAMS\GripImg2=*SGP_PARAMS\GripImage(ID, *SGP_PARAMS\GripWidth, *SGP_PARAMS\Thickness, *SGP_PARAMS\Vertical, #True)
SetGadgetState(*SGP_PARAMS\Grip, ImageID(*SGP_PARAMS\GripImg1))
EndIf
EndIf
EndIf
;}
Case #SGP_WM_SENDEVENT
;{/// SEND PB EVENT
Protected EvenType=lparam
Select EvenType
Case #PB_EventType_Change
If GetGadgetState(ID)<>*SGP_PARAMS\Pos
PB_Gadget_SendGadgetCommand(GadgetID(ID), EvenType)
EndIf
Default
PB_Gadget_SendGadgetCommand(GadgetID(ID), EvenType)
EndSelect
;}
Case #SGP_WM_SAVEUNSNAPPOS
;{/// SAVE UNSNAP POS
Protected LinePos=lParam
If *SGP_PARAMS\Vertical
If (LinePos=*SGP_PARAMS\Limit\Right Or LinePos=*SGP_PARAMS\Limit\Left)
If LinePos<>*SGP_PARAMS\Pos
*SGP_PARAMS\UnsnapPos=*SGP_PARAMS\Pos
EndIf
Else
*SGP_PARAMS\UnsnapPos=#PB_Ignore
EndIf
Else
If (LinePos=*SGP_PARAMS\Limit\top Or LinePos=*SGP_PARAMS\Limit\right)
If LinePos<>*SGP_PARAMS\Pos
*SGP_PARAMS\UnsnapPos=*SGP_PARAMS\Pos
EndIf
Else
*SGP_PARAMS\UnsnapPos=#PB_Ignore
EndIf
EndIf
;}
EndSelect
ProcedureReturn CallWindowProc_(*SGP_PARAMS\CB, Window, Message, wParam, lParam)
EndProcedure
ProcedureDLL SGP_SplitterGadget(ID, x, y, Width, Height, Gadget1, Gadget2, Flags=0)
;create line images (transparent or dashed)
SGP_LineImages()
;gadget
Protected result=SplitterGadget(ID, x, y, Width, Height, Gadget1, Gadget2, Flags)
If result=0 : ProcedureReturn 0 : EndIf
If ID=#PB_Any : ID=result : EndIf
;set style (enable double-click)
SetClassLong_(GadgetID(ID), #GCL_STYLE, GetClassLong_(GadgetID(ID), #GCL_STYLE) | #CS_DBLCLKS)
;set parameters
Protected *SGP_PARAMS.SGP_PARAMS=AllocateMemory(SizeOf(SGP_PARAMS))
*SGP_PARAMS\ID=ID
*SGP_PARAMS\Dashed=0
*SGP_PARAMS\Flags=Flags
*SGP_PARAMS\Vertical=Flags & #PB_Splitter_Vertical
*SGP_PARAMS\SnapFirst=0
*SGP_PARAMS\SnapSecond=0
*SGP_PARAMS\UnsnapPos=150;#PB_Ignore
*SGP_PARAMS\GripImg1=CreateImage(#PB_Any, 2, 2, 32)
*SGP_PARAMS\GripImg2=CreateImage(#PB_Any, 2, 2, 32)
*SGP_PARAMS\Line=SGP_Line
*SGP_PARAMS\Parent=UseGadgetList(GadgetID(ID))
If *SGP_PARAMS\Parent
;hidden gadgets for drawing line and grip
If *SGP_PARAMS\Vertical
*SGP_PARAMS\Thickness=(GadgetX(Gadget2)-GadgetWidth(Gadget1))
*SGP_PARAMS\Grip=ImageGadget(#PB_Any, GadgetX(ID)+GetGadgetState(ID), GadgetY(ID), 0, 0, 0)
Else
*SGP_PARAMS\Thickness=(GadgetY(Gadget2)-GadgetHeight(Gadget1))
*SGP_PARAMS\Grip=ImageGadget(#PB_Any, GadgetX(ID), GadgetY(ID)+GetGadgetState(ID), 0, 0, 0)
EndIf
HideGadget(*SGP_PARAMS\Grip, 1)
DisableGadget(*SGP_PARAMS\Grip, 1)
EndIf
UseGadgetList(*SGP_PARAMS\Parent)
SetGadgetData(ID, *SGP_PARAMS)
SetTimer_(GadgetID(ID), 100, 500, 0)
SetProp_(GadgetID(ID), "SplitterGadgetPlus", ID)
;set callbacks
*SGP_PARAMS\CB=SetWindowLong_(GadgetID(ID), #GWL_WNDPROC, @SGP_CB())
ProcedureReturn result
EndProcedure
Macro SplitterGadget
SGP_SplitterGadget
EndMacro
Procedure SetSplitterSnapping(ID, SnapFirst, SnapSecond) ; change snap-to-border distance (disable if ZERO)
Protected *SGP_PARAMS.SGP_PARAMS=GetGadgetData(ID)
*SGP_PARAMS\SnapFirst=SnapFirst
*SGP_PARAMS\SnapSecond=SnapSecond
EndProcedure
Procedure SetSplitterDoubleClick(ID, DblClickToSnap=#True) ; snap-to-border via double-click (disable if #FALSE)
Protected *SGP_PARAMS.SGP_PARAMS=GetGadgetData(ID)
*SGP_PARAMS\SnapDblClick=0
If DblClickToSnap
If *SGP_PARAMS\Flags & #PB_Splitter_FirstFixed
*SGP_PARAMS\SnapDblClick=1
EndIf
If *SGP_PARAMS\Flags & #PB_Splitter_SecondFixed
*SGP_PARAMS\SnapDblClick=2
EndIf
EndIf
EndProcedure
Procedure SetSplitterDashed(ID, Thickness=0, GripWidth=0, *GripDrawingFunction=#Null) ; change bar thickness (between 4 - 16), grip size (disable if ZERO)
Protected *SGP_PARAMS.SGP_PARAMS=GetGadgetData(ID)
;enable dashed bar
*SGP_PARAMS\Dashed=1
;update bar thickness
If Thickness>16 : Thickness=16 : EndIf
If Thickness<4 : Thickness=4 : EndIf
If *SGP_PARAMS\Thickness<>Thickness
*SGP_PARAMS\Thickness=Thickness
PostMessage_(GadgetID(ID), #SGP_WM_FIXUP, 0, 0)
EndIf
;update grip button ( optional custom grip painter )
If gripWidth<1
*SGP_PARAMS\GripWidth=0
*SGP_PARAMS\GripImage=#Null
SetGadgetState(*SGP_PARAMS\Grip, 0)
HideGadget(*SGP_PARAMS\Grip, 1)
Else
*SGP_PARAMS\GripWidth=GripWidth
If *GripDrawingFunction
*SGP_PARAMS\GripImage=*GripDrawingFunction
Else
*SGP_PARAMS\GripImage=@SGP_GripImages()
EndIf
SetGadgetState(*SGP_PARAMS\Grip, ImageID(*SGP_PARAMS\GripImg1))
HideGadget(*SGP_PARAMS\Grip, 0)
PostMessage_(GadgetID(ID), #SGP_WM_FIXUP, 0, 0)
EndIf
EndProcedure
Procedure LockSplitter(ID, Locked=#True) ; lock splitter bar (unlock if #FALSE)
Protected *SGP_PARAMS.SGP_PARAMS=GetGadgetData(ID)
*SGP_PARAMS\Locked=Locked
EndProcedure
Procedure SwapSplitter(ID, SwapBarPosition=#True, SwapSnapping=#True, SwapMinimumSize=#True, SwapFixedGadget=#True, SwapGadgets=#True) ; swap gadgets and other options
Protected *SGP_PARAMS.SGP_PARAMS=GetGadgetData(ID)
Protected SGP_PARAMS.SGP_PARAMS
CopyMemory(*SGP_PARAMS, @SGP_PARAMS, SizeOf(SGP_PARAMS))
If SwapFixedGadget
If SGP_PARAMS\Flags & #PB_Splitter_SecondFixed
SGP_PARAMS\Flags | #PB_Splitter_FirstFixed & ~#PB_Splitter_SecondFixed
ElseIf SGP_PARAMS\Flags & #PB_Splitter_FirstFixed
SGP_PARAMS\Flags | #PB_Splitter_SecondFixed & ~#PB_Splitter_FirstFixed
EndIf
EndIf
If SwapSnapping
Swap SGP_PARAMS\SnapFirst, SGP_PARAMS\SnapSecond
EndIf
Protected Pos=GetGadgetState(ID)
If SwapBarPosition
If *SGP_PARAMS\Vertical
Pos+(GadgetWidth(ID)-2*Pos-*SGP_PARAMS\Thickness)
Else
Pos+(GadgetHeight(ID)-2*Pos-*SGP_PARAMS\Thickness)
EndIf
EndIf
Protected Min1=GetGadgetAttribute(ID, #PB_Splitter_FirstMinimumSize)
Protected Min2=GetGadgetAttribute(ID, #PB_Splitter_SecondMinimumSize)
If SwapMinimumSize
Swap Min1, Min2
EndIf
Protected Gadget1=GetGadgetAttribute(ID, #PB_Splitter_FirstGadget)
Protected Gadget2=GetGadgetAttribute(ID, #PB_Splitter_SecondGadget)
If SwapGadgets
Swap Gadget1, Gadget2
EndIf
Protected CurrentGadgetList=UseGadgetList(*SGP_PARAMS\Parent)
If CurrentGadgetList
;preserver gadget children
Protected dummy=TextGadget(#PB_Any, 0, 0, 0, 0, "")
SetGadgetAttribute(ID, #PB_Splitter_FirstGadget, dummy)
SetGadgetAttribute(ID, #PB_Splitter_SecondGadget, dummy)
;recreate gadget
SplitterGadget(ID, GadgetX(ID), GadgetY(ID), GadgetWidth(ID), GadgetHeight(ID), Gadget1, Gadget2, SGP_PARAMS\Flags)
SetGadgetAttribute(ID, #PB_Splitter_FirstMinimumSize, Min1)
SetGadgetAttribute(ID, #PB_Splitter_SecondMinimumSize, Min2)
SetGadgetState(ID, Pos)
If SGP_PARAMS\Dashed
SetSplitterDashed(ID, SGP_PARAMS\Thickness, SGP_PARAMS\GripWidth, SGP_PARAMS\GripImage)
EndIf
SetSplitterSnapping(ID, SGP_PARAMS\SnapFirst, SGP_PARAMS\SnapSecond)
SetSplitterDoubleClick(ID, SGP_PARAMS\SnapDblClick)
UseGadgetList(CurrentGadgetList)
EndIf
EndProcedure
Procedure.b SplitterLocked(ID) ;Returns #True if splitter is locked
Protected *SGP_PARAMS.SGP_PARAMS=GetGadgetData(ID)
If *SGP_PARAMS\Locked
ProcedureReturn #True
EndIf
EndProcedure
Procedure.b SplitterSnapped(ID) ;Returns 1 or 2 if splitter snapped border 1 or 2 is snapped (not snapped if ZERO)
Protected *SGP_PARAMS.SGP_PARAMS=GetGadgetData(ID)
Protected snapPos1=GetGadgetAttribute(ID, #PB_Splitter_FirstMinimumSize)
Protected snapPos2
If *SGP_PARAMS\Vertical
snapPos2=GadgetWidth(ID)-GetGadgetAttribute(ID, #PB_Splitter_FirstMinimumSize)-*SGP_PARAMS\Thickness
Else
snapPos2=GadgetHeight(ID)-GetGadgetAttribute(ID, #PB_Splitter_SecondMinimumSize)-*SGP_PARAMS\Thickness
EndIf
If *SGP_PARAMS\SnapFirst And GetGadgetState(ID)=snapPos1
ProcedureReturn 1
ElseIf *SGP_PARAMS\SnapSecond And GetGadgetState(ID)=snapPos2
ProcedureReturn 2
EndIf
EndProcedure
; ********************
; EXAMPLE @ eddy
; ********************
Enumeration
#FirstWindow
#SecondWindow
#Splitter1
#Splitter2
#w=800
#h=600
EndEnumeration
If OpenWindow(#FirstWindow, 0, 0, 410, 440, "Dashed SplitterGadget And Auto Snap-To-Border", #PB_Window_SizeGadget | #PB_Window_SystemMenu)
WindowBounds(#FirstWindow, 300, 200, #PB_Ignore, #PB_Ignore)
SmartWindowRefresh(#FirstWindow, 1)
ButtonGadget(300, 5, 5, 80, 20, "SWAP")
PanelGadget(10, 0, 0, 0, 0)
AddGadgetItem(10, -1, "Tab 1")
ButtonGadget(22, 0, 0, 80, 30, "CLICK!")
CloseGadgetList()
ButtonGadget(11, 0, 0, 0, 0, "BIG CLICK!")
SplitterGadget(#Splitter1, 5, 30, 0, 0, 10, 11, #PB_Splitter_FirstFixed)
SetGadgetAttribute(#Splitter1, #PB_Splitter_FirstMinimumSize, 20)
SetGadgetAttribute(#Splitter1, #PB_Splitter_SecondMinimumSize, 10)
SetSplitterDoubleClick(#Splitter1, #True)
SetSplitterSnapping(#Splitter1, 50, 100)
SetSplitterDashed(#Splitter1, 8, 100)
;SetSplitterDashed(#Splitter1, 8, 100, @MyGripDrawingFunction())
EndIf
If OpenWindow(#SecondWindow, 220, 220, 410, 440, "SplitterGadget : enable / disable options", #PB_Window_SizeGadget | #PB_Window_SystemMenu)
WindowBounds(#SecondWindow, 300, 200, #PB_Ignore, #PB_Ignore)
SmartWindowRefresh(#SecondWindow, 1)
CheckBoxGadget(100, 5, 5, 80, 20, "LOCKED")
CheckBoxGadget(101, 100, 5, 130, 20, "DOUBLE-CLICK SNAP")
CheckBoxGadget(102, 250, 5, 120, 20, "SNAP-TO-BORDER")
SetGadgetState(101, #True)
SetGadgetState(102, #True)
ContainerGadget(800, 0, 0, 0, 0, #PB_Container_Double) : CloseGadgetList()
ContainerGadget(900, 0, 0, 0, 0, #PB_Container_Double) : CloseGadgetList()
SetGadgetItemColor(800, 0, #PB_Gadget_BackColor, $F0F0F0)
SetGadgetColor(900, #PB_Gadget_BackColor, $ACACAC)
SplitterGadget(#Splitter2, 5, 30, 0, 0, 800, 900, #PB_Splitter_Vertical | #PB_Splitter_FirstFixed | #PB_Splitter_Separator)
SetSplitterSnapping(#Splitter2, 90, 30)
SetSplitterDoubleClick(#Splitter2, #True)
EndIf
Repeat
Define e=WaitWindowEvent()
Define g=EventGadget()
Define t=EventType()
Define w=EventWindow()
Select e
Case #PB_Event_CloseWindow
End
Case #PB_Event_SizeWindow
Select w
Case #FirstWindow
ResizeGadget(#Splitter1, #PB_Ignore, #PB_Ignore, WindowWidth(w)-10, WindowHeight(w)-40)
Case #SecondWindow
ResizeGadget(#Splitter2, #PB_Ignore, #PB_Ignore, WindowWidth(w)-10, WindowHeight(w)-40)
EndSelect
Case #PB_Event_Gadget
Select g
Case #Splitter1
If t=#PB_EventType_LeftDoubleClick
Debug "Double-Click : #Splitter1"
ElseIf t=#PB_EventType_Change
Debug "Splitter1 : pos="+Str(GetGadgetState(g))
EndIf
Case #Splitter2
If t=#PB_EventType_LeftDoubleClick
Debug "Double-Click : #Splitter2"
ElseIf t=#PB_EventType_Change
Debug "Splitter2 : pos="+Str(GetGadgetState(g))
EndIf
Case 300
SwapSplitter(#Splitter1)
Case 100
LockSplitter(#Splitter2, GetGadgetState(100))
Case 101
SetSplitterDoubleClick(#Splitter2, GetGadgetState(101))
Case 102
SetSplitterSnapping(#Splitter2, 90*GetGadgetState(102), 30*GetGadgetState(102))
EndSelect
Default
EndSelect
ForEver