SplitterGadget+ dashed bar, border snap, thickness,grip,swap
Posted: Thu Aug 29, 2013 6:51 am
- Customizations supported
- grip size(disable If 0)
- bar thickness
- grip images
- border snapping distances (disable If 0)
- enable auto snapping by double-click(disable If #False)
- lock splitter bar(unlock If #False) - Methods
-SwapSplitter : Swap gadgets with options
-SplitterLocked : returns #True If the splitter is locked
-SplitterSnapped : returns 1 or 2 if left or right boder snapped (returns 0 if none of them) - Events supported:
-event type: #PB_EventType_LeftDoubleClick
-event type: #PB_EventType_Change
Code: Select all
;:=============================================================================
;:- SplitterPlus.pbi
;:- Author : Eddy
;:- Date : August 29, 2013
;:- Compiler : PureBasic 5.20 LTS
;:- Target OS : Windows
;:- Source --------------------------------------------------------------------
;:- http://www.purebasic.fr/english/viewtopic.php?f=40&t=56290
;:=============================================================================
EnableExplicit
Enumeration
;splitter gadget events (for internal use)
#WM_SPLITTER_POSITION_GRIP_AND_GADGETS=#WM_USER
#WM_SPLITTER_REDRAW_GRIP_IMAGES
#WM_SPLITTER_CHECK_GRIP_FOCUS
#WM_SPLITTER_CHECK_LINE_CAPTURE
#WM_SPLITTER_UPDATE_GRIP_FOCUS
#WM_SPLITTER_UPDATE_GRIP_CURSOR
#WM_SPLITTER_UPDATE_SNAP_ZONE
#WM_SPLITTER_UPDATE_UNSNAPPOS
#WM_SPLITTER_POSTEVENT_CHANGE
#WM_SPLITTER_POSTEVENT_DBLCLICK
#WM_SPLITTER_RELEASE_SPLITBAR_CAPTURE
#WM_SPLITTER_MOVE_SPLITBAR
;dashed bar events (for internal use)
#WM_SPLITTER_RELEASE_LINE_CAPTURE
#WM_SPLITTER_MOVE_LINE
#WM_SPLITTER_SHOW_LINE
#WM_SPLITTER_HIDE_LINE
#WM_SPLITTER_UPDATE_LINE_CURSOR
EndEnumeration
Procedure SplitterCustomCallback(hWnd, message, wParam, lParam)
Static cursorArrow, cursorV, cursorH
If cursorArrow=0
cursorArrow=LoadCursor_(0, #IDC_ARROW)
cursorV=LoadCursor_(0, #IDC_SIZENS)
cursorH=LoadCursor_(0, #IDC_SIZEWE)
EndIf
If GetProp_(hWnd, "PurebasicCustomSplitterCB")
Protected Splitter=GetProp_(hWnd, "PB_ID")
Protected *SplitterID=GadgetID(Splitter)
;{ Get parameters
Protected a=GetGadgetAttribute(Splitter, #PB_Splitter_FirstGadget)
Protected b=GetGadgetAttribute(Splitter, #PB_Splitter_SecondGadget)
Protected verticalBar=GetProp_(*SplitterID, "VerticalBar")
Protected grip=GetProp_(*SplitterID, "Grip")
Protected gripVisible=GetProp_(*SplitterID, "GripVisible")
Protected gripWidth=GetProp_(*SplitterID, "GripWidth")
Protected gripFocus=GetProp_(*SplitterID, "GripFocus")
Protected gripNormal=GetProp_(*SplitterID, "GripNormal")
Protected thickness=GetProp_(*SplitterID, "Thickness")
Protected snapFirst=GetProp_(*SplitterID, "SnapFirst")
Protected snapSecond=GetProp_(*SplitterID, "SnapSecond")
Protected dblClickToSnap=GetProp_(*SplitterID, "DblClickToSnap")
Protected locked=GetProp_(*SplitterID, "Locked")
Protected focused=GetProp_(*SplitterID, "Focused")
Protected *snap.RECT=GetProp_(*SplitterID, "Snap")
Protected *limit.RECT=GetProp_(*SplitterID, "Limit")
Protected lastPos=GetProp_(*SplitterID, "LastPos")
Protected parentWindow=GetProp_(GetAncestor_(*SplitterID, #GA_ROOT), "PB_WindowID")-1
Protected lx=GadgetX(Splitter, #PB_Gadget_ScreenCoordinate)
Protected ly=GadgetY(Splitter, #PB_Gadget_ScreenCoordinate)
Protected line=GetProp_(*SplitterID, "Line")
If IsWindow(line) : Protected *lineID=WindowID(line) : EndIf
;}
If locked
Select message
Case #WM_MOUSEMOVE, #WM_LBUTTONDOWN, #WM_LBUTTONUP, #WM_LBUTTONDBLCLK
;{ Locked splitter
SetCursor_(cursorArrow) ;default cursor
ProcedureReturn 1 ;disable normal behaviour
;}
EndSelect
EndIf
If gripVisible
Select message
Case #WM_SPLITTER_POSITION_GRIP_AND_GADGETS
;{ Position grip and gadgets
If verticalBar
Protected x=GadgetWidth(a) + thickness
ResizeGadget(b, x, #PB_Ignore, GadgetWidth(Splitter)-x, #PB_Ignore)
ResizeGadget(grip, GetGadgetState(Splitter), (GadgetHeight(Splitter)-gripWidth) / 2, #PB_Ignore, #PB_Ignore)
Else
Protected y=GadgetHeight(a) + thickness
ResizeGadget(b, #PB_Ignore, y, #PB_Ignore, GadgetHeight(Splitter)-y)
ResizeGadget(grip, (GadgetWidth(Splitter)-gripWidth) / 2, GetGadgetState(Splitter), #PB_Ignore, #PB_Ignore)
EndIf
;}
Case #WM_SPLITTER_REDRAW_GRIP_IMAGES
;{ Redraw grip images
Protected gripImage=wParam
If StartDrawing(ImageOutput(gripImage))
Protected dot
Protected f1=RGB(189, 204, 254)
Protected f2=GetSysColor_(#COLOR_BTNFACE)
Protected c1=GetSysColor_(#COLOR_BTNSHADOW)
Protected c2=GetSysColor_(#COLOR_BTNHILIGHT)
Protected w=ImageWidth(gripImage)
Protected h=ImageHeight(gripImage)
;background rectangle
If gripImage=gripFocus
Box(0, 0, w, h, f1)
Else
Box(0, 0, w, h, f2)
EndIf
If verticalBar
;borders
Line(0, 0, w, 1, c1)
Line(0, 1, w, 1, c2)
Line(0, h-2, w, 1, c1)
Line(0, h-1, w, 1, c2)
;dots
For dot=10 To h-10 Step 3
Line(w / 2-1, dot, 2, 1, c1)
Next
Else
;borders
Line(0, 0, 1, h, c1)
Line(1, 0, 1, h, c2)
Line(w-2, 0, 1, h, c1)
Line(w-1, 0, 1, h, c2)
;dots
For dot=10 To w-10 Step 3
Line(dot, h / 2-1, 1, 2, c1)
Line(dot, h / 2 + 1, 1, 1, c2)
Next
EndIf
StopDrawing()
EndIf
;}
Case #WM_SPLITTER_CHECK_GRIP_FOCUS
;{ Check if grip has focus
If DesktopMouseX()>=GadgetX(grip, #PB_Gadget_ScreenCoordinate) And
DesktopMouseX()<(GadgetX(grip, #PB_Gadget_ScreenCoordinate) + GadgetWidth(grip)) And
DesktopMouseY()>=GadgetY(grip, #PB_Gadget_ScreenCoordinate) And
DesktopMouseY()<(GadgetY(grip, #PB_Gadget_ScreenCoordinate) + GadgetHeight(grip))
If focused=0
SetProp_(*SplitterID, "Focused", 1)
;use timer to check grip automaticly
SetTimer_(*SplitterID, 2000, 100, 0)
SendMessage_(*SplitterID, #WM_SPLITTER_UPDATE_GRIP_FOCUS, 0, 0)
EndIf
Else
If focused=1
SetProp_(*SplitterID, "Focused", 0)
;stop grip checking (because mouse pointer is out of area)
KillTimer_(*SplitterID, 2000)
SendMessage_(*SplitterID, #WM_SPLITTER_UPDATE_GRIP_FOCUS, 0, 0)
EndIf
EndIf
;}
Case #WM_SPLITTER_UPDATE_GRIP_FOCUS
;{ Show or Hide grip focus
If focused
If GetGadgetState(grip)<>ImageID(gripFocus)
SetGadgetState(grip, ImageID(gripFocus))
EndIf
Else
If GetGadgetState(grip)<>ImageID(gripNormal)
SetGadgetState(grip, ImageID(gripNormal))
EndIf
EndIf
;}
Case #WM_SPLITTER_UPDATE_GRIP_CURSOR
;{ Show cursor if grip focused or not
If Not focused
SetCursor_(cursorArrow)
ElseIf verticalBar
SetCursor_(cursorH)
Else
SetCursor_(cursorV)
EndIf
;}
EndSelect
Else
Select message
Case #WM_SPLITTER_RELEASE_SPLITBAR_CAPTURE
;{ Release splitter bar (and snap it if possible)
If GetCapture_()=*SplitterID
If GetProp_(*lineID, "LineVisible")
SendMessage_(*lineID, #WM_SPLITTER_RELEASE_LINE_CAPTURE, 0, 0)
Else
SendMessage_(*SplitterID, #WM_SPLITTER_UPDATE_UNSNAPPOS, 0, GetGadgetState(Splitter))
PostMessage_(*SplitterID, #WM_SPLITTER_POSTEVENT_CHANGE, 0, 0)
EndIf
EndIf
;}
Case #WM_SPLITTER_MOVE_SPLITBAR
;{ Move splitter bar
If GetCapture_()=*SplitterID
Protected Hide.b=1
;snap auto
If verticalBar
x=GetGadgetState(Splitter)
If x<*snap\Left : x=*limit\Left : Hide=0 : EndIf
If x>*snap\Right : x=*limit\Right : Hide=0 : EndIf
ResizeWindow(line, lx + x, #PB_Ignore, #PB_Ignore, #PB_Ignore)
Else
y=GetGadgetState(Splitter)
If y<*snap\Top : y=*limit\Top : Hide=0 : EndIf
If y>*snap\Bottom : y=*limit\Bottom : Hide=0 : EndIf
ResizeWindow(line, #PB_Ignore, ly + y, #PB_Ignore, #PB_Ignore)
EndIf
;show or hide snap position preview
If Hide
If GetProp_(*lineID, "LineVisible")
PostMessage_(*lineID, #WM_SPLITTER_HIDE_LINE, 0, 0)
EndIf
Else
If GetProp_(*lineID, "LineVisible")=0
PostMessage_(*lineID, #WM_SPLITTER_SHOW_LINE, 0, 0)
EndIf
EndIf
EndIf
;}
EndSelect
EndIf
Select message
Case #WM_SPLITTER_CHECK_LINE_CAPTURE
;{ Position line and drag line if possible
SetProp_(*SplitterID, "LastPos", GetGadgetState(Splitter))
SetProp_(*lineID, "Splitter", Splitter)
If verticalBar
SetProp_(*lineID, "LineDragX", DesktopMouseX())
ResizeWindow(line, lx + GetGadgetState(Splitter), ly, Thickness, GadgetHeight(Splitter))
Else
SetProp_(*lineID, "LineDragY", DesktopMouseY())
ResizeWindow(line, lx, ly + GetGadgetState(Splitter), GadgetWidth(Splitter), Thickness)
EndIf
If gripVisible
If GetProp_(*lineID, "LineVisible")=0 And focused
SendMessage_(*lineID, #WM_SPLITTER_SHOW_LINE, 0, 0)
SetCapture_(*lineID)
EndIf
ProcedureReturn 1
Else
If GetProp_(*lineID, "LineVisible")=0
SendMessage_(*lineID, #WM_SPLITTER_SHOW_LINE, 0, 0)
EndIf
EndIf
;}
Case #WM_SPLITTER_UPDATE_SNAP_ZONE
;{ Update splitterbar limit and snap area
*limit\Left=GetGadgetAttribute(Splitter, #PB_Splitter_FirstMinimumSize)
*limit\Top=GetGadgetAttribute(Splitter, #PB_Splitter_FirstMinimumSize)
*limit\Right=GadgetWidth(Splitter)-thickness-GetGadgetAttribute(Splitter, #PB_Splitter_SecondMinimumSize)
*limit\Bottom=GadgetHeight(Splitter)-thickness-GetGadgetAttribute(Splitter, #PB_Splitter_SecondMinimumSize)
CopyStructure(*limit, *snap, RECT)
*snap\Left + snapFirst
*snap\Top + snapFirst
*snap\Right-snapSecond
*snap\Bottom-snapSecond
;}
Case #WM_SPLITTER_UPDATE_UNSNAPPOS
;{ Update unsnap position
Protected LinePos=lParam
If verticalBar
If (LinePos=*Limit\Right Or LinePos=*Limit\Left) And LinePos<>lastPos
SetProp_(*SplitterID, "UnsnapPos", lastPos)
EndIf
Else
If (LinePos=*Limit\top Or LinePos=*Limit\right) And LinePos<>lastPos
SetProp_(*SplitterID, "UnsnapPos", lastPos)
EndIf
EndIf
;}
Case #WM_SPLITTER_POSTEVENT_CHANGE
;{ Event CHANGE
PostEvent(#PB_Event_Gadget, parentWindow, Splitter, #PB_EventType_Change)
;}
Case #WM_SPLITTER_POSTEVENT_DBLCLICK
;{ Event DBLCLICK
PostEvent(#PB_Event_Gadget, parentWindow, Splitter, #PB_EventType_LeftDoubleClick)
;}
EndSelect
Select message
Case #WM_DESTROY
FreeMemory(*snap)
FreeMemory(*limit)
FreeGadget(grip)
FreeImage(gripFocus)
FreeImage(gripNormal)
Case #WM_PAINT
PostMessage_(*SplitterID, #WM_SPLITTER_POSITION_GRIP_AND_GADGETS, 0, 0)
PostMessage_(*SplitterID, #WM_SPLITTER_UPDATE_GRIP_FOCUS, 0, 0)
Case #WM_LBUTTONDOWN
SendMessage_(*SplitterID, #WM_SPLITTER_UPDATE_GRIP_CURSOR, 0, 0)
SendMessage_(*SplitterID, #WM_SPLITTER_UPDATE_SNAP_ZONE, 0, 0)
If SendMessage_(*SplitterID, #WM_SPLITTER_CHECK_LINE_CAPTURE, 0, 0)
ProcedureReturn 1
EndIf
Case #WM_MOUSEMOVE
SendMessage_(*SplitterID, #WM_SPLITTER_UPDATE_GRIP_CURSOR, 0, 0)
SendMessage_(*SplitterID, #WM_SPLITTER_MOVE_SPLITBAR, 0, 0)
SendMessage_(*SplitterID, #WM_SPLITTER_CHECK_GRIP_FOCUS, 0, 0)
Case #WM_LBUTTONUP
SendMessage_(*SplitterID, #WM_SPLITTER_UPDATE_GRIP_CURSOR, 0, 0)
SendMessage_(*SplitterID, #WM_SPLITTER_RELEASE_SPLITBAR_CAPTURE, 0, 0)
Case #WM_LBUTTONDBLCLK
SendMessage_(*SplitterID, #WM_SPLITTER_UPDATE_GRIP_CURSOR, 0, 0)
Protected Pos=lastPos
Protected SnapAction$=""
Protected Snap1, Snap2
If verticalBar
Snap1=*Limit\Left
Snap2=*Limit\Right
Else
Snap1=*Limit\Top
Snap2=*Limit\Bottom
EndIf
;fix pixel slide
If gripVisible=0 And Abs(Pos-Snap1)<2 : Pos=Snap1 : EndIf
If gripVisible=0 And Abs(Pos-Snap2)<2 : Pos=Snap2 : EndIf
;determine snap action
If gripVisible And Not focused
SnapAction$=""
ElseIf(Pos=Snap1 Or Pos=Snap2)
SnapAction$="UNSNAP_ACTION"
Else
SnapAction$="SNAP_ACTION"
EndIf
Select SnapAction$
Case "SNAP_ACTION"
Select dblClickToSnap
Case 1
SetGadgetState(Splitter, Snap1)
SetProp_(*SplitterID, "Focused", 0)
SetProp_(*SplitterID, "UnsnapPos", lastPos)
Case 2
SetGadgetState(Splitter, Snap2)
SetProp_(*SplitterID, "Focused", 0)
SetProp_(*SplitterID, "UnsnapPos", lastPos)
Default
EndSelect
Case "UNSNAP_ACTION"
PostMessage_(*lineID, #WM_SPLITTER_HIDE_LINE, 0, 0)
SetGadgetState(Splitter, GetProp_(*SplitterID, "UnsnapPos"))
SetProp_(*SplitterID, "Focused", 0)
EndSelect
PostMessage_(*SplitterID, #WM_SPLITTER_POSTEVENT_CHANGE, 0, 0)
PostMessage_(*SplitterID, #WM_SPLITTER_POSTEVENT_DBLCLICK, 0, 0)
Case #WM_TIMER
SendMessage_(*SplitterID, #WM_SPLITTER_CHECK_GRIP_FOCUS, 0, 0)
EndSelect
ProcedureReturn CallWindowProc_(GetProp_(hWnd, "PurebasicCustomSplitterCB"), hWnd, message, wParam, lParam)
EndIf
If GetProp_(hWnd, "PurebasicCustomSplitterLineCB")
line=GetProp_(hWnd, "PB_WindowID")-1
*lineID=WindowID(line)
Splitter=GetProp_(*lineID, "Splitter")
If IsGadget(Splitter)
*SplitterID=GadgetID(Splitter)
verticalBar=GetProp_(*SplitterID, "VerticalBar")
thickness=GetProp_(*SplitterID, "Thickness")
lx=GadgetX(Splitter, #PB_Gadget_ScreenCoordinate)
ly=GadgetY(Splitter, #PB_Gadget_ScreenCoordinate)
EndIf
Select message
Case #WM_SPLITTER_UPDATE_LINE_CURSOR
;{ Show cursor (for vertical or horizontal scrolling)
If verticalBar
SetCursor_(cursorH)
Else
SetCursor_(cursorV)
EndIf
;}
Case #WM_SPLITTER_SHOW_LINE
;{ Show line (transparency, resize)
SetProp_(*lineID, "LineVisible", 1)
SetLayeredWindowAttributes_(*lineID, 0, GetProp_(*lineID, "LineAlpha"), #LWA_ALPHA)
If verticalBar
ResizeWindow(Line, #PB_Ignore, #PB_Ignore, Thickness, GadgetHeight(Splitter))
Else
ResizeWindow(Line, #PB_Ignore, #PB_Ignore, GadgetWidth(Splitter), Thickness)
EndIf
;}
Case #WM_SPLITTER_HIDE_LINE
;{ Hide line (full transparency, no size)
SetProp_(*lineID, "LineVisible", 0)
SetLayeredWindowAttributes_(*lineID, 0, 0, #LWA_ALPHA)
ResizeWindow(line, #PB_Ignore, #PB_Ignore, 0, 0)
;}
Case #WM_SPLITTER_MOVE_LINE
;{ Move line
*snap.RECT=GetProp_(*SplitterID, "Snap")
*limit.RECT=GetProp_(*SplitterID, "Limit")
If verticalBar
x=(GetGadgetState(Splitter)) + (DesktopMouseX()-GetProp_(*lineID, "LineDragX"))
;snap auto
If x<*snap\Left : x=*limit\Left : EndIf
If x>*snap\Right : x=*limit\Right : EndIf
;move limits
If x<*limit\Left : x=*limit\Left : EndIf
If x>*limit\Right : x=*limit\Right : EndIf
ResizeWindow(Line, lx + x, #PB_Ignore, #PB_Ignore, #PB_Ignore)
Else
y=(GetGadgetState(Splitter)) + (DesktopMouseY()-GetProp_(*lineID, "LineDragY"))
;snap auto
If y<*snap\Top : y=*limit\Top : EndIf
If y>*snap\Bottom : y=*limit\Bottom : EndIf
;move limits
If y<*limit\Top : y=*limit\Top : EndIf
If y>*limit\Bottom : y=*limit\Bottom : EndIf
ResizeWindow(Line, #PB_Ignore, ly + y, #PB_Ignore, #PB_Ignore)
EndIf
;}
Case #WM_SPLITTER_RELEASE_LINE_CAPTURE
;{ Release line capture
If GetProp_(*lineID, "LineVisible")
If verticalBar
LinePos=WindowX(Line)-GadgetX(Splitter, #PB_Gadget_ScreenCoordinate)
Else
LinePos=WindowY(Line)-GadgetY(Splitter, #PB_Gadget_ScreenCoordinate)
EndIf
PostMessage_(*lineID, #WM_SPLITTER_HIDE_LINE, 0, 0)
PostMessage_(*SplitterID, #WM_SPLITTER_UPDATE_UNSNAPPOS, 0, LinePos)
SetGadgetState(Splitter, LinePos)
PostMessage_(*SplitterID, #WM_SPLITTER_POSTEVENT_CHANGE, 0, 0)
EndIf
;release captured line
ReleaseCapture_()
;}
Case #WM_MOUSEMOVE
PostMessage_(*lineID, #WM_SPLITTER_MOVE_LINE, 0, 0)
PostMessage_(*lineID, #WM_SPLITTER_UPDATE_LINE_CURSOR, 0, 0)
Case #WM_LBUTTONUP
PostMessage_(*lineID, #WM_SPLITTER_RELEASE_LINE_CAPTURE, 0, 0)
EndSelect
ProcedureReturn CallWindowProc_(GetProp_(hWnd, "PurebasicCustomSplitterLineCB"), hWnd, message, wParam, lParam)
EndIf
EndProcedure
Procedure SetSplitterEffects(Splitter, Thickness=8, GripWidth=100, SnapFirst=100, SnapSecond=100, DblClickToSnap=1, Locked=#False)
Protected *SplitterID=GadgetID(Splitter)
Static line
If Not line
Protected colorRGBA=$1E000000
;create line windows
Protected parent=OpenWindow(#PB_Any, 0, 0, 0, 0, "", #PB_Window_NoGadgets | #PB_Window_Invisible | #PB_Window_NoActivate)
line=OpenWindow(#PB_Any, 0, 0, 0, 0, "", #PB_Window_NoGadgets | #PB_Window_Invisible | #PB_Window_BorderLess, WindowID(parent))
SetWindowColor(line, RGB(Red(colorRGBA), Green(colorRGBA), Blue(colorRGBA)))
DisableWindow(line, 1)
StickyWindow(line, 1)
HideWindow(line, 0, #PB_Window_NoActivate)
;enable transparent fx
Protected *lineID=WindowID(line)
SetWindowLongPtr_(*lineID, #GWL_EXSTYLE, GetWindowLongPtr_(*lineID, #GWL_EXSTYLE) | #WS_EX_LAYERED)
SetLayeredWindowAttributes_(*lineID, 0, Alpha(colorRGBA), #LWA_ALPHA)
SetProp_(*lineID, "LineAlpha", Alpha(colorRGBA))
;enable line custom effects
SetProp_(*lineID, "PurebasicCustomSplitterLineCB", SetWindowLong_(*lineID, #GWL_WNDPROC, @SplitterCustomCallback()))
EndIf
If GetProp_(*SplitterID, "PurebasicCustomSplitterCB")=0
;enable double-click detection
SetClassLongPtr_(*SplitterID, #GCL_STYLE, GetClassLongPtr_(*SplitterID, #GCL_STYLE) | #CS_DBLCLKS)
;enable splitter custom effects
SetProp_(*SplitterID, "PurebasicCustomSplitterCB", SetWindowLong_(*SplitterID, #GWL_WNDPROC, @SplitterCustomCallback()))
;init snapping
Protected *snap.RECT=AllocateMemory(SizeOf(RECT))
Protected *limit.RECT=AllocateMemory(SizeOf(RECT))
SetProp_(*SplitterID, "Snap", *snap)
SetProp_(*SplitterID, "Limit", *limit)
SetProp_(*SplitterID, "Line", line)
;init grip images and gadget
Protected previousGadgetList=UseGadgetList(*SplitterID)
If previousGadgetList
Protected gripNormal=CreateImage(#PB_Any, 2, 2, 32, RGB(255, 0, 0))
Protected gripFocus=CreateImage(#PB_Any, 2, 2, 32, RGB(255, 0, 0))
Protected grip=ImageGadget(#PB_Any, 0, 0, 0, 0, 0)
HideGadget(grip, 1)
DisableGadget(grip, 1)
UseGadgetList(previousGadgetList)
SetProp_(*SplitterID, "GripNormal", gripNormal)
SetProp_(*SplitterID, "GripFocus", gripFocus)
SetProp_(*SplitterID, "Grip", grip)
EndIf
;init orientation and default thickness
Protected a=GetGadgetAttribute(Splitter, #PB_Splitter_FirstGadget)
Protected b=GetGadgetAttribute(Splitter, #PB_Splitter_SecondGadget)
Protected verticalBar=Bool(GadgetX(b)<>GadgetX(a))
Protected defaultThickness=Bool(verticalBar=1)*Abs(GadgetX(b)-GadgetX(a)-GadgetWidth(a)) + Bool(verticalBar=0)*Abs(GadgetY(b)-GadgetY(a)-GadgetHeight(a))
Debug defaultThickness
SetProp_(*SplitterID, "VerticalBar", verticalBar)
SetProp_(*SplitterID, "Thickness", defaultThickness)
SetProp_(*SplitterID, "DefaultThickness", defaultThickness)
EndIf
;save splitter parameters
If DblClickToSnap<>#PB_Ignore
SetProp_(*SplitterID, "DblClickToSnap", DblClickToSnap)
EndIf
If SnapFirst<>#PB_Ignore
SetProp_(*SplitterID, "SnapFirst", SnapFirst)
EndIf
If SnapSecond<>#PB_Ignore
SetProp_(*SplitterID, "SnapSecond", SnapSecond)
EndIf
If GripWidth<>#PB_Ignore
SetProp_(*SplitterID, "GripWidth", GripWidth)
EndIf
If Thickness<>#PB_Ignore
If Thickness>=0 And Thickness<4 : Thickness=4 : EndIf
SetProp_(*SplitterID, "Thickness", Thickness)
EndIf
If Locked<>#PB_Ignore
SetProp_(*SplitterID, "Locked", Locked)
EndIf
Thickness=GetProp_(*SplitterID, "Thickness")
GripWidth=GetProp_(*SplitterID, "GripWidth")
grip=GetProp_(*SplitterID, "Grip")
gripFocus=GetProp_(*SplitterID, "GripFocus")
gripNormal=GetProp_(*SplitterID, "GripNormal")
If Thickness>0 And GripWidth>0
;enable grip & dashed bar
SetProp_(*SplitterID, "GripVisible", #True)
Protected w=GripWidth, h=Thickness
If verticalBar : Swap w, h : EndIf
ResizeImage(gripNormal, w, h, #PB_Image_Raw)
ResizeImage(gripFocus, w, h, #PB_Image_Raw)
SendMessage_(*SplitterID, #WM_SPLITTER_REDRAW_GRIP_IMAGES, gripNormal, 0)
SendMessage_(*SplitterID, #WM_SPLITTER_REDRAW_GRIP_IMAGES, gripFocus, 0)
SetGadgetState(grip, ImageID(gripNormal))
HideGadget(grip, 0)
;position grip & gadgets
SendMessage_(*SplitterID, #WM_SPLITTER_POSITION_GRIP_AND_GADGETS, 0, 0)
Else
;disable grip & dashed bar
SetProp_(*SplitterID, "GripVisible", #False)
SetGadgetState(grip, #Null)
HideGadget(grip, 1)
;restore default thickness
SetProp_(*SplitterID, "Thickness", GetProp_(*SplitterID, "DefaultThickness"))
EndIf
EndProcedure
Procedure.i SplitterLocked(Splitter) ;Returns #True if splitter is locked
Protected *SplitterID=GadgetID(Splitter)
ProcedureReturn Bool(GetProp_(*SplitterID, "Locked"))
EndProcedure
Procedure.i SplitterSnapped(Splitter) ;Returns 1 or 2 if splitter snapped border 1 or 2 is snapped (not snapped if ZERO)
Protected *SplitterID=GadgetID(Splitter)
Protected verticalBar=GetProp_(*SplitterID, "VerticalBar")
Protected thickness=GetProp_(*SplitterID, "Thickness")
Protected snapFirst=GetProp_(*SplitterID, "SnapFirst")
Protected snapSecond=GetProp_(*SplitterID, "SnapSecond")
Protected snapPos1=GetGadgetAttribute(Splitter, #PB_Splitter_FirstMinimumSize)
Protected snapPos2
If verticalBar
snapPos2=GadgetWidth(Splitter)-GetGadgetAttribute(Splitter, #PB_Splitter_FirstMinimumSize)-thickness
Else
snapPos2=GadgetHeight(Splitter)-GetGadgetAttribute(Splitter, #PB_Splitter_SecondMinimumSize)-thickness
EndIf
If snapFirst And GetGadgetState(Splitter)=snapPos1
ProcedureReturn 1
ElseIf snapSecond And GetGadgetState(Splitter)=snapPos2
ProcedureReturn 2
EndIf
EndProcedure
Procedure SwapSplitter(Splitter, SwapBarPosition=#True, SwapSnapping=#True, SwapMinimumSize=#True, SwapGadgets=#True) ; swap gadgets and other options
SetSplitterEffects(Splitter, #PB_Ignore, #PB_Ignore, #PB_Ignore, #PB_Ignore, #PB_Ignore, #PB_Ignore)
Protected *SplitterID=GadgetID(Splitter)
Protected verticalBar=GetProp_(*SplitterID, "VerticalBar")
Protected thickness=GetProp_(*SplitterID, "Thickness")
Protected gripWidth=GetProp_(*SplitterID, "GripWidth")
Protected dblClickToSnap=GetProp_(*SplitterID, "DblClickToSnap")
Protected locked=GetProp_(*SplitterID, "Locked")
Protected flags=Bool(GetProp_(*SplitterID, "DefaultThickness")>4)*#PB_Splitter_Separator
Protected snapFirst=GetProp_(*SplitterID, "SnapFirst")
Protected snapSecond=GetProp_(*SplitterID, "SnapSecond")
If SwapSnapping
Swap SnapFirst, SnapSecond
EndIf
Protected Min1=GetGadgetAttribute(Splitter, #PB_Splitter_FirstMinimumSize)
Protected Min2=GetGadgetAttribute(Splitter, #PB_Splitter_SecondMinimumSize)
If SwapMinimumSize
Swap Min1, Min2
EndIf
Protected Gadget1=GetGadgetAttribute(Splitter, #PB_Splitter_FirstGadget)
Protected Gadget2=GetGadgetAttribute(Splitter, #PB_Splitter_SecondGadget)
If SwapGadgets
Swap Gadget1, Gadget2
EndIf
Protected Pos=GetGadgetState(Splitter)
Protected PosOpposite=Pos + (Bool(verticalBar=1)*GadgetWidth(Splitter) +
Bool(verticalBar=0)*GadgetHeight(Splitter) +
(-2*Pos)-Thickness)
If SwapBarPosition
Swap Pos, PosOpposite
EndIf
Protected x=GadgetX(Splitter), y=GadgetY(Splitter)
Protected w=GadgetWidth(Splitter), h=GadgetHeight(Splitter)
Protected previousGadgetList=UseGadgetList(GetParent_(*SplitterID))
Static dummy
If Not dummy : dummy=TextGadget(#PB_Any, 0, 0, 0, 0, "") : HideGadget(dummy, 1) : EndIf
SetGadgetAttribute(Splitter, #PB_Splitter_SecondGadget, dummy)
SetGadgetAttribute(Splitter, #PB_Splitter_FirstGadget, Gadget1)
SetGadgetAttribute(Splitter, #PB_Splitter_SecondGadget, Gadget2)
SetGadgetAttribute(Splitter, #PB_Splitter_FirstMinimumSize, Min1)
SetGadgetAttribute(Splitter, #PB_Splitter_SecondMinimumSize, Min2)
SetGadgetState(Splitter, Pos)
SetSplitterEffects(Splitter, thickness, gripWidth, snapFirst, snapSecond, dblClickToSnap, locked)
EndProcedure
; ***************************
; EXAMPLE
; ***************************
CompilerIf #PB_Compiler_IsMainFile
DisableExplicit
firstWin=OpenWindow(#PB_Any, 0, 0, 0, 0, "Dashed SplitterGadget And Auto Snap-To-Border", #PB_Window_SizeGadget | #PB_Window_SystemMenu)
If firstWin
WindowBounds(firstWin, 410, 440, #PB_Ignore, #PB_Ignore)
SmartWindowRefresh(firstWin, 1)
panel=PanelGadget(#PB_Any, 0, 0, 0, 0)
AddGadgetItem(panel, -1, "Tab 1")
panelButton=ButtonGadget(#PB_Any, 0, 0, 100, 30, "CLICK!")
CloseGadgetList()
otherButton=ButtonGadget(#PB_Any, 0, 0, 0, 0, "BIG CLICK!")
swapButton=ButtonGadget(#PB_Any, 5, 5, 100, 30, "SWAP")
splitter1=SplitterGadget(#PB_Any, 50, 50, 110, 110, panel, otherButton, #PB_Splitter_SecondFixed)
SetSplitterEffects(splitter1, 8, 100, 50, 100, 1)
SetGadgetAttribute(splitter1, #PB_Splitter_FirstMinimumSize, 60)
SetGadgetAttribute(splitter1, #PB_Splitter_SecondMinimumSize, 15)
SetGadgetState(splitter1, 20)
EndIf
SecondWin=OpenWindow(#PB_Any, 220, 220, 0, 0, "SplitterGadget : enable / disable options", #PB_Window_SizeGadget | #PB_Window_SystemMenu)
If SecondWin
WindowBounds(SecondWin, 410, 410, #PB_Ignore, #PB_Ignore)
SmartWindowRefresh(SecondWin, 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) : CloseGadgetList()
ContainerGadget(900, 0, 0, 0, 0) : CloseGadgetList()
SetGadgetColor(800, #PB_Gadget_BackColor, $C9C9E3)
SetGadgetColor(900, #PB_Gadget_BackColor, $ACACAC)
splitter2=SplitterGadget(#PB_Any, 50, 50, 0, 0, 800, 900, #PB_Splitter_Vertical | #PB_Splitter_FirstFixed | #PB_Splitter_Separator)
SetSplitterEffects(splitter2, 0, 0, 90, 30, 2)
EndIf
Repeat
e=WaitWindowEvent()
g=EventGadget()
t=EventType()
w=EventWindow()
Select e
Case #PB_Event_CloseWindow
CloseWindow(w)
If Not IsWindow(firstWin) And Not IsWindow(SecondWin) : End : EndIf
Case #PB_Event_SizeWindow
Select w
Case firstWin
ResizeGadget(splitter1, #PB_Ignore, #PB_Ignore, WindowWidth(w)-110, WindowHeight(w)-120)
Case SecondWin
ResizeGadget(splitter2, #PB_Ignore, #PB_Ignore, WindowWidth(w)-110, WindowHeight(w)-120)
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=" + GetGadgetState(g)
Debug "Splitter1 Snapped=" + SplitterSnapped(g)
EndIf
Case Splitter2
If t=#PB_EventType_LeftDoubleClick
Debug "Double-Click : #Splitter2"
ElseIf t=#PB_EventType_Change
Debug "Splitter2 : pos=" + GetGadgetState(g)
Debug "Splitter2 Snapped=" + SplitterSnapped(g)
EndIf
Case swapButton
SwapSplitter(Splitter1)
Case 100
SetSplitterEffects(Splitter2, #PB_Ignore, #PB_Ignore, #PB_Ignore, #PB_Ignore, #PB_Ignore, GetGadgetState(100))
Debug "Splitter2 Locked=" + SplitterLocked(splitter2)
Case 101
SetSplitterEffects(Splitter2, #PB_Ignore, #PB_Ignore, #PB_Ignore, #PB_Ignore, GetGadgetState(101), #PB_Ignore)
Case 102
SetSplitterEffects(Splitter2, #PB_Ignore, #PB_Ignore, 90*GetGadgetState(102), 30*GetGadgetState(102), #PB_Ignore, #PB_Ignore)
EndSelect
Default
EndSelect
ForEver
CompilerEndIf