mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 13:53:45 +03:00
Upload
This commit is contained in:
294
lua/slib/vgui/cl_slistview.lua
Normal file
294
lua/slib/vgui/cl_slistview.lua
Normal file
@@ -0,0 +1,294 @@
|
||||
--[[
|
||||
| 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 = {}
|
||||
|
||||
local font = slib.createFont("Roboto", 15)
|
||||
local textcolor, maincolor_7, linecol, neutralcolor, margin = slib.getTheme("textcolor"), slib.getTheme("maincolor", 7), Color(24,24,24,160), slib.getTheme("neutralcolor"), slib.getTheme("margin")
|
||||
|
||||
function PANEL:Init()
|
||||
self.Columns = self.Columns or {}
|
||||
self.Lines = self.Lines or {}
|
||||
|
||||
self.columniteration = 0
|
||||
self.lineiteration = 0
|
||||
|
||||
self.assortment = self.assortment or {}
|
||||
|
||||
slib.wrapFunction(self, "Dock", nil, function() return self end, true)
|
||||
slib.wrapFunction(self, "SetSize", nil, function() return self end, true)
|
||||
slib.wrapFunction(self, "Center", nil, function() return self end, true)
|
||||
slib.wrapFunction(self, "SetPos", nil, function() return self end, true)
|
||||
slib.wrapFunction(self, "MakePopup", nil, function() return self end, true)
|
||||
end
|
||||
|
||||
function PANEL:getColumnPos(col)
|
||||
local result = self.Columns[col]:GetPos()
|
||||
return select(1, result)
|
||||
end
|
||||
|
||||
function PANEL:getColumnWide(col)
|
||||
return self.Columns[col]:GetWide()
|
||||
end
|
||||
|
||||
local function differenciate(a, b)
|
||||
if isfunction(a) then a = a() end
|
||||
if isfunction(b) then b = b() end
|
||||
if isnumber(tonumber(a)) and isnumber(tonumber(b)) then return tonumber(a), tonumber(b) end
|
||||
|
||||
if !(isstring(a) == isstring(b)) or isbool(a) or isbool(b) then
|
||||
return tostring(a), tostring(b)
|
||||
end
|
||||
|
||||
return a, b
|
||||
end
|
||||
|
||||
function PANEL:addColumn(name)
|
||||
if !IsValid(self.topbar) then
|
||||
self.topbar = vgui.Create("EditablePanel", self)
|
||||
self.topbar:Dock(TOP)
|
||||
self.topbar:SetZPos(-32768)
|
||||
self.topbar:SetTall(slib.getScaledSize(25, "y"))
|
||||
|
||||
self.topbar.Paint = function(s,w,h)
|
||||
surface.SetDrawColor(maincolor_7)
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
|
||||
surface.SetDrawColor(linecol)
|
||||
surface.DrawRect(0, h - 1, w - 1, 1)
|
||||
end
|
||||
end
|
||||
|
||||
self.columniteration = self.columniteration + 1
|
||||
|
||||
local iteration = self.columniteration
|
||||
local ignoreWidth = false
|
||||
|
||||
|
||||
if istable(name) then
|
||||
if name[2] then
|
||||
ignoreWidth = name[2]
|
||||
end
|
||||
name = name[1]
|
||||
end
|
||||
|
||||
self.Columns[iteration] = vgui.Create("DButton", self.topbar)
|
||||
self.Columns[iteration]:Dock(LEFT)
|
||||
self.Columns[iteration]:SetWide(self:GetWide() / #self.Columns)
|
||||
self.Columns[iteration].Width = self:GetWide() / #self.Columns
|
||||
self.Columns[iteration]:SetText("")
|
||||
self.Columns[iteration].name = name
|
||||
self.Columns[iteration].iteration = iteration
|
||||
self.Columns[iteration].ignoreWidth = ignoreWidth
|
||||
|
||||
self.Columns[iteration].DoClick = function()
|
||||
if self.assortment.iteration == iteration then
|
||||
self.assortment.ascending = !self.assortment.ascending
|
||||
else
|
||||
self.assortment.iteration = iteration
|
||||
self.assortment.ascending = true
|
||||
end
|
||||
|
||||
local basictable = {}
|
||||
local cleantable = {}
|
||||
|
||||
for i=1,#self.Lines do
|
||||
local tbl = self.Columns[iteration]["lines"][i]
|
||||
local sortvalue = istable(tbl) and (tbl.sortvalue or tbl.text) or tbl
|
||||
|
||||
table.insert(basictable, sortvalue)
|
||||
end
|
||||
|
||||
if self.assortment.ascending then
|
||||
table.sort(basictable, function(a, b) a, b = differenciate(a, b) return a > b end)
|
||||
else
|
||||
table.sort(basictable, function(a, b) a, b = differenciate(a, b) return a < b end)
|
||||
end
|
||||
|
||||
for i, z in pairs(basictable) do
|
||||
cleantable[z] = i
|
||||
end
|
||||
|
||||
for i=1,#self.Lines do
|
||||
local tbl = self.Columns[iteration]["lines"][i]
|
||||
local final = istable(tbl) and (tbl.sortvalue or tbl.text) or tbl
|
||||
|
||||
if !IsValid(self.Lines[i]) then continue end
|
||||
|
||||
self.Lines[i]:SetZPos(cleantable[final])
|
||||
end
|
||||
end
|
||||
|
||||
self.Columns[iteration].Paint = function(s,w,h)
|
||||
draw.SimpleText(name, font, slib.getTheme("margin"), h * .5, textcolor, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function PANEL:addColumns(...)
|
||||
local args = {...}
|
||||
|
||||
for k,v in pairs(args) do
|
||||
self:addColumn(v)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function PANEL:addLine(...)
|
||||
local args = {...}
|
||||
if !IsValid(self.frame) then
|
||||
self.frame = vgui.Create("SScrollPanel", self)
|
||||
self.frame:Dock(FILL)
|
||||
self.frame:SetTall(slib.getScaledSize(25, "y"))
|
||||
end
|
||||
|
||||
self.lineiteration = self.lineiteration + 1
|
||||
|
||||
local iteration = self.lineiteration
|
||||
|
||||
for k,v in ipairs(args) do
|
||||
local display = istable(v) and v[1] or v
|
||||
local sortingvalue
|
||||
|
||||
if istable(v) and v[2] then
|
||||
sortingvalue = v[2]
|
||||
end
|
||||
|
||||
self.Columns[k]["lines"] = self.Columns[k]["lines"] or {}
|
||||
self.Columns[k]["lines"][iteration] = self.Columns[k]["lines"][iteration] or {}
|
||||
|
||||
self.Columns[k]["lines"][iteration]["text"] = display
|
||||
|
||||
if sortingvalue then
|
||||
self.Columns[k]["lines"][iteration]["sortvalue"] = sortingvalue
|
||||
end
|
||||
end
|
||||
|
||||
self.Lines[iteration] = vgui.Create("DButton", self)
|
||||
self.Lines[iteration]:Dock(TOP)
|
||||
self.Lines[iteration]:SetTall(slib.getScaledSize(25, "y"))
|
||||
self.Lines[iteration]:SetText("")
|
||||
self.Lines[iteration].InitDoClick = self.Lines[iteration].DoClick
|
||||
|
||||
self.Lines[iteration].Think = function()
|
||||
self.Lines[iteration]:SetMouseInputEnabled(self.Lines[iteration].DoClick ~= self.Lines[iteration].InitDoClick)
|
||||
end
|
||||
|
||||
self.Lines[iteration].Paint = function(s,w,h)
|
||||
local wantedcolor = neutralcolor
|
||||
|
||||
if !s:IsHovered() then
|
||||
wantedcolor = table.Copy(wantedcolor)
|
||||
wantedcolor.a = 0
|
||||
end
|
||||
|
||||
surface.SetDrawColor(slib.lerpColor(s, wantedcolor))
|
||||
surface.DrawRect(0, 0, w, h)
|
||||
|
||||
for i = 1,#self.Columns do
|
||||
local display = self.Columns[i]["lines"][iteration].text
|
||||
|
||||
if isfunction(display) then
|
||||
display = display()
|
||||
end
|
||||
|
||||
local x,y = self:getColumnPos(i), h * .5
|
||||
local w = self:getColumnWide(i)
|
||||
|
||||
if w < (self:getTextWidth(display, self.Columns[i].maxTxtLen) + margin * 2) then self:resizeColumns() end
|
||||
if i == 1 then
|
||||
s.name = display
|
||||
end
|
||||
|
||||
if self.Columns[i].ignoreWidth or self.Columns[i].maxTxtLen then
|
||||
surface.SetFont(font)
|
||||
local txt_h = select(2, surface.GetTextSize(display))
|
||||
local screen_x, screen_y = s:LocalToScreen(0,0)
|
||||
|
||||
render.SetScissorRect(screen_x + x, screen_y, screen_x + x + self.Columns[i]:GetWide() - margin, screen_y + h, true)
|
||||
draw.SimpleText(display, font, x + slib.getTheme("margin"), y, textcolor, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
|
||||
render.SetScissorRect(0, 0, 0, 0, false)
|
||||
else
|
||||
|
||||
if self.Columns[i].customRender and self.Columns[i].customRender(x, 0, w, h, s) == true then return end
|
||||
|
||||
draw.SimpleText(display, font, x + slib.getTheme("margin"), y, textcolor, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:resizeColumns()
|
||||
|
||||
return self, self.Lines[iteration]
|
||||
end
|
||||
|
||||
function PANEL:getTextWidth(txt, max)
|
||||
txt = tostring(txt)
|
||||
|
||||
if max then
|
||||
txt = string.sub(txt, 1, max)
|
||||
end
|
||||
|
||||
surface.SetFont(font)
|
||||
|
||||
return surface.GetTextSize(txt)
|
||||
end
|
||||
|
||||
function PANEL:resizeColumns()
|
||||
local columnsizes = {}
|
||||
local fullwidth = self:GetWide()
|
||||
local spaceleft = 0
|
||||
|
||||
for k, v in pairs(self.Columns) do
|
||||
local ignoreWidth = self.Columns[k].ignoreWidth
|
||||
surface.SetFont(font)
|
||||
|
||||
local longest = self:getTextWidth(self.Columns[k].name)
|
||||
if ignoreWidth then columnsizes[k] = isstring(ignoreWidth) and self:getTextWidth(ignoreWidth) or longest continue end
|
||||
if !self.Columns[k]["lines"] then continue end
|
||||
for i, z in pairs(self.Columns[k]["lines"]) do
|
||||
local compare = isfunction(z.text) and z.text() or z.text
|
||||
local width = self:getTextWidth(compare, self.Columns[k].maxTxtLen) + (slib.getTheme("margin") * 10)
|
||||
if longest < width then longest = width end
|
||||
end
|
||||
|
||||
columnsizes[k] = longest
|
||||
end
|
||||
|
||||
local occupiedspace = 0
|
||||
for k,v in pairs(columnsizes) do
|
||||
occupiedspace = occupiedspace + v
|
||||
end
|
||||
|
||||
for k,v in pairs(self.Columns) do
|
||||
local v = columnsizes[k] or 0
|
||||
|
||||
local gapadd = (fullwidth - occupiedspace) / #self.Columns
|
||||
self.Columns[k]:SetWide(v + gapadd)
|
||||
end
|
||||
end
|
||||
|
||||
function PANEL:OnSizeChanged()
|
||||
self:resizeColumns()
|
||||
end
|
||||
|
||||
function PANEL:PaintOver(w,h)
|
||||
for k,v in pairs(self.Columns) do
|
||||
if k >= #self.Columns then break end
|
||||
local x,y = self:getColumnPos(k), h * .5
|
||||
local w = self:getColumnWide(k)
|
||||
surface.SetDrawColor(linecol)
|
||||
surface.DrawRect(x + w - 1, 0, 1, h)
|
||||
end
|
||||
end
|
||||
|
||||
vgui.Register("SListView", PANEL, "SScrollPanel")
|
||||
Reference in New Issue
Block a user