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.

531 lines
17 KiB

---@type Tinkr, Bastion
---@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 Type = "DiesalObjectBase"
local Version = 1
---@class Diesal.GUI.ObjectBase.Methods
local ObjectBase = {
--#region Diesal.GUI.Objectbase.BaseMethods
--#region BlizzardFrameMethods
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
Hide = function(self)
self.frame:Hide()
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
Show = function(self)
self.frame:Show()
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param strata FrameStrata
SetFrameStrata = function(self, strata)
self.frame:SetFrameStrata(strata)
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param parent Frame
SetParent = function(self, parent)
local frame = self.frame
frame:SetParent(nil)
frame:SetParent(parent)
self.settings.parent = parent
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
GetWidth = function(self)
return self.frame:GetWidth()
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param width number
SetWidth = function(self, width)
self.settings.width = width
self.frame:SetWidth(width)
self:FireEvent("OnWidthSet", width)
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param ignoreRect? boolean
GetHeight = function(self, ignoreRect)
return self.frame:GetHeight(ignoreRect)
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param height number
SetHeight = function(self, height)
self.settings.height = height
self.frame:SetHeight(height)
self:FireEvent("OnHeightSet", height)
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@return number width, number height
GetSize = function(self)
return self.frame:GetSize()
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param width number
---@param height number
SetSize = function(self, width, height)
self.settings.width = width
self.settings.height = height
--TODO: Transition to SetSize?
self.frame:SetSize(width, height)
--self.frame:SetHeight(height)
--self.frame:SetWidth(width)
self:FireEvent("OnWidthSet", width)
self:FireEvent("OnHeightSet", height)
self:FireEvent("OnSizeSet", width, height)
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
IsVisible = function(self)
return self.frame:IsVisible()
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
IsShown = function(self)
return self.frame:IsShown()
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
SetPoint = function(self, ...)
self.frame:SetPoint(...)
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
SetAllPoints = function(self, ...)
return self.frame:SetAllPoints(...)
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
ClearAllPoints = function(self)
return self.frame:ClearAllPoints()
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
GetNumPoints = function(self)
return self.frame:GetNumPoints()
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
GetPoint = function(self, ...)
return self.frame:GetPoint(...)
end,
--#endregion BlizzardFrameMethods
---@class Diesal.GUI.Region.FontString : FontString
---@field defaultFontObject Font
---@class Diesal.GUI.Region.EditBox : EditBox, FontableFrameMixin
---@field defaultFontObject Font
---@class Diesal.GUI.Region.ScrollingMessageFrame : ScrollingMessageFrame
---@field defaultFontObject Font
---@alias Diesal.GUI.Region.Custom
---|Diesal.GUI.Region.FontString
---|Diesal.GUI.Region.EditBox
---|Diesal.GUI.Region.ScrollingMessageFrame
---@alias Diesal.GUI.Parent.Region
---|Frame
---|Texture
---|Diesal.Object
---|BackdropTemplate
--#region DiesalObjectMethods
---@generic RT
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param regionType `RT` | "FontString" | "Texture" | "EditBox" | "ScrollingMessageFrame" | FrameType
---@param regionName string
---@param parentRegion Diesal.GUI.Parent.Region
---@param defaultFontObject? Font
---@param ... any
---@return RT
CreateRegion = function(self, regionType, regionName, parentRegion, defaultFontObject, ...)
if regionType == "FontString" then
---@class Diesal.GUI.Region.FontString
local fontString = parentRegion:CreateFontString()
fontString.defaultFontObject = defaultFontObject or _G.DiesalFontNormal
fontString:SetFont(fontString.defaultFontObject:GetFont())
fontString:SetTextColor(fontString.defaultFontObject:GetTextColor())
fontString:SetSpacing(fontString.defaultFontObject:GetSpacing())
self[regionName] = fontString
self.fontStrings[regionName] = fontString
return fontString
end
if regionType == "Texture" then
self[regionName] = parentRegion:CreateTexture(...)
return self[regionName]
end
if regionType == "EditBox" then
local editBox = CreateFrame("EditBox", nil, parentRegion, ...)
---@cast editBox Diesal.GUI.Region.EditBox
-- set Default font properties
editBox.defaultFontObject = defaultFontObject or _G.DiesalFontNormal
editBox:SetFont(editBox.defaultFontObject:GetFont())
editBox:SetTextColor(editBox.defaultFontObject:GetTextColor())
editBox:SetSpacing(editBox.defaultFontObject:GetSpacing())
editBox:HookScript("OnEscapePressed", function(this)
DiesalGUI:ClearFocus()
end)
editBox:HookScript("OnEditFocusGained", function(this)
DiesalGUI:SetFocus(this)
GameTooltip:Hide()
end)
self[regionName] = editBox
return editBox
end
if regionType == "ScrollingMessageFrame" then
local srollingMessageFrame = CreateFrame("ScrollingMessageFrame", nil, parentRegion, ...) ---@cast srollingMessageFrame Diesal.GUI.Region.ScrollingMessageFrame
-- set Default font properties
srollingMessageFrame.defaultFontObject = defaultFontObject or _G.DiesalFontNormal
srollingMessageFrame:SetFont(srollingMessageFrame.defaultFontObject:GetFont())
srollingMessageFrame:SetTextColor(srollingMessageFrame.defaultFontObject:GetTextColor())
srollingMessageFrame:SetSpacing(srollingMessageFrame.defaultFontObject:GetSpacing())
self[regionName] = srollingMessageFrame
return srollingMessageFrame
end
self[regionName] = CreateFrame(regionType, nil, parentRegion, ...)
return self[regionName]
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param methods? table<string, fun(self?: self, ...): any>
SetMethods = function(self, methods)
if methods and type(methods) == "table" then
for method, func in pairs(methods) do
if type(func) == "function" then
self.methods[method] = func
end
end
end
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T
---@param frame (Frame | BackdropTemplate | ScrollFrame | ScrollFrameTemplate)?
SetObj = function(self, frame)
---@diagnostic disable-next-line: inject-field
frame.obj = self
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
ResetFonts = function(self)
for name, fontString in pairs(self.fontStrings) do
fontString:SetFont(fontString.defaultFontObject:GetFont())
fontString:SetTextColor(fontString.defaultFontObject:GetTextColor())
fontString:SetSpacing(fontString.defaultFontObject:GetSpacing())
end
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param object Diesal.Object
AddChild = function(self, object)
tinsert(self.children, object)
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
Release = function(self)
DiesalGUI:Release(self)
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param object Diesal.Object
ReleaseChild = function(self, object)
local children = self.children
for i = 1, #children do
if children[i] == object then
children[i]:Release()
tremove(children, i)
break
end
end
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
ReleaseChildren = function(self)
local children = self.children
for i = 1, #children do
children[i]:Release()
children[i] = nil
end
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param parent? Diesal.Object
---@param addToChildren? boolean
SetParentObject = function(self, parent, addToChildren)
local frame = self.frame
local settings = self.settings
frame:SetParent(nil)
if parent then
frame:SetParent(parent.content)
settings.parent = parent.content
end
settings.parentObject = parent
if parent and addToChildren then
parent:AddChild(self)
end
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param settings table
---@param apply? boolean
SetSettings = function(self, settings, apply)
for key, value in pairs(settings) do
self.settings[key] = value
end
if apply then
self:ApplySettings()
end
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param apply? boolean
ResetSettings = function(self, apply)
self.settings = DiesalTools.TableCopy(self.defaults or {})
if apply then
self:ApplySettings()
end
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param event string
FireEvent = function(self, event, ...)
if self.eventListeners[event] then
for _, listener in ipairs(self.eventListeners[event]) do
listener(self, event, ...)
end
--return self.eventListeners[event](self, event, ...)
end
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param event string
---@param listener fun(self: T, event: string, ...: any)
AddEventListener = function(self, event, listener)
if type(listener) == "function" then
--self.eventListeners[event] = listener
if not self.eventListeners[event] then
self.eventListeners[event] = {}
end
table.insert(self.eventListeners[event], listener)
else
error("listener is required to be a function", 2)
end
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param event string
---@param listener fun(self: T, event: string, ...: any)
SetEventListener = function(self, event, listener)
if type(listener) == "function" then
--self.eventListeners[event] = listener
if not self.eventListeners[event] then
self.eventListeners[event] = {}
end
table.insert(self.eventListeners[event], listener)
else
error("listener is required to be a function", 2)
end
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
ResetEventListeners = function(self)
for k in pairs(self.eventListeners) do
self.eventListeners[k] = nil
end
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param name string
---@param style Diesal.Style.Style
SetStyle = function(self, name, style)
DiesalStyle:SetObjectStyle(self, name, style)
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param name string
---@param style Diesal.Style.Style
UpdateStyle = function(self, name, style)
DiesalStyle:UpdateObjectStyle(self, name, style)
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param Stylesheet Diesal.Style.Stylesheet
UpdateStylesheet = function(self, Stylesheet)
DiesalStyle:UpdateObjectStylesheet(self, Stylesheet)
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param Stylesheet Diesal.Style.Stylesheet
SetStylesheet = function(self, Stylesheet)
DiesalStyle:SetObjectStylesheet(self, Stylesheet)
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
---@param name string
ReleaseTexture = function(self, name)
if not self.textures[name] then
return
end
DiesalStyle:ReleaseTexture(self, name)
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
ReleaseTextures = function(self)
DiesalStyle:ReleaseTextures(self)
end,
---@generic T : Diesal.GUI.ObjectBase
---@param self T | Diesal.GUI.ObjectBase
ApplySettings = function(self) end,
--#endregion DiesalObjectMethods
--#endregion Diesal.GUI.Objectbase.BaseMethods
}
DiesalGUI.ObjectBase = ObjectBase
---@class Diesal.GUI.ObjectBase.Settings
---@field parent Frame
---@field parentObject Diesal.Object?
---@field height number
---@field width number
---@class Diesal.GUI.ObjectBase.Methods
---@field OnAcquire fun(self)
---@field OnRelease fun(self)
---@field ApplySettings fun(self)
---@alias DiesalObjectBase Diesal.GUI.ObjectBase
---@class SelfFrame : Frame
---@field obj DiesalObjectBase
-- Returns an Object Base
---@param objectType string | Diesal.Object.Type
local Constructor = function(objectType)
---@class Diesal.GUI.ObjectBase : Diesal.GUI.ObjectBase.Methods
---@field frame SelfFrame
---@field isContainer boolean
---@field type Diesal.Object.Type
---@field fontStrings { [string]: Diesal.GUI.Region.FontString }
---@field textures { [string]: Diesal.Style.Texture }
---@field children { [number]: Diesal.GUI.ObjectBase }
---@field eventListeners { [string]: fun(self: self, event: string, ...)[] }
---@field settings Diesal.GUI.ObjectBase.Settings
---@field defaults Diesal.GUI.ObjectBase.Settings
local object = {
isContainer = false,
type = objectType,
fontStrings = {},
textures = {},
children = {},
eventListeners = {},
methods = {},
userdata = {},
}
for k, v in pairs(ObjectBase) do
object.methods[k] = v
end
setmetatable(object, {
---@param self Diesal.GUI.ObjectBase
---@param k string
__index = function(self, k)
-- Look for replaced methods.
local response = self.methods[k]
if response ~= nil then
return response
end
return rawget(self, k)
end,
})
return object
end
DiesalGUI:RegisterObjectConstructor(Type, Constructor, Version)
--[[ function DiesalGUI:CreateObjectBase(objectType)
local object = {
isContainer = false,
type = objectType,
fontStrings = {},
textures = {},
children = {},
eventListeners = {},
}
setmetatable(object, { __index = ObjectBase })
return object
end ]]