Files
wnsrc/lua/vgui/dtilelayout.lua
lifestorm 9c918c46e5 Upload
2024-08-04 23:12:27 +03:00

287 lines
5.2 KiB
Lua

--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PANEL = {}
AccessorFunc( PANEL, "m_iSpaceX", "SpaceX" )
AccessorFunc( PANEL, "m_iSpaceY", "SpaceY" )
AccessorFunc( PANEL, "m_iBorder", "Border" )
AccessorFunc( PANEL, "m_iBaseSize", "BaseSize" )
AccessorFunc( PANEL, "m_iMinHeight", "MinHeight" )
function PANEL:Init()
self:SetDropPos( "46" )
self:SetMinHeight( 1 )
self:SetSpaceX( 0 )
self:SetSpaceY( 0 )
self:SetBorder( 0 )
self:SetBaseSize( 64 )
self.LastW = 0
self.LastH = 0
self.Tiles = {}
end
function PANEL:Layout()
self.LastW = 0
self.LastH = 0
self:InvalidateLayout()
end
function PANEL:FitsInTile( x, y, w, h )
for a = x, x + ( w - 1 ) do
for b = y, y + ( h - 1 ) do
if ( self:GetTile( a, b ) == 1 ) then
return false
end
end
end
return true
end
function PANEL:FindFreeTile( x, y, w, h )
x = x or 1
y = y or 1
local span = math.floor( ( self:GetWide() - self:GetBorder() * 2 + self:GetSpaceX() ) / ( self:GetBaseSize() + self:GetSpaceX() ) )
if ( span < 1 ) then span = 1 end
for i = 1, span do
-- Too long to fit on this line
if ( ( i + ( w - 1 ) ) > span ) then
-- If we're on the first part
-- and the line is empty
-- add it. It might be too long to fit on anyway
if ( i == 1 && self:FitsInTile( i, y, w, h ) ) then
return i, y
end
break
end
if ( self:FitsInTile( i, y, w, h ) ) then
return i, y
end
end
return self:FindFreeTile( 1, y + 1, w, h )
end
function PANEL:ClearTiles()
self.Tiles = {}
end
function PANEL:GetTile( x, y )
if ( !self.Tiles[y] ) then
return nil
end
return self.Tiles[y][x]
end
function PANEL:SetTile( x, y, val )
if ( !self.Tiles[y] ) then
self.Tiles[y] = {}
end
self.Tiles[y][x] = val
end
function PANEL:ConsumeTiles( x, y, w, h )
for a = x, x + ( w - 1 ) do
for b = y, y + ( h - 1 ) do
self:SetTile( a, b, 1 )
end
end
end
function PANEL:LayoutTiles()
local StartLine = 1
local tilesize = self:GetBaseSize()
local MaxWidth = math.floor( ( self:GetWide() - self:GetBorder() * 2 + self:GetSpaceX() ) / ( tilesize + self:GetSpaceX() ) )
self:ClearTiles()
for k, v in ipairs( self:GetChildren() ) do
if ( !v:IsVisible() ) then continue end
local w = math.ceil( v:GetWide() / ( tilesize + self:GetSpaceX() ) )
local h = math.ceil( v:GetTall() / ( tilesize + self:GetSpaceY() ) )
if ( v.OwnLine ) then
w = MaxWidth
end
local x, y = self:FindFreeTile( 1, StartLine, w, h )
v:SetPos( self:GetBorder() + ( x - 1 ) * ( tilesize + self:GetSpaceX() ), self:GetBorder() + ( y - 1 ) * ( tilesize + self:GetSpaceY() ) )
self:ConsumeTiles( x, y, w, h )
if ( v.OwnLine ) then
StartLine = y + 1
end
LastX = x
end
end
function PANEL:PerformLayout()
local ShouldLayout = false
if ( self.LastW != self:GetWide() ) then ShouldLayout = true end
if ( self.LastH != self:GetTall() ) then ShouldLayout = true end
self.LastW = self:GetWide()
self.LastH = self:GetTall()
if ( ShouldLayout ) then
self:LayoutTiles()
end
local w, h = self:ChildrenSize()
h = math.max( h + self:GetBorder(), self:GetMinHeight() )
self:SetHeight( h )
end
function PANEL:OnModified()
-- Override me
end
function PANEL:OnChildRemoved()
-- A panel got removed, we gotta recompress z positions
for k, v in pairs( self:GetChildren() ) do
v:SetZPos( k )
end
self:Layout()
end
function PANEL:OnChildAdded( child )
-- Set the Z position for child ordering. Without this self:GetChildren() might return unpredictable results
child:SetZPos( self:ChildCount() )
local dn = self:GetDnD()
if ( dn ) then
child:Droppable( self:GetDnD() )
end
if ( self:IsSelectionCanvas() ) then
child:SetSelectable( true )
end
self:Layout()
end
function PANEL:Copy()
local copy = vgui.Create( "DTileLayout", self:GetParent() )
copy:CopyBase( self )
copy:SetSortable( self:GetSortable() )
copy:SetDnD( self:GetDnD() )
copy:SetSpaceX( self:GetSpaceX() )
copy:SetSpaceY( self:GetSpaceY() )
copy:SetBorder( self:GetBorder() )
copy:SetSelectionCanvas( self:GetSelectionCanvas() )
copy.OnModified = self.OnModified
copy:CopyContents( self )
return copy
end
function PANEL:CopyContents( from )
for k, v in ipairs( from:GetChildren() ) do
v:Copy():SetParent( self )
end
end
function PANEL:GenerateExample( ClassName, PropertySheet, Width, Height )
local pnl = vgui.Create( ClassName )
pnl:MakeDroppable( "ExampleDraggable", false )
pnl:SetWide( 196 )
pnl:SetUseLiveDrag( true )
pnl:SetSelectionCanvas( true )
pnl:SetSpaceX( 4 )
pnl:SetSpaceY( 8 )
pnl:SetBorder( 10 )
pnl:SetBaseSize( 32 )
for i = 1, 10 do
local btn = pnl:Add( "DButton" )
btn:SetSize( 32, 32 )
btn:SetText( i )
end
local btn_br = pnl:Add( "DButton" )
btn_br:SetSize( 32, 32 )
btn_br:SetText( "<br>" )
btn_br.OwnLine = true
for i = 1, 10 do
local btn = pnl:Add( "DButton" )
btn:SetSize( 32, 32 )
btn:SetText( 10 + i )
end
PropertySheet:AddSheet( ClassName, pnl, nil, true, true )
end
derma.DefineControl( "DTileLayout", "", PANEL, "DDragBase" )