- auto resize gadgets
- UseWindowLayout / UseGadgetLayout (layout management)
- resize priority parameter
- layout with margins & paddings
- DockGadget (docking modes: left, right, top, bottom, fill)
- AnchorGadget
- cross-platform (ios/win/linux)
For PB4.3 you can find the old version here :http://www.purebasic.fr/english/viewtop ... 12&t=34464
GadgetLayout.pbi
Code: Select all
;-TOP
; Comment : Gadget Layout
; Author : eddy
; Web : http://www.purebasic.fr/english/viewtopic.php?f=12&t=53113
;
; File: : GadgetLayout.pbi
; Version : v1.01
EnableExplicit
Enumeration
#Layout_IsParentWindow=0
#Layout_IsParentGadget
#Layout_IsAnchor
#Dock_None
#Dock_Left
#Dock_Right
#Dock_Top
#Dock_Bottom
#Dock_Fill
EndEnumeration
Structure GADGET_LAYOUT
;child gadget layouts
List Layouts.GADGET_LAYOUT()
;parent window or parent gadget or child gadget
Object.i
;item layout identifier (only for panel gadget)
ItemLayout.i
;layout mode
LayoutMode.i
;auto-resize priority
AutoResizePriority.i
;child margins / parent paddings
StructureUnion
MarginLeft.i
PaddingLeft.i
EndStructureUnion
StructureUnion
MarginTop.i
PaddingTop.i
EndStructureUnion
StructureUnion
MarginRight.i
PaddingRight.i
EndStructureUnion
StructureUnion
MarginBottom.i
PaddingBottom.i
EndStructureUnion
;offset from centered anchor
CenterOffsetX.i
CenterOffsetY.i
EndStructure
Global NewList ParentLayouts.GADGET_LAYOUT()
Procedure.i SelectParentLayout(Parent.i, LayoutMode, ItemLayout=#PB_Ignore)
With ParentLayouts()
ForEach ParentLayouts()
If \Object=Parent And \LayoutMode=LayoutMode
If \LayoutMode=#Layout_IsParentWindow Or ItemLayout=#PB_Ignore Or \ItemLayout=ItemLayout
ProcedureReturn ParentLayouts()
EndIf
EndIf
Next
ProcedureReturn #Null
EndWith
EndProcedure
Procedure.i UseParentDefaultPriority(Parent.i, LayoutMode, Priority)
If Priority<>#PB_Ignore : ProcedureReturn Priority : EndIf
If LayoutMode=#Layout_IsParentWindow : ProcedureReturn 100000 : EndIf
If LayoutMode=#Layout_IsParentGadget
Select GadgetType(Parent)
Case #PB_GadgetType_ScrollArea,#PB_GadgetType_Container : ProcedureReturn 10000
Case #PB_GadgetType_Panel : ProcedureReturn 1000
Case #PB_GadgetType_Frame3D : ProcedureReturn 100
EndSelect
EndIf
EndProcedure
Procedure.i UseParentLayout(Parent.i, LayoutMode, PaddingLeft=#PB_Ignore, PaddingTop=#PB_Ignore, PaddingRight=#PB_Ignore, PaddingBottom=#PB_Ignore, ItemLayout=#PB_Ignore, Priority=#PB_Ignore)
With ParentLayouts()
If Not SelectParentLayout(Parent, LayoutMode, ItemLayout)
AddElement(ParentLayouts())
Priority=UseParentDefaultPriority(Parent,LayoutMode,Priority)
EndIf
\Object=Parent
\LayoutMode=LayoutMode
If PaddingLeft<>#PB_Ignore : \PaddingLeft=PaddingLeft : EndIf
If PaddingTop<>#PB_Ignore : \PaddingTop=PaddingTop : EndIf
If PaddingRight<>#PB_Ignore : \PaddingRight=PaddingRight : EndIf
If PaddingBottom<>#PB_Ignore : \PaddingBottom=PaddingBottom : EndIf
If ItemLayout<>#PB_Ignore : \ItemLayout=ItemLayout : EndIf
If Priority<>#PB_Ignore
\AutoResizePriority=Priority
SortStructuredList(ParentLayouts(), #PB_Sort_Descending, OffsetOf(GADGET_LAYOUT\AutoResizePriority), #PB_Integer)
EndIf
ProcedureReturn ParentLayouts()
EndWith
EndProcedure
Procedure.i UseWindowLayout(Window.i, PaddingLeft=#PB_Ignore, PaddingTop=#PB_Ignore, PaddingRight=#PB_Ignore, PaddingBottom=#PB_Ignore, Priority=#PB_Ignore)
If IsWindow(Window)
ProcedureReturn UseParentLayout(Window, #Layout_IsParentWindow, PaddingLeft, PaddingTop, PaddingRight, PaddingBottom, #PB_Ignore, Priority)
EndIf
EndProcedure
Procedure.i UseGadgetLayout(Gadget.i, PaddingLeft=#PB_Ignore, PaddingTop=#PB_Ignore, PaddingRight=#PB_Ignore, PaddingBottom=#PB_Ignore, Priority=#PB_Ignore)
If IsGadget(Gadget)
ProcedureReturn UseParentLayout(Gadget, #Layout_IsParentGadget, PaddingLeft, PaddingTop, PaddingRight, PaddingBottom, #PB_Ignore, Priority)
EndIf
EndProcedure
Procedure.i UseGadgetItemLayout(Gadget.i, ItemLayout.i, PaddingLeft=#PB_Ignore, PaddingTop=#PB_Ignore, PaddingRight=#PB_Ignore, PaddingBottom=#PB_Ignore, Priority=#PB_Ignore)
If IsGadget(Gadget)
ProcedureReturn UseParentLayout(Gadget, #Layout_IsParentGadget, PaddingLeft, PaddingTop, PaddingRight, PaddingBottom, ItemLayout, Priority)
EndIf
EndProcedure
Procedure DockGadget(Gadget, DockMode, MarginLeft=0, MarginTop=0, MarginRight=0, MarginBottom=0)
AddElement(ParentLayouts()\Layouts())
With ParentLayouts()\Layouts()
\Object=Gadget
\LayoutMode=DockMode
\MarginLeft=MarginLeft
\MarginTop=MarginTop
\MarginRight=MarginRight
\MarginBottom=MarginBottom
EndWith
EndProcedure
Procedure AnchorGadget(Gadget, MarginLeft=#PB_Ignore,MarginTop=#PB_Ignore, MarginRight=#PB_Ignore, MarginBottom=#PB_Ignore)
AddElement(ParentLayouts()\Layouts())
With ParentLayouts()\Layouts()
\Object=Gadget
\LayoutMode=#Layout_IsAnchor
\MarginLeft=MarginLeft
\MarginTop=MarginTop
\MarginRight=MarginRight
\MarginBottom=MarginBottom
If \MarginLeft=#PB_Ignore And \MarginRight=#PB_Ignore : \CenterOffsetX=GadgetX(Gadget) : EndIf
If \MarginTop=#PB_Ignore And \MarginBottom=#PB_Ignore : \CenterOffsetY=GadgetY(Gadget) : EndIf
EndWith
EndProcedure
Procedure AutoResizeGadgets()
ForEach ParentLayouts()
With ParentLayouts()
;calculate parent position and available space
Protected x=0,y=0,w=0,h=0,px=0,py=0
Select \LayoutMode
Case #Layout_IsParentWindow
If Not IsWindow(\Object)
ClearList(\Layouts())
DeleteElement(ParentLayouts())
Continue
EndIf
w=WindowWidth(\Object)
h=WindowHeight(\Object)
Case #Layout_IsParentGadget
If Not IsGadget(\Object)
ClearList(\Layouts())
DeleteElement(ParentLayouts())
Continue
EndIf
Select GadgetType(\Object)
Case #PB_GadgetType_ScrollArea,#PB_GadgetType_Container
w=GadgetWidth(\Object)
h=GadgetHeight(\Object)
Case #PB_GadgetType_Panel
w=GetGadgetAttribute(\Object,#PB_Panel_ItemWidth)
h=GetGadgetAttribute(\Object,#PB_Panel_ItemHeight)
Default
px=GadgetX(\Object)
py=GadgetY(\Object)
w=GadgetWidth(\Object)
h=GadgetHeight(\Object)
EndSelect
EndSelect
If w<=0 Or h<=0 : Continue : EndIf
x+\PaddingLeft
y+\PaddingTop
w-\PaddingRight-x
h-\PaddingBottom-y
EndWith
ForEach ParentLayouts()\Layouts()
With ParentLayouts()\Layouts()
If Not IsGadget(\Object)
DeleteElement(ParentLayouts()\Layouts())
Continue
EndIf
;calculate gadget position and its needed space
Protected totalW=\MarginLeft+GadgetWidth(\Object)+\MarginRight
Protected totalH=\MarginTop+GadgetHeight(\Object)+\MarginBottom
Protected gx=#PB_Ignore
Protected gy=#PB_Ignore
Protected gw=#PB_Ignore
Protected gh=#PB_Ignore
Select \LayoutMode
Case #Layout_IsAnchor
If \MarginLeft<>#PB_Ignore
gx=x+\MarginLeft
If \MarginRight<>#PB_Ignore
gw=w-\MarginRight-\MarginLeft
EndIf
ElseIf \MarginRight<>#PB_Ignore
gx=x+w-\MarginRight-GadgetWidth(\Object)
Else
gx=x+(w-GadgetWidth(\Object))/2+\CenterOffsetX
EndIf
If \MarginTop<>#PB_Ignore
gy=y+\MarginTop
If \MarginBottom<>#PB_Ignore
gh=h-\MarginBottom-\MarginTop
EndIf
ElseIf \MarginBottom<>#PB_Ignore
gy=y+h-\MarginBottom-GadgetHeight(\Object)
Else
gy=y+(h-GadgetHeight(\Object))/2+\CenterOffsetY
EndIf
Case #Dock_Left
gx=x+\MarginLeft
gy=y+\MarginTop
gh=h-\MarginBottom-\MarginTop
x+totalW
w-totalW
Case #Dock_Right
gx=x+\MarginLeft+w-totalW
gy=y+\MarginTop
gh=h-\MarginBottom-\MarginTop
w-totalW
Case #Dock_Top
gx=x+\MarginLeft
gy=y+\MarginTop
gw=w-\MarginRight-\MarginLeft
y+totalH
h-totalH
Case #Dock_Bottom
gx=x+\MarginLeft
gy=y+\MarginTop+h-totalH
gw=w-\MarginRight-\MarginLeft
h-totalH
Case #Dock_Fill
gx=x+\MarginLeft
gy=y+\MarginTop
gw=w-\MarginRight-\MarginLeft
gh=h-\MarginBottom-\MarginTop
EndSelect
If (gw<>#PB_Ignore And gw<0) : gw=0 : EndIf
If (gh<>#PB_Ignore And gh<0) : gh=0 : EndIf
ResizeGadget(\Object,px+gx,py+gy,gw,gh)
EndWith
Next
Next
EndProcedure