Files
2026-07-15 23:00:59 -07:00

333 lines
8.6 KiB
Lua

GuildRecipesOcto = GuildRecipesOcto or {}
---@class GuildRecipesOcto
local m = GuildRecipesOcto
if m.FrameBuilder then return end
local M = {}
---@alias FrameStyle
---| "TOOLTIP"
---| "NONE"
---@class FrameBuilder
---@field name fun( self: FrameBuilder, name: string ): FrameBuilder
---@field type fun( self: FrameBuilder, type: FrameType ): FrameBuilder
---@field title fun( self: FrameBuilder, title: string ): FrameBuilder
---@field parent fun( self: FrameBuilder, parent: Frame ): FrameBuilder
---@field point fun( self: FrameBuilder, point: FramePoint, relative_region: string|Region|nil, relative_point: FramePoint, offset_x: number?, offset_y: number?)
---@field width fun( self: FrameBuilder, width: number ): FrameBuilder
---@field height fun( self: FrameBuilder, height: number ): FrameBuilder
---@field frame_level fun( self: FrameBuilder, frame_level: number ): FrameBuilder
---@field frame_style fun( self: FrameBuilder, frame_style: FrameStyle ): FrameBuilder
---@field strata fun( self: FrameBuilder, strata: FrameStrata ): FrameBuilder
---@field movable fun( self: FrameBuilder ): FrameBuilder
---@field backdrop fun( self: FrameBuilder, backdrop: Backdrop ): FrameBuilder
---@field backdrop_color fun( self: FrameBuilder, r: number, g: number, b: number, a: number ): FrameBuilder
---@field border_color fun( self: FrameBuilder, r: number, g: number, b: number, a: number ): FrameBuilder
---@field esc fun( self: FrameBuilder ): FrameBuilder
---@field close_button fun( self: FrameBuilder ): FrameBuilder
---@field on_drag_stop fun( self: FrameBuilder, callback: function ): FrameBuilder
---@field hidden fun( self: FrameBuilder ): FrameBuilder
---@field build fun( self: FrameBuilder ): Frame
---@class FrameBuilderFactory
---@field new fun(): FrameBuilder
---@return FrameBuilder
function M.new()
local options = {
backdrop = {}
}
local is_dragging
local function create_frame()
---@param parent Frame
---@param title string
---@return Frame
local function create_titlebar( parent, title )
local frame = CreateFrame( "Frame", nil, parent )
frame:SetPoint( "TopLeft", parent, "TopLeft", 5, -5 )
frame:SetPoint( "BottomRight", parent, "TopRight", -5, -24 )
frame:SetBackdrop( { bgFile = "Interface/Buttons/WHITE8x8" } )
frame:SetBackdropColor( 0, 0, 0, 1 )
if options.frame_level then
frame:SetFrameLevel( options.frame_level )
end
local bottom_border = frame:CreateTexture( nil, "ARTWORK" )
bottom_border:SetTexture( .6, .6, .6, 1 )
bottom_border:SetPoint( "TopLeft", frame, "BottomLeft", -1, 1 )
bottom_border:SetPoint( "BottomRight", frame, "BottomRight", 1, 0 )
if options.close_button then
local btn_close = m.GuiElements.tiny_button( parent, "X", "Close Window" )
btn_close:SetPoint( "TopRight", parent, "TopRight", -4, -4 )
btn_close:SetScript( "OnClick", function() parent:Hide() end )
if options.frame_level then
btn_close:SetFrameLevel( options.frame_level + 1 )
end
end
local title_label = frame:CreateFontString( nil, "ARTWORK", "GRFontNormal" )
title_label:SetPoint( "CENTER", frame, "CENTER", 0, 0 )
title_label:SetTextColor( 1, 1, 1 )
title_label:SetJustifyH( "CENTER" )
title_label:SetText( title )
parent.title_label = title_label
return frame
end
local function create_main_frame()
local type = options.type or "Frame"
local parent = options.parent or UIParent
local frame = CreateFrame( type, options.name, parent )
frame:SetWidth( options.width or 280 )
frame:SetHeight( options.height or 100 )
frame:EnableMouse( true )
if options.frame_style == "TOOLTIP" then
frame:SetBackdrop( {
bgFile = options.backdrop.bgFile or "Interface/Tooltips/UI-Tooltip-Background",
edgeFile = options.backdrop.edgeFile or "Interface/Tooltips/UI-Tooltip-Border",
tile = true,
tileSize = 16,
edgeSize = options.backdrop.edgeSize or 16,
insets = { left = 4, right = 4, top = 4, bottom = 4 }
} )
elseif options.frame_style == "NONE" then
if options.backdrop then
frame:SetBackdrop( {
bgFile = options.backdrop.bgFile,
edgeFile = options.backdrop.edgeFile,
tile = options.backdrop.tile or false,
tileSize = options.backdrop.tileSize,
edgeSize = options.backdrop.edgeSize,
insets = options.backdrop.insets
} )
end
else
frame:SetBackdrop( {
bgFile = options.backdrop.bgFile or "Interface/Buttons/WHITE8x8",
edgeFile = options.backdrop.edgeFile or "Interface/Buttons/WHITE8x8",
tile = options.backdrop.tile or true,
tileSize = options.backdrop.tileSize or 0,
edgeSize = options.backdrop.edgeSize or 0.8,
insets = options.backdrop.insets or { left = 0, right = 0, top = 0, bottom = 0 }
} )
end
if options.points then
for _, p in pairs( options.points ) do
frame:SetPoint( p.point, p.relative_region or UIParent, p.relative_point, p.x, p.y )
end
else
frame:SetPoint( "TopLeft", UIParent, "Center", -(options.width or 200) / 2, (options.height or 200) / 2 )
end
if options.backdrop_color then
local c = options.backdrop_color
frame:SetBackdropColor( c.r, c.g, c.b, c.a or 1 )
else
frame:SetBackdropColor( 0, 0, 0, 0.7 )
end
if options.border_color then
local c = options.border_color
frame:SetBackdropBorderColor( c.r, c.g, c.b, options.frame_style == "Classic" and 1 or c.a )
end
if options.title then
create_titlebar( frame, options.title )
end
if options.hidden then
frame:Hide()
end
if options.frame_level then
frame:SetFrameLevel( options.frame_level )
end
if options.strata then
frame:SetFrameStrata( options.strata )
else
frame:SetFrameStrata( "DIALOG" )
end
if options.movable then
frame:SetMovable( true )
frame:RegisterForDrag( "LeftButton" )
frame:SetScript( "OnDragStart", function()
if not frame:IsMovable() then return end
is_dragging = true
this:StartMoving()
end )
frame:SetScript( "OnDragStop", function()
if not frame:IsMovable() then return end
is_dragging = false
frame:StopMovingOrSizing()
if options.on_drag_stop then
options.on_drag_stop( frame )
end
end )
else
frame:SetMovable( false )
end
if options.esc then
table.insert( UISpecialFrames, frame:GetName() )
end
if options.scale then
frame:SetScale( options.scale )
end
return frame
end
local frame = create_main_frame()
return frame
end
local function name( self, v )
options.name = v
return self
end
local function type( self, v )
options.type = v
return self
end
local function title( self, v )
options.title = v
return self
end
local function parent( self, v )
options.parent = v
return self
end
local function point( self, _point, relative_region, relative_point, offset_x, offset_y )
options.points = options.points or {}
table.insert( options.points, {
point = _point,
relative_region = relative_region,
relative_point = relative_point,
x = offset_x,
y = offset_y
} )
return self
end
local function width( self, v )
options.width = v
return self
end
local function height( self, v )
options.height = v
return self
end
local function frame_style( self, v )
options.frame_style = v
return self
end
local function frame_level( self, v )
options.frame_level = v
return self
end
local function strata( self, v )
options.strata = v
return self
end
local function movable( self )
options.movable = true
return self
end
local function backdrop( self, _backdrop )
options.backdrop = _backdrop
return self
end
local function backdrop_color( self, r, g, b, a )
options.backdrop_color = { r = r, g = g, b = b, a = a }
return self
end
local function border_color( self, r, g, b, a )
options.border_color = { r = r, g = g, b = b, a = a }
return self
end
local function esc( self )
options.esc = true
return self
end
local function close_button( self )
options.close_button = true
return self
end
local function on_drag_stop( self, callback )
options.on_drag_stop = callback
return self
end
local function hidden( self )
options.hidden = true
return self
end
local function build()
return create_frame()
end
---@type FrameBuilder
return {
name = name,
type = type,
title = title,
parent = parent,
point = point,
width = width,
height = height,
frame_level = frame_level,
frame_style = frame_style,
strata = strata,
movable = movable,
backdrop = backdrop,
backdrop_color = backdrop_color,
border_color = border_color,
esc = esc,
close_button = close_button,
on_drag_stop = on_drag_stop,
hidden = hidden,
build = build
}
end
m.FrameBuilder = M
return M