Files
wnsrc/lua/slib/vgui/cl_stableviewer.lua
lifestorm 94063e4369 Upload
2024-08-04 22:55:00 +03:00

426 lines
13 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 = {}
local font = slib.createFont("Roboto", 15)
local neutralcolor, textcolor, successcolor_100, failcolor_100, maincolor_5, maincolor_7, maincolor_10, maincolor_15 = slib.getTheme("neutralcolor"), slib.getTheme("textcolor"), slib.getTheme("successcolor", -100), slib.getTheme("failcolor", -100), slib.getTheme("maincolor", 5), slib.getTheme("maincolor", 7), slib.getTheme("maincolor", 10), slib.getTheme("maincolor", 15)
function PANEL:Init()
self:SetSize(slib.getScaledSize(450, "x"), slib.getScaledSize(330, "y"))
:Center()
:MakePopup()
:addCloseButton()
:setTitle("Table Viewer", slib.createFont("Roboto", 17))
:setBlur(true)
self.entryheight = slib.getScaledSize(20, "y")
self.viewbox = vgui.Create("EditablePanel", self.frame)
self.viewbox:Dock(RIGHT)
self.viewbox:SetWide(self.frame:GetWide())
self.viewer = vgui.Create("SScrollPanel", self.viewbox)
:Dock(FILL)
end
local function createButton(self, parent, str, val)
local istbl = istable(val)
local selparent = parent and parent or self.viewer
local value = vgui.Create("SButton", selparent)
:Dock(TOP)
:SetZPos(-10)
:SetTall(slib.getScaledSize(25, "y"))
value.title = str
value.tbl = istbl and val or parent.tbl
value.Paint = function(s,w,h)
local wantedcolor = selparent == self.suggestions and successcolor_100 or (value.toggleable and selparent.tbl[str] and successcolor_100 or failcolor_100)
if !value.toggleable and (!s:IsHovered() or self.viewOnly) then
wantedcolor = table.Copy(wantedcolor)
wantedcolor.a = 0
end
surface.SetDrawColor(slib.lerpColor(s, wantedcolor))
surface.DrawRect(0, 0, w, h)
local display = ""
if !istbl and (isstring(val) or isnumber(val)) then
display = ": "..tostring(val)
end
draw.SimpleText(str..display, font, slib.getTheme("margin"), h * .5, textcolor, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
end
value.Think = function()
if !value.toggleable and self:getRule("toggleables", str) then
value.toggleable = true
end
if value:IsHovered() and input.IsKeyDown(KEY_LSHIFT) and input.IsMouseDown(MOUSE_RIGHT) then
value:DoClick()
end
end
value.DoClick = function()
if self.viewOnly then return end
self.modified = true
if selparent == self.suggestions then
local edit = IsValid(self.selected) and self.selected or self.viewer
if self.rules and self.rules.onlymodifytable and edit:GetName() == "SScrollPanel" then return end
if self.customvalues then
local popup = vgui.Create("SPopupBox")
:setTitle(value.title)
local entry = popup:addInput("text", self.customvalueplaceholder)
if self.customnumeric then
entry:SetNumeric(true)
end
popup:addChoise(self.customvalues, function()
local val = entry:GetValue()
self:addValue(editTbl, value.title, val, edit)
edit.tbl[value.title] = val
if edit == self.viewer then
self:sortValues(self.viewer)
end
end)
return
else
edit.tbl[value.title] = true
self:addValue(editTbl, value.title, true, edit)
end
if edit == self.viewer then
self:sortValues(self.viewer)
end
else
if value.toggleable then
selparent.tbl[str] = !selparent.tbl[str]
return end
value:Remove()
end
selparent.tbl[str] = nil
end
return value
end
function PANEL:addValue(panel, str, val, parent)
if istable(val) then
local selpar = parent or panel
parent = vgui.Create("EditablePanel", selpar)
parent:Dock(TOP)
parent:SetTall(slib.getScaledSize(25, "y"))
parent:DockMargin(slib.getTheme("margin"),slib.getTheme("margin"),slib.getTheme("margin"),slib.getTheme("margin"))
parent:DockPadding(0,slib.getScaledSize(25, "y"),0,0)
parent.isTblContainer = true
parent.tbl = val
parent.title = str
parent.OnSizeChanged = function(w,h)
parent.top:SetWide(parent:GetWide())
end
parent.top = vgui.Create("SButton", parent)
parent.top:SetSize(parent:GetWide(), slib.getScaledSize(25, "y"))
parent.top.DoClick = function()
if self.rules and self.rules.tableDeletable and !self:getRule("undeleteableTables", str) then
parent:Remove()
selpar.tbl[str] = nil
self.modified = true
return end
self.selected = self.selected ~= parent and parent or nil
end
parent.top.Paint = function(s,w,h)
local wantedcolor = self.rules and self.rules.tableDeletable and !self:getRule("undeleteableTables", str) and failcolor_100 or neutralcolor
surface.SetDrawColor(maincolor_7)
surface.DrawRect(0, 0, w, h)
surface.SetDrawColor(maincolor_5)
surface.DrawRect(0,h-1,w,1)
if self.rules and self.rules.tableDeletable and !self:getRule("undeleteableTables", str) then
if !s:IsHovered() then
wantedcolor = table.Copy(wantedcolor)
wantedcolor.a = 0
end
elseif self.selected ~= parent then
wantedcolor = table.Copy(wantedcolor)
wantedcolor.a = 0
end
surface.SetDrawColor(slib.lerpColor(s, wantedcolor))
surface.DrawRect(0, 0, w, h)
draw.SimpleText(str, font, slib.getTheme("margin"), h * .5, textcolor, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER)
end
parent.PaintOver = function(s, w, h)
surface.SetDrawColor(maincolor_5)
surface.DrawOutlinedRect(0, 0, w, h)
end
parent.OnChildAdded = function(child)
local addheight = slib.getScaledSize(25, "y")
parent:SetTall(parent:GetTall() + addheight)
local grandparent = parent:GetParent()
if !grandparent.isTblContainer then return end
grandparent:SetTall(grandparent:GetTall() + addheight)
end
parent.OnChildRemoved = function(child)
local addheight = slib.getScaledSize(25, "y")
parent:SetTall(parent:GetTall() - addheight)
local grandparent = parent:GetParent()
if !grandparent.isTblContainer then return end
grandparent:SetTall(grandparent:GetTall() - addheight)
end
if selpar ~= self.viewer then
selpar:SetTall(selpar:GetTall() + (slib.getTheme("margin") * 2))
end
for k,v in pairs(val) do
self:addValue(panel, k, v, parent)
end
return end
return createButton(self, parent and parent or panel, str, val)
end
local function differenciate(a, b)
if !(isstring(a) == isstring(b)) or isbool(a) or isbool(b) then
return tostring(a), tostring(b)
end
return a, b
end
function PANEL:setCustomValues(bool, placeholder, numeric)
self.customvalues = bool
self.customvalueplaceholder = placeholder
self.customnumeric = numeric
return self
end
function PANEL:sortValues(panel)
if !IsValid(panel) then return self end
local basictable = {}
local cleantable = {}
for k,v in pairs(panel.tbl) do
table.insert(basictable, k)
end
table.sort(basictable, function(a, b) local a, b = differenciate(a, b) return a < b end)
for k,v in pairs(basictable) do
cleantable[v] = k
end
for k, v in pairs(panel:GetCanvas():GetChildren()) do
if !v.title then continue end
v:SetZPos(cleantable[v.title])
end
return self
end
function PANEL:addSuggestions(tbl)
if !tbl then return self end
local wide, tall = self.frame:GetWide() * .5, self.frame:GetTall()
self.viewer:SetPos(wide, 0)
self.viewer:SetWide(wide)
self.suggestionbox = vgui.Create("EditablePanel", self.frame)
self.suggestionbox:Dock(LEFT)
self.suggestionbox:SetWide(self.frame:GetWide() * .5)
self.viewbox:SetWide(self.frame:GetWide() * .5)
self.suggestions = vgui.Create("SScrollPanel", self.suggestionbox)
self.suggestions:Dock(FILL)
self.suggestions.tbl = tbl
self.suggestions.hidden = {}
self.suggestions.PaintOver = function(s,w,h)
surface.SetDrawColor(maincolor_10)
surface.DrawRect(w - 1, 0, 1, h)
end
self.suggestions.Think = function()
local edit = IsValid(self.selected) and self.selected or self.viewer
for k, value in pairs(self.suggestions:GetCanvas():GetChildren()) do
if value:IsVisible() ~= !edit.tbl[value.title] and !value.searchHidden then
value:SetVisible(!edit.tbl[value.title])
self.suggestions:GetCanvas():InvalidateLayout(true)
end
end
end
for k,v in pairs(tbl) do
self:addValue(self.suggestions, k, v)
end
return self
end
function PANEL:setOnlyModifyTable(bool)
self.rules = self.rules or {}
self.rules.onlymodifytable = bool
end
function PANEL:setToggleable(module, name, string)
self.rules = self.rules or {}
self.rules[module] = self.rules[module] or {}
self.rules[module][name] = self.rules[module][name] or {}
self.rules[module][name].toggleables = self.rules[module][name].toggleables or {}
self.rules[module][name].toggleables[string] = true
end
function PANEL:setTableDeletable(bool)
self.rules = self.rules or {}
self.rules.tableDeletable = bool
end
function PANEL:setundeleteableTable(module, name, string)
self.rules = self.rules or {}
self.rules[module] = self.rules[module] or {}
self.rules[module][name] = self.rules[module][name] or {}
self.rules[module][name].undeleteableTables = self.rules[module][name].undeleteableTables or {}
self.rules[module][name].undeleteableTables[string] = true
end
function PANEL:setAddRules(rule)
self.rules = self.rules or {}
self.rules.addRules = rule
end
function PANEL:getRule(type, str)
local returnval = false
if self.rules and self.rules[self.modulename] and self.rules[self.modulename][self.name] and self.rules[self.modulename][self.name][type] and self.rules[self.modulename][self.name][type][str] then
returnval = true
end
return returnval
end
function PANEL:setIdentifiers(module, name)
self.modulename, self.name = module, name
end
function PANEL:setTable(tbl)
if !tbl or !istable(tbl) then return self end
self.viewer.tbl = tbl
for k,v in pairs(tbl) do
self:addValue(self.viewer, k, v)
end
return self
end
function PANEL:addSearch(panel, viewer)
if !IsValid(panel) or !IsValid(viewer) then return self end
panel.search = vgui.Create("SSearchBar", panel)
:addIcon()
:SetWide(panel:GetWide())
:Dock(TOP)
:DockMargin(0,0,0,0)
panel.search.entry.onValueChange = function(newvalue)
for k,v in pairs(viewer:GetCanvas():GetChildren()) do
if !v.title then continue end
v:SetVisible(string.find(string.lower(v.title), string.lower(newvalue)))
if v:IsVisible() then
v.searchHidden = nil
else
v.searchHidden = true
end
end
viewer:GetCanvas():InvalidateLayout(true)
end
return self
end
function PANEL:addEntry()
self.addEntryFrame = vgui.Create("EditablePanel", self.viewbox)
self.addEntryFrame:Dock(BOTTOM)
self.addEntryButton = vgui.Create("SButton", self.addEntryFrame)
:Dock(RIGHT)
:setTitle("Add")
self.addEntryButton.accentheight = 1
self.addEntryButton.bg = maincolor_10
self.addEntryButton.DoClick = function()
local key, edit = self.entry:GetValue(), (IsValid(self.selected) and self.selected or self.viewer)
if !key or key == "" or edit.tbl[key] then return end
if self.rules and self.rules.onlymodifytable and edit:GetName() == "SScrollPanel" then return end
local val
if self.rules and self.rules.addRules and edit:GetName() == "SScrollPanel" then
val = table.Copy(self.rules.addRules)
end
if !val then val = key end
local result = !istable(val) and true or val
edit.tbl[key] = result
self:addValue(edit, key, result, edit)
self:sortValues(self.viewer)
self.modified = true
self.entry:SetValue("")
end
self.entry = vgui.Create("STextEntry", self.addEntryFrame)
:Dock(FILL)
:SetValue("")
self.entry.bg = maincolor_10
self.entry.placeholder = ""
self.addEntryFrame:SetTall(self.entry:GetTall())
self.addEntryButton:SetTall(self.entry:GetTall())
return self
end
vgui.Register("STableViewer", PANEL, "SFrame")