- automatic resize gadgets
- set gadget docking mode
- set gadget anchors
- refresh gadget docking
- macro for FreeGadget (to refresh gadget docking)
- get gadget docking mode

Code: Select all
;{ Utils
Structure GadgetAnchor
;gadget ID
ID.i
;gadget container
Parent.i
;for gadget layout calculation
a.i
b.i
c.i
d.i
;anchor status
Left.b
Top.b
Right.b
Bottom.b
;margin distance for docking
MarginLeft.i
MarginTop.i
MarginRight.i
MarginBottom.i
;docking parameters
GadgetDocking.i
DockMode.b
DockPriority.i
EndStructure
Structure GadgetDocking
;gadget container
Parent.i
;for client size calculation
a.i
b.i
c.i
d.i
EndStructure
Global NewList GadgetAnchor.GadgetAnchor()
Global NewList GadgetDocking.GadgetDocking()
DeclareDLL AutoDockGadgets()
;}
;{ Functions for GadgetDock & GadgetAnchor
Enumeration 0
#Dock_None
#Dock_Left
#Dock_Right
#Dock_Top
#Dock_Bottom
#Dock_Fill
EndEnumeration
ProcedureDLL.l GetGadgetDock(ID) ;get gadget docking mode
ForEach GadgetAnchor()
With GadgetAnchor()
If \ID=ID
Protected DockMode=\DockMode
EndIf
EndWith
Next
ProcedureReturn DockMode
EndProcedure
ProcedureDLL SetGadgetAnchor(ID, Left.b, Top.b, Right.b, Bottom.b) ;set gadget border anchor
;find anchor if exists
Protected GadgetAnchor
ForEach GadgetAnchor()
If GadgetAnchor()\ID=ID
GadgetAnchor=@GadgetAnchor()
Break
EndIf
Next
;create anchor if necessary
If Not GadgetAnchor
AddElement(GadgetAnchor())
EndIf
;delete anchor if standard
If Left And Top And Not Right And Not Bottom
DeleteElement(GadgetAnchor())
ProcedureReturn
EndIf
With GadgetAnchor()
\ID=ID
\Left=Left
\Top=Top
\Right=Right
\Bottom=Bottom
\Parent=GetParent_(GadgetID(ID))
\GadgetDocking=0
\DockMode=0
\DockPriority=0
;remove docking behaviour if necessary
Shared GadgetDocking
If Not GadgetDocking And \DockMode
AutoDockGadgets()
EndIf
\a=#PB_Ignore
\b=#PB_Ignore
\c=#PB_Ignore
\d=#PB_Ignore
GetClientRect_(\parent, rc.RECT)
Protected parentW=rc\right
Protected parentH=rc\bottom
Protected parentCenterX=rc\right/2
Protected parentCenterY=rc\bottom/2
If Left
ElseIf Right
\a=rc\right-GadgetX(ID)
Else
\a=parentCenterX-GadgetX(ID)
EndIf
If Right
\c=parentW-(GadgetX(ID)+GadgetWidth(ID))
EndIf
If Top
ElseIf Bottom
\b=parentH-GadgetY(ID)
Else
\b=parentCenterY-GadgetY(ID)
EndIf
If Bottom
\d=parentH-(GadgetY(ID)+GadgetHeight(ID))
EndIf
EndWith
EndProcedure
ProcedureDLL SetGadgetDock(ID, DockMode, MarginLeft=#PB_Ignore, MarginTop=#PB_Ignore, MarginRight=#PB_Ignore, MarginBottom=#PB_Ignore) ;set gadget docking mode
Protected parent=GetParent_(GadgetID(ID))
GetClientRect_(parent, rc.RECT)
Protected parentW=rc\right
Protected parentH=rc\bottom
Protected parentCenterX=rc\right/2
Protected parentCenterY=rc\bottom/2
Protected a, b, c, d
Protected x, y, w, h
If DockMode=#Dock_None
SetGadgetAnchor(ID, 1, 1, 0, 0)
AutoDockGadgets()
ProcedureReturn
EndIf
ForEach GadgetDocking()
With GadgetDocking()
If \parent=parent
a=\a
b=\b
c=\c
d=\d
DeleteElement(GadgetDocking())
Break
EndIf
EndWith
Next
AddElement(GadgetDocking())
With GadgetAnchor()
ForEach GadgetAnchor()
If \ID=ID
If MarginLeft=#PB_Ignore : MarginLeft=\MarginLeft : EndIf
If MarginTop=#PB_Ignore : MarginTop=\MarginTop : EndIf
If MarginRight=#PB_Ignore : MarginRight=\MarginRight : EndIf
If MarginBottom=#PB_Ignore : MarginBottom=\MarginBottom : EndIf
Break
EndIf
Next
If MarginLeft=#PB_Ignore : MarginLeft=0 : EndIf
If MarginTop=#PB_Ignore : MarginTop=0 : EndIf
If MarginRight=#PB_Ignore : MarginRight=0 : EndIf
If MarginBottom=#PB_Ignore : MarginBottom=0 : EndIf
Shared GadgetDocking
GadgetDocking=1
Select DockMode
Case #Dock_Left
x=a+MarginLeft
y=b+MarginTop
h=parentH-d-b-MarginTop-MarginBottom
ResizeGadget(ID, x, y, #PB_Ignore, h)
SetGadgetAnchor(ID, 1, 1, 0, 1)
a+GadgetWidth(ID)+MarginLeft+MarginRight
Case #Dock_Right
x=parentW-c-GadgetWidth(ID)-MarginRight
y=b+MarginTop
h=parentH-d-b-MarginTop-MarginBottom
ResizeGadget(ID, x, y, #PB_Ignore, h)
SetGadgetAnchor(ID, 0, 1, 1, 1)
c+GadgetWidth(ID)+MarginLeft+MarginRight
Case #Dock_Top
x=a+MarginLeft
y=b+MarginTop
w=parentW-c-a-MarginLeft-MarginRight
ResizeGadget(ID, x, y, w, #PB_Ignore)
SetGadgetAnchor(ID, 1, 1, 1, 0)
b+GadgetHeight(ID)+MarginTop+MarginBottom
Case #Dock_Bottom
x=a+MarginLeft
y=parentH-d-GadgetHeight(ID)-MarginBottom
w=parentW-c-a-MarginLeft-MarginRight
ResizeGadget(ID, x, y, w, #PB_Ignore)
SetGadgetAnchor(ID, 1, 0, 1, 1)
d+GadgetHeight(ID)+MarginTop+MarginBottom
Case #Dock_Fill
x=a+MarginLeft
y=b+MarginTop
w=parentW-c-a-MarginLeft-MarginRight
h=parentH-d-b-MarginTop-MarginBottom
ResizeGadget(ID, x, y, w, h)
SetGadgetAnchor(ID, 1, 1, 1, 1)
EndSelect
GadgetDocking=0
;update docking client size
GadgetDocking()\parent=parent
GadgetDocking()\a=a
GadgetDocking()\b=b
GadgetDocking()\c=c
GadgetDocking()\d=d
;update docking margins
\MarginLeft=MarginLeft
\MarginTop=MarginTop
\MarginRight=MarginRight
\MarginBottom=MarginBottom
If \DockMode<>DockMode : AutoDockGadgetsNeeded=1 : EndIf
\GadgetDocking=@GadgetDocking()
\DockMode=DockMode
;update docked gadgets if necessary
If AutoDockGadgetsNeeded
AutoDockGadgets()
EndIf
EndWith
EndProcedure
ProcedureDLL AutoResizeGadgets() ;update gadget sizes
Shared AutoResizeGadgets
If Not AutoResizeGadgets
AutoResizeGadgets=1
;{/// UPDATE GADGET SIZES
ForEach GadgetAnchor()
If Not IsGadget(GadgetAnchor()\ID)
DeleteElement(GadgetAnchor())
Continue
EndIf
Protected x, y, w, h
Protected gx, gy
With GadgetAnchor()
GetClientRect_(\parent, rc.RECT)
Protected parentW=rc\right
Protected parentH=rc\bottom
Protected parentCenterX=rc\right/2
Protected parentCenterY=rc\bottom/2
If \Left
x=\a
gx=GadgetX(\ID)
ElseIf \c<>#PB_Ignore
x=parentW-\a
gx=x
Else
x=parentCenterX-\a
EndIf
If \Right
w=parentW-gx-\c
Else
w=\c
EndIf
If \Top
y=\b
gy=GadgetY(\ID)
ElseIf \d<>#PB_Ignore
y=parentH-\b
gy=y
Else
y=parentCenterY-\b
EndIf
If \Bottom
h=parentH-gy-\d
Else
h=\d
EndIf
ResizeGadget(\ID, x, y, w, h)
EndWith
Next
;}/// UPDATE GADGET SIZES
AutoResizeGadgets=0
EndIf
EndProcedure
ProcedureDLL AutoDockGadgets() ;update docked gadgets
Shared AutoDockGadgets
If Not AutoDockGadgets
AutoDockGadgets=1
;{/// UPDATE DOCKED GADGETS
ForEach GadgetDocking()
With GadgetDocking()
If Not IsWindow(\parent)
DeleteElement(GadgetDocking())
Continue
EndIf
\a=0
\b=0
\c=0
\d=0
EndWith
Next
;update docking priority (#Dock_Fill = low priority)
ForEach GadgetAnchor()
With GadgetAnchor()
If \DockMode=#Dock_Fill
CompilerIf #PB_Compiler_Version<430
\DockPriority=CountList(GadgetAnchor())
CompilerElse
\DockPriority=ListSize(GadgetAnchor())
CompilerEndIf
Else
\DockPriority=ListIndex(GadgetAnchor())
EndIf
EndWith
Next
SortStructuredList(GadgetAnchor(), #PB_Sort_Ascending, OffsetOf(GadgetAnchor\DockPriority), #PB_Sort_Integer)
ForEach GadgetAnchor()
With GadgetAnchor()
If Not IsGadget(\ID)
DeleteElement(GadgetAnchor())
Continue
EndIf
If Not \DockMode
Continue
EndIf
SetGadgetDock(\ID, \DockMode)
EndWith
Next
;}/// UPDATE DOCKED GADGETS
AutoDockGadgets=0
EndIf
EndProcedure
Macro FreeGadget(ID, FreeGadgetFunction=FreeGadget)
FreeGadgetFunction(ID)
If GetGadgetDock(ID)
AutoDockGadgets()
EndIf
EndMacro
;}
; ********************
; EXAMPLE
; ********************
If OpenWindow(1, 200, 200, 230, 220, "Docking by Eddy", #PB_Window_SizeGadget | #PB_Window_SystemMenu)
CompilerIf #PB_Compiler_Version < 430
CreateGadgetList(WindowID(1))
CompilerElse
WindowBounds(1, 220, 170, 500, 500)
CompilerEndif
SmartWindowRefresh(1, 1)
ButtonGadget(50, 0, 0, 20, 20, "D")
SetGadgetDock(50, #Dock_Right, 0, 0, 5, 0)
ButtonGadget(60, 0, 0, 20, 20, "Remove Me!")
SetGadgetDock(60, #Dock_top, 5, 5, 5, 5)
ButtonGadget(70, 0, 0, 20, 20, "Clone Me!")
SetGadgetDock(70, #Dock_Bottom, 5, 5, 5, 5)
ButtonGadget(80, 0, 0, 20, 20, "D")
SetGadgetDock(80, #Dock_Left, 0, 5, 0, 5)
ButtonGadget(90, 0, 0, 20, 20, "D")
SetGadgetDock(90, #Dock_Left)
If ContainerGadget(10, 50, 50, 0, 0, #PB_Container_Single)
SetGadgetColor(10, #PB_Gadget_BackColor, RGB(255, 255, 0))
SetGadgetDock(10, #Dock_Fill)
ButtonGadget(11, 130, 10, 20, 20, "1")
SetGadgetAnchor(11, 0, 1, 1, 0)
ButtonGadget(12, 130, 90, 20, 20, "2")
SetGadgetAnchor(12, 0, 0, 1, 1)
ButtonGadget(13, 10, 50, 20, 20, "3")
SetGadgetAnchor(13, 1, 0, 0, 0)
ButtonGadget(14, 70, 50, 20, 20, "4")
SetGadgetAnchor(14, 0, 0, 0, 0)
CloseGadgetList()
EndIf
EndIf
Repeat
e=WaitWindowEvent()
If e=#PB_Event_SizeWindow
AutoResizeGadgets()
EndIf
If e=#PB_Event_Gadget And EventGadget()=70 And EventType()=#PB_EventType_LeftClick
;//// HOW TO ADD NEW DOCKED GADGET
ButtonGadget(190, 0, 0, 20, 20, "Clone Me!")
SetGadgetDock(190, #Dock_Bottom, 5, 5, 5, 0)
EndIf
If e=#PB_Event_Gadget And EventGadget()=60 And EventType()=#PB_EventType_LeftClick
;//// HOW TO REMOVE DOCKED GADGET (3 ways)
#HowToRemoveDockedGadget=1
CompilerSelect #HowToRemoveDockedGadget
CompilerCase 1
FreeGadget(60)
;If GetGadgetDock(ID)<>#Dock_None : AutoDockGadgets() : EndIf
CompilerCase 2
SetGadgetAnchor(60, 0, 0, 0, 0)
CompilerCase 3
SetGadgetDock(60, #Dock_None)
CompilerEndSelect
EndIf
Until e=#PB_Event_CloseWindow