You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

459 lines
16 KiB

---@type Diesal.GUI
local DiesalGUI = LibStub("DiesalGUI-2.0")
---@type Diesal.Tools
local DiesalTools = LibStub("DiesalTools-2.0")
---@type Diesal.Style
local DiesalStyle = LibStub("DiesalStyle-2.0")
local Colors = DiesalStyle.Colors
-- | Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local type, select, pairs, tonumber = type, select, pairs, tonumber
local floor, ceil = math.floor, math.ceil
-- | WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | Window |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = "DiesalWindow"
local Version = 14
-- ~~| Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
["frame-outline"] = {
type = "outline",
layer = "BACKGROUND",
color = "000000",
},
["frame-shadow"] = {
type = "shadow",
edgeSize = 0,
offset = { 5, 5, 5, 5},
edgeFile = [[interface/reforging/itemupgradefxtooltipglow]],
},
["titleBar-color"] = {
type = "texture",
layer = "BACKGROUND",
color = "000000",
alpha = 0.95,
},
["titletext-Font"] = {
type = "font",
color = "d8d8d8",
},
["header-background"] = {
type = "texture",
layer = "BACKGROUND",
gradient = { "VERTICAL", Colors.UI_400_GR[1], Colors.UI_400_GR[2] },
alpha = 0.95,
position = { 0, 0, 0, -1 },
},
["header-inline"] = {
type = "outline",
layer = "BORDER",
gradient = { "VERTICAL", "ffffff", "ffffff" },
alpha = { 0.05, 0.02 },
position = { 0, 0, 0, -1 },
},
["header-divider"] = {
type = "texture",
layer = "BORDER",
color = "000000",
alpha = 1,
position = { 0, 0, nil, 0 },
height = 1,
},
["content-background"] = {
type = "texture",
layer = "BACKGROUND",
color = Colors.UI_100,
alpha = 0.95,
},
["content-outline"] = {
type = "outline",
layer = "BORDER",
color = "FFFFFF",
alpha = 0.01,
},
["footer-background"] = {
type = "texture",
layer = "BACKGROUND",
gradient = { "VERTICAL", Colors.UI_400_GR[1], Colors.UI_400_GR[2] },
alpha = 0.95,
position = { 0, 0, -1, 0 },
},
["footer-divider"] = {
type = "texture",
layer = "BACKGROUND",
color = "000000",
position = { 0, 0, 0, nil },
height = 1,
},
["footer-inline"] = {
type = "outline",
layer = "BORDER",
gradient = { "VERTICAL", "ffffff", "ffffff" },
alpha = { 0.05, 0.02 },
position = { 0, 0, -1, 0 },
debug = true,
},
}
local wireFrame = {
["frame-white"] = {
type = "outline",
layer = "OVERLAY",
color = "ffffff",
},
["titleBar-yellow"] = {
type = "outline",
layer = "OVERLAY",
color = "fffc00",
},
["closeButton-orange"] = {
type = "outline",
layer = "OVERLAY",
color = "ffd400",
},
["header-blue"] = {
type = "outline",
layer = "OVERLAY",
color = "00aaff",
},
["footer-green"] = {
type = "outline",
layer = "OVERLAY",
color = "55ff00",
},
}
local sizerWireFrame = {
["sizerR-yellow"] = {
type = "outline",
layer = "OVERLAY",
color = "fffc00",
},
["sizerB-green"] = {
type = "outline",
layer = "OVERLAY",
color = "55ff00",
},
["sizerBR-blue"] = {
type = "outline",
layer = "OVERLAY",
color = "00aaff",
},
}
-- | Window Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function round(num)
if num >= 0 then
return floor(num + 0.5)
else
return ceil(num - 0.5)
end
end
-- | Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---@class Diesal.GUI.Window.Methods
---@field OnAcquire fun(self: Diesal.GUI.Object.Window)
---@field OnRelease fun(self: Diesal.GUI.Object.Window)
---@field SetTopLevel fun(self: Diesal.GUI.Object.Window)
---@field SetContentHeight fun(self: Diesal.GUI.Object.Window, height: number)
---@field ApplySettings fun(self: Diesal.GUI.Object.Window)
---@field UpdatePosition fun(self: Diesal.GUI.Object.Window)
---@field UpdateSizers fun(self: Diesal.GUI.Object.Window)
---@field SetTitle fun(self: Diesal.GUI.Object.Window, title?: string, subtitle?: string)
local methods = {
---@param self Diesal.GUI.Object.Window
["OnAcquire"] = function(self)
self:ApplySettings()
self:SetStylesheet(Stylesheet)
-- self:SetStylesheet(sizerWireFrame)
self:Show()
end,
["OnRelease"] = function(self) end,
["SetTopLevel"] = function(self)
self.frame:SetToplevel(true)
end,
---@param height number
["SetContentHeight"] = function(self, height)
local contentHeight = round(self.content:GetHeight())
self.frame:SetHeight((self.settings.height - contentHeight) + height)
end,
["ApplySettings"] = function(self)
local settings = self.settings
local frame = self.frame
local titleBar = self.titleBar
local closeButton = self.closeButton
local header = self.header
local content = self.content
local footer = self.footer
local headerHeight = settings.header and settings.headerHeight or 0
local footerHeight = settings.footer and settings.footerHeight or 0
frame:SetResizeBounds(settings.minWidth, settings.minHeight, settings.maxWidth, settings.maxHeight)
self:UpdatePosition()
self:UpdateSizers()
titleBar:SetHeight(settings.titleBarHeight)
closeButton:SetHeight(settings.titleBarHeight - 6)
closeButton:SetWidth(settings.titleBarHeight - 6)
content:SetPoint("TOPLEFT", settings.padding[1], -(settings.titleBarHeight + headerHeight + settings.padding[3]))
content:SetPoint("BOTTOMRIGHT", -settings.padding[2], footerHeight + settings.padding[4])
header:SetHeight(headerHeight)
footer:SetHeight(footerHeight)
header[settings.header and "Show" or "Hide"](header)
footer[settings.footer and "Show" or "Hide"](footer)
header:SetPoint("TOPLEFT", self.titleBar, "BOTTOMLEFT", settings.padding[1], 0)
header:SetPoint("TOPRIGHT", self.titleBar, "BOTTOMRIGHT", -settings.padding[2], 0)
footer:SetPoint("BOTTOMLEFT", settings.padding[1], settings.padding[4])
footer:SetPoint("BOTTOMRIGHT", -settings.padding[2], settings.padding[4])
end,
["UpdatePosition"] = function(self)
self.frame:ClearAllPoints()
if self.settings.top and self.settings.left then
self.frame:SetPoint("TOP", UIParent, "BOTTOM", 0, self.settings.top)
self.frame:SetPoint("LEFT", UIParent, "LEFT", self.settings.left, 0)
else
self.frame:SetPoint("CENTER", UIParent, "CENTER")
end
self.frame:SetWidth(self.settings.width)
self.frame:SetHeight(self.settings.height)
end,
["UpdateSizers"] = function(self)
local settings = self.settings
local frame = self.frame
local sizerB = self.sizerB
local sizerR = self.sizerR
local sizerBR = self.sizerBR
sizerBR[settings.sizerBR and "Show" or "Hide"](sizerBR)
sizerBR:SetSize(settings.sizerBRWidth, settings.sizerBRHeight)
sizerB[settings.sizerB and "Show" or "Hide"](sizerB)
sizerB:SetHeight(settings.sizerHeight)
sizerB:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -settings.sizerBRWidth, 0)
sizerR[settings.sizerR and "Show" or "Hide"](sizerR)
sizerR:SetWidth(settings.sizerWidth)
sizerR:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, -settings.titleBarHeight)
sizerR:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 0, settings.sizerBRHeight)
end,
---@param title string
---@param subtitle? string
["SetTitle"] = function(self, title, subtitle)
local settings = self.settings
settings.title = title or settings.title
settings.subTitle = subtitle or settings.subTitle
self.titletext:SetText(("%s |cff7f7f7f%s"):format(settings.title, settings.subTitle))
end,
}
---@alias PaddingLeft number
---@alias PaddingRight number
---@alias PaddingTop number
---@alias PaddingBottom number
---@class Diesal.GUI.Window.Settings
---@field footer boolean -- false
---@field footerHeight number -- 21
---@field header boolean -- false
---@field headerHeight number -- 21
---@field height number -- 300
---@field left? number
---@field maxHeight number -- 9999
---@field maxWidth number -- 9999
---@field minHeight number -- 200
---@field minWidth number -- 200
---@field padding { [1]: PaddingLeft, [2]: PaddingRight, [3]: PaddingTop, [4]: PaddingBottom } -- Left, Right, Top, Bottom
---@field sizerB boolean -- true
---@field sizerBR boolean -- true
---@field sizerBRHeight number -- 6,
---@field sizerBRWidth number -- 6,
---@field sizerHeight number -- 6
---@field sizerR boolean -- true
---@field sizerWidth number -- 6
---@field subTitle string -- ""
---@field title string -- ""
---@field titleBarHeight number -- 18,
---@field top? number
---@field width number -- 500,
---@class DiesalWindow : Diesal.GUI.Object.Window
-- | Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
---@class Diesal.GUI.Object.Window : Diesal.GUI.ObjectBase, Diesal.GUI.Window.Methods
---@field frame Frame
---@field titleBar Button
---@field closeButton Button
---@field titletext FontString
---@field header Frame
---@field content Frame
---@field footer Frame
---@field sizerR Frame
---@field sizerB Frame
---@field sizerBR Frame
---@field listener Tinkr.Util.GUIBuilder.Listener
---@field status_listener Tinkr.Util.GUIBuilder.Listener
---@field settings Diesal.GUI.Window.Settings
---@field defaults Diesal.GUI.Window.Settings
local self = DiesalGUI:Create(Type, true)
self.isContainer = true
local frame = CreateFrame("Frame", nil, DiesalGUI.UIParent)
frame:SetClampedToScreen(true)
self.frame = frame
self.defaults = {
height = 300,
width = 500,
minHeight = 200,
minWidth = 200,
maxHeight = 9999,
maxWidth = 9999,
left = nil,
top = nil,
titleBarHeight = 18,
title = "",
subTitle = "",
padding = { 1, 1, 0, 1 },
header = false,
headerHeight = 21,
footer = false,
footerHeight = 21,
sizerR = true,
sizerB = true,
sizerBR = true,
sizerWidth = 6,
sizerHeight = 6,
sizerBRHeight = 6,
sizerBRWidth = 6,
}
-- ~~ Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OnAcquire, OnRelease, OnHeightSet, OnWidthSet
-- OnSizeChanged, OnDragStop, OnHide, OnShow, OnClose
-- ~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
frame:EnableMouse()
frame:SetMovable(true)
frame:SetResizable(true)
frame:SetScript("OnMouseDown", function(this, button)
DiesalGUI:OnMouse(this, button)
end)
frame:SetScript("OnSizeChanged", function(this, width, height)
self.settings.width = DiesalTools.Round(width)
self.settings.height = DiesalTools.Round(height)
self:FireEvent("OnSizeChanged", self.settings.width, self.settings.height)
end)
frame:SetScript("OnHide", function(this)
self:FireEvent("OnHide")
end)
frame:SetScript("OnShow", function(this)
self:FireEvent("OnShow")
end)
frame:SetToplevel(true)
local titleBar = self:CreateRegion("Button", "titleBar", frame)
titleBar:SetPoint("TOPLEFT")
titleBar:SetPoint("TOPRIGHT")
titleBar:EnableMouse()
titleBar:SetScript("OnMouseDown", function(this, button)
DiesalGUI:OnMouse(this, button)
frame:StartMoving()
end)
titleBar:SetScript("OnMouseUp", function(this)
frame:StopMovingOrSizing()
self.settings.top = DiesalTools.Round(frame:GetTop())
self.settings.left = DiesalTools.Round(frame:GetLeft())
self:UpdatePosition()
self:FireEvent("OnDragStop", self.settings.left, self.settings.top)
end)
local closeButton = self:CreateRegion("Button", "closeButton", titleBar)
closeButton:SetNormalAtlas("uitools-icon-close")
closeButton:SetHighlightAtlas("uitools-icon-close")
closeButton:GetHighlightTexture():SetVertexColor(1, 0, 0, 1)
--closeButton:SetPushedAtlas("simplecheckout-close-pressed-1x")
--closeButton:GetHighlightTexture():SetVertexColor(1, 0, 0, 1)
closeButton:SetScript("OnEnter",function()
closeButton:GetNormalTexture():Hide()
end)
closeButton:SetScript("OnLeave", function()
closeButton:GetNormalTexture():Show()
end)
closeButton:SetPoint("RIGHT", -5, -0)
closeButton:SetScript("OnClick", function(this, button)
DiesalGUI:OnMouse(this, button)
PlaySound(799)
self:FireEvent("OnClose")
self:Hide()
end)
local titletext = self:CreateRegion("FontString", "titletext", titleBar)
titletext:SetWordWrap(false)
titletext:SetPoint("LEFT", 4, 0)
titletext:SetPoint("RIGHT", -20, 0)
titletext:SetJustifyH("LEFT")
self:CreateRegion("Frame", "header", frame)
self:CreateRegion("Frame", "content", frame)
self:CreateRegion("Frame", "footer", frame)
local sizerBR = self:CreateRegion("Frame", "sizerBR", frame)
sizerBR:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 0, 0)
sizerBR:EnableMouse()
sizerBR:SetScript("OnMouseDown", function(this, button)
DiesalGUI:OnMouse(this, button)
frame:StartSizing("BOTTOMRIGHT")
end)
sizerBR:SetScript("OnMouseUp", function(this)
frame:StopMovingOrSizing()
self:UpdatePosition()
self:FireEvent("OnSizeStop", self.settings.width, self.settings.height)
end)
local sizerB = self:CreateRegion("Frame", "sizerB", frame)
sizerB:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 0, 0)
sizerB:EnableMouse()
sizerB:SetScript("OnMouseDown", function(this, button)
DiesalGUI:OnMouse(this, button)
frame:StartSizing("BOTTOM")
end)
sizerB:SetScript("OnMouseUp", function(this)
frame:StopMovingOrSizing()
self:UpdatePosition()
self:FireEvent("OnSizeStop", self.settings.width, self.settings.height)
end)
local sizerR = self:CreateRegion("Frame", "sizerR", frame)
sizerR:EnableMouse()
sizerR:SetScript("OnMouseDown", function(this, button)
DiesalGUI:OnMouse(this, button)
frame:StartSizing("RIGHT")
end)
sizerR:SetScript("OnMouseUp", function(this)
frame:StopMovingOrSizing()
self:UpdatePosition()
self:FireEvent("OnSizeStop", self.settings.width, self.settings.height)
end)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self:SetMethods(methods)
self:SetObj(self.frame)
--[[ for method, func in pairs(methods) do
self[method] = func
end ]]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type, Constructor, Version)