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

326 lines
7.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 math = math
local gui = gui
local draw = draw
local surface = surface
local ScrW = ScrW
local ScrH = ScrH
local IsValid = IsValid
local ipairs = ipairs
local SUI, NAME = CURRENT_SUI, CURRENT_SUI.name
local TDLib = sui.TDLib
local FRAME_FONT = SUI.CreateFont("Frame", "Roboto", 18)
local Panel = FindMetaTable("Panel")
local PANEL = {}
AccessorFunc(PANEL, "m_bHeaderHeight", "HeaderHeight", FORCE_NUMBER)
AccessorFunc(PANEL, "m_bTitleFont", "TitleFont", FORCE_STRING)
AccessorFunc(PANEL, "m_bSizable", "Sizable", FORCE_BOOL)
AccessorFunc(PANEL, "m_iMinWidth", "MinWidth", FORCE_NUMBER)
AccessorFunc(PANEL, "m_iMinHeight", "MinHeight", FORCE_NUMBER)
local header_Think = function(s)
local parent = s.parent
local sw, sh = ScrW(), ScrH()
if s.dragging then
local x, y = input.GetCursorPos()
x, y = math.Clamp(x, 1, sw - 1), math.Clamp(y, 1, sh - 1)
x, y = x - s.dragging[1], y - s.dragging[2]
parent:SetPos(x, y)
parent:InvalidateLayout(true)
parent:OnPosChanged()
else
local x, y, w, h = parent:GetBounds()
parent:SetPos(math.Clamp(x, 5, sw - w - 5), math.Clamp(y, 5, sh - h - 5))
end
end
local header_OnMousePressed = function(s)
local parent = s.parent
s.dragging = {gui.MouseX() - parent.x, gui.MouseY() - parent.y}
s:MouseCapture(true)
end
local header_OnMouseReleased = function(s)
s.dragging = nil
s:MouseCapture(false)
end
local title_SetBGColor = function(s, c)
s:SetVisible(c and true or false)
end
local title_update_color = function(s)
s:SetTextColor(SUI.GetColor("title"))
end
local close_DoClick = function(s)
s.frame:Remove()
end
function PANEL:Init()
local header_buttons = {}
self.header_buttons = header_buttons
self:Center()
self:SetHeaderHeight(28)
local header = self:Add("PANEL")
header:Dock(TOP)
header.Paint = self.HeaderPaint
header:SetCursor("sizeall")
header.parent = self
header.Think = header_Think
header.OnMousePressed = header_OnMousePressed
header.OnMouseReleased = header_OnMouseReleased
self.header = header
local title = header:Add(NAME .. ".Label")
title:Dock(LEFT)
title:DockMargin(6, 2, 0, 2)
title:SetText("")
title:SetTextColor(SUI.GetColor("title"))
title:SizeToContents()
title.SetBGColor = title_SetBGColor
hook.Add(NAME .. ".ThemeChanged", title, title_update_color)
self.title = title
self.close = self:AddHeaderButton("https://raw.githubusercontent.com/Srlion/Addons-Data/main/icons/sui/close.png", "close", close_DoClick)
self.close.frame = self
self:SetSize(SUI.Scale(520), SUI.Scale(364))
self:SetTitleFont(FRAME_FONT)
SUI.OnScaleChanged(self, self.ScaleChanged)
function self:PerformLayout(w, h)
if IsValid(title) then
title:SizeToContents()
end
if IsValid(header) then
header:SetTall(SUI.Scale(self:GetHeaderHeight()))
end
for k, v in ipairs(header_buttons) do
if IsValid(v) then
v:SetWide(v:GetTall())
local margin = SUI.Scale(4)
v.image:DockMargin(margin, margin, margin, margin)
end
end
end
end
function PANEL:SetSize(w, h)
self.real_w, self.real_h = w, h
self:ScaleChanged()
end
function PANEL:HeaderPaint(w, h)
draw.RoundedBoxEx(3, 0, 0, w, h, SUI.GetColor("header"), true, true)
end
local SetSize = Panel.SetSize
PANEL.RealSetSize = SetSize
function PANEL:ScaleChanged()
if self.sizing then return end
local new_w, new_h = SUI.Scale(self.real_w), SUI.Scale(self.real_h)
self.x, self.y = self.x + (self:GetWide() / 2 - new_w / 2), self.y + (self:GetTall() / 2 - new_h / 2)
SetSize(self, new_w, new_h)
self:InvalidateLayout(true)
end
function PANEL:Paint(w, h)
if SUI.GetColor("frame_blur") then
TDLib.BlurPanel(self)
end
self:RoundedBox("Background", 3, 0, 0, w, h, SUI.GetColor("frame"))
end
function PANEL:SetTitleFont(font)
self.m_bTitleFont = font
self.title:SetFont(font)
end
function PANEL:SetTitle(text)
self.title:SetText(text)
self.title:SizeToContents()
end
function PANEL:AddHeaderButton(image_name, name, callback)
local button = self.header:Add("DButton")
button:SetText("")
button:Dock(RIGHT)
button:DockMargin(0, 2, #self.header:GetChildren() == 1 and 4 or 2, 2)
local hover = name .. "_hover"
local press = name .. "_press"
local circle = {}
button.Paint = function(s, w, h)
if s:IsHovered() then
TDLib.DrawCircle(circle, w / 2, h / 2, w / 2, SUI.GetColor(hover))
end
if s.Depressed then
TDLib.DrawCircle(circle, w / 2, h / 2, w / 2, SUI.GetColor(press))
end
end
button.DoClick = callback
local image = button:Add(NAME .. ".Image")
image:Dock(FILL)
image:SetMouseInputEnabled(false)
image:SetImage(image_name)
button.image = image
table.insert(self.header_buttons, button)
return button
end
function PANEL:OnMousePressed(_, checking)
if not self.m_bSizable then return end
local x, y = self:LocalToScreen(0, 0)
local w, h = self:GetSize()
if gui.MouseX() > (x + w - 20) and gui.MouseY() > (y + h - 20) then
if not checking then
self.sizing = {gui.MouseX() - w, gui.MouseY() - h}
self:MouseCapture(true)
end
self:SetCursor("sizenwse")
return
end
if checking then
self:SetCursor("arrow")
end
end
function PANEL:OnMouseReleased()
if not self.m_bSizable then return end
self:MouseCapture(false)
SUI.CallScaleChanged()
self.sizing = nil
end
function PANEL:Think()
if not self.m_bSizable then return end
self:OnMousePressed(nil, true)
if not self.sizing then return end
local sw, sh = ScrW(), ScrH()
local cx, cy = input.GetCursorPos()
local mousex = math.Clamp(cx, 1, sw - 1)
local mousey = math.Clamp(cy, 1, sh - 1)
local x = mousex - self.sizing[1]
x = math.Clamp(x, self.m_iMinWidth, sw - 10)
local y = mousey - self.sizing[2]
y = math.Clamp(y, self.m_iMinHeight, sh - 10)
self.real_w, self.real_h = x, y
SetSize(self, x, y)
self:InvalidateLayout(true)
self:SetCursor("sizenwse")
end
function PANEL:OnPosChanged()
end
local SetVisible = Panel.SetVisible
local Remove = Panel.Remove
local anim_speed = 0.2
local show = function(s)
local w, h = s.real_w, s.real_h
if s.anim_scale then
w, h = SUI.Scale(w), SUI.Scale(h)
end
SetVisible(s, true)
SetSize(s, w * 1.1, h * 1.1)
s:Center()
s:Stop()
s:SizeTo(w, h, anim_speed, 0, -1)
s:MoveTo((ScrW() / 2) - (w / 2), (ScrH() / 2) - (h / 2), anim_speed, 0, -1)
s:AlphaTo(255, anim_speed + 0.02, 0)
s:MakePopup()
end
local remove = function(s, hide)
if not hide and not s:IsVisible() then
Remove(s)
return
end
local w, h = s.real_w, s.real_h
if s.anim_scale then
w, h = SUI.Scale(w), SUI.Scale(h)
end
w, h = w * 1.1, h * 1.1
s:Stop()
s:SizeTo(w, h, anim_speed, 0, -1)
s:MoveTo((ScrW() / 2) - (w / 2), (ScrH() / 2) - (h / 2), anim_speed, 0, -1)
s:SetMouseInputEnabled(false)
s:SetKeyboardInputEnabled(false)
s:AlphaTo(0, anim_speed + 0.02, 0, function()
if hide then
SetVisible(s, false)
else
Remove(s)
end
end)
end
local hide = function(s)
remove(s, true)
end
function PANEL:AddAnimations(w, h, no_scale)
self.anim_scale = not no_scale
self.real_w, self.real_h = w, h
self:SetAlpha(0)
show(self)
self.Remove = remove
self.Hide = hide
self.Show = show
end
sui.register("Frame", PANEL, "EditablePanel")