enUS Localization Update Announcement / localization-update-announcement (push) Canceled after 0s
307 lines
12 KiB
Lua
307 lines
12 KiB
Lua
-- Bagshui UI Class: Window Frames
|
|
|
|
Bagshui:AddComponent(function()
|
|
local Ui = Bagshui.prototypes.Ui
|
|
|
|
--- Create a frame to be used as the basis of a window.
|
|
--- Adding a title will automatically create a title bar with close button.
|
|
---@param name string Unique name for the window (will be passed to `Ui:CreateElementName()`).
|
|
---@param parent table? Parent frame (default: `UIParent`).
|
|
---@param height number? Default: 500.
|
|
---@param width number? Default: 500.
|
|
---@param title string? Text to display in the title bar.
|
|
---@param noCloseOnEscape boolean? Don't set this frame to be closed when the escape key is pressed.
|
|
---@return table window
|
|
function Ui:CreateWindowFrame(name, parent, height, width, title, noCloseOnEscape)
|
|
local frameParent = parent or _G.UIParent
|
|
|
|
local frame = _G.CreateFrame("Frame", self:CreateElementName(name), frameParent)
|
|
frame.bagshuiData = {
|
|
isWindow = true, -- Used in a couple of places to differentiate "window" frames from all other types.
|
|
}
|
|
|
|
-- Set required properties.
|
|
frame:SetToplevel(true) -- The frame won't come to the front when clicked without this.
|
|
frame:SetMovable(true)
|
|
frame:EnableMouse(true)
|
|
frame:RegisterForDrag("LeftButton")
|
|
frame:SetWidth((height or 500))
|
|
frame:SetHeight((width or 500))
|
|
|
|
-- Make draggable.
|
|
frame:SetScript("OnDragStart", function()
|
|
if frame:IsMovable() then
|
|
frame:StartMoving()
|
|
end
|
|
end)
|
|
frame:SetScript("OnDragStop", function()
|
|
frame:StopMovingOrSizing()
|
|
end)
|
|
|
|
-- Open/Close events.
|
|
frame:SetScript("OnShow", function()
|
|
Bagshui:RaiseEvent("BAGSHUI_WINDOW_OPENED", false, frame)
|
|
end)
|
|
frame:SetScript("OnHide", function()
|
|
Bagshui:RaiseEvent("BAGSHUI_WINDOW_CLOSED", false, frame)
|
|
end)
|
|
|
|
-- Set default style and color.
|
|
self:SetFrameBackdrop(frame)
|
|
frame:SetBackdropColor(
|
|
BsSkin.frameBackgroundColor[1],
|
|
BsSkin.frameBackgroundColor[2],
|
|
BsSkin.frameBackgroundColor[3],
|
|
BsSkin.frameBackgroundColor[4] or 1
|
|
)
|
|
if BsSkin.frameBorderColor then
|
|
frame:SetBackdropBorderColor(
|
|
BsSkin.frameBorderColor[1],
|
|
BsSkin.frameBorderColor[2],
|
|
BsSkin.frameBorderColor[3],
|
|
BsSkin.frameBorderColor[4] or 1
|
|
)
|
|
end
|
|
|
|
-- Add title bar and close button.
|
|
if title then
|
|
frame.bagshuiData.header, frame.bagshuiData.title, frame.bagshuiData.closeButton =
|
|
self:CreateTitleBar(frame, title)
|
|
end
|
|
|
|
-- Shouldn't be visible by default.
|
|
frame:Hide()
|
|
|
|
-- Close when escape is pressed.
|
|
if not noCloseOnEscape then
|
|
Bagshui:RegisterFrameForCloseOnEscape(frame)
|
|
end
|
|
|
|
return frame
|
|
end
|
|
|
|
--- Create a frame whose only contents are a full-size scrollable edit box.
|
|
--- Always generates a title bar.
|
|
---@param name string Parameter for `Ui:CreateWindowFrame()`.
|
|
---@param parent table? Parameter for `Ui:CreateWindowFrame()`.
|
|
---@param height number? Parameter for `Ui:CreateWindowFrame()`.
|
|
---@param width number? Parameter for `Ui:CreateWindowFrame()`.
|
|
---@param title string? Parameter for `Ui:CreateWindowFrame()` (default: `Edit Window`).
|
|
---@param noCloseOnEscape boolean? Parameter for `Ui:CreateWindowFrame()`.
|
|
---@param fontObject string|table? Parameter for `Ui:CreateEditBox()`.
|
|
---@param selectAllOnFocus boolean? Parameter for `Ui:CreateEditBox()`.
|
|
---@return table window
|
|
---@return table scrollFrame
|
|
---@return table editBox
|
|
function Ui:CreateScrollableEditBoxWindow(
|
|
name,
|
|
parent,
|
|
height,
|
|
width,
|
|
title,
|
|
noCloseOnEscape,
|
|
fontObject,
|
|
selectAllOnFocus
|
|
)
|
|
local frame = self:CreateWindowFrame(name, parent, height, width, title, noCloseOnEscape)
|
|
|
|
local scrollFrame, editBox = self:CreateScrollableEditBox(
|
|
"EditScroll",
|
|
frame,
|
|
nil, -- borderStyle
|
|
nil, -- editBoxInherits
|
|
fontObject,
|
|
selectAllOnFocus
|
|
)
|
|
if frame.bagshuiData.header then
|
|
self:SetPoint(scrollFrame, "TOPLEFT", frame.bagshuiData.header, "BOTTOMLEFT", 0, -2)
|
|
else
|
|
self:SetPoint(scrollFrame, "TOPLEFT", frame, "TOPLEFT", BsSkin.windowPadding, -BsSkin.windowPadding)
|
|
end
|
|
self:SetPoint(scrollFrame, "BOTTOMRIGHT", frame, "BOTTOMRIGHT", -BsSkin.windowPadding, BsSkin.windowPadding)
|
|
-- Manually setting width so that the EditBox can be properly sized.
|
|
self:SetWidth(scrollFrame, frame:GetWidth() - (BsSkin.windowPadding * 2))
|
|
|
|
frame.bagshuiData.scrollFrame = scrollFrame
|
|
frame.bagshuiData.editBox = editBox
|
|
|
|
return frame, scrollFrame, editBox
|
|
end
|
|
|
|
--- Add a title bar (header frame, window title, and close button) to a window frame.
|
|
---@param windowFrame table Frame created by `Ui:CreateWindowFrame()`.
|
|
---@param windowTitleText string Parameter for `Ui:CreateWindowTitle()`.
|
|
---@param closeFunction function? `clickFunction` parameter for `Ui:CreateWindowTitle()`.
|
|
---@return table header Frame
|
|
---@return table title FontString
|
|
---@return table closeButton Button
|
|
function Ui:CreateTitleBar(windowFrame, windowTitleText, closeFunction)
|
|
local header = self:CreateHeaderFooter("Header", windowFrame, "TOP", BsSkin.windowTitleBarHeight)
|
|
|
|
local title = self:CreateWindowTitle("Title", header, windowTitleText, "LEFT", 0, 0)
|
|
|
|
local closeButton = self:CreateCloseButton("CloseButton", header, "RIGHT", 0, 0, closeFunction)
|
|
|
|
return header, title, closeButton
|
|
end
|
|
|
|
--- Create a header or footer frame for a window.
|
|
--- By default will create a header anchored to the top, but if `anchorTopBottom == "BOTTOM"` a footer will be created.
|
|
---@param name string Unique name for the element (will be passed to `Ui:CreateElementName()`).
|
|
---@param windowFrame table Parent frame.
|
|
---@param anchorTopBottom string? `"TOP"` (header) or `"BOTTOM"` (footer).
|
|
---@param height number? Defaults to `BsSkin.windowHeaderFooterHeight`.
|
|
---@param xOffset number? See code for default.
|
|
---@param yOffset number? See code for default.
|
|
---@return table headerOrFooter
|
|
function Ui:CreateHeaderFooter(name, windowFrame, anchorTopBottom, height, xOffset, yOffset)
|
|
-- Figure out positioning.
|
|
anchorTopBottom = (anchorTopBottom == "BOTTOM") and "BOTTOM" or "TOP"
|
|
local invertY = (anchorTopBottom == "TOP") and -1 or 1
|
|
xOffset = xOffset or BsSkin.windowPadding
|
|
yOffset = yOffset or ((BsSkin.windowPadding - BsSkin.windowHeaderFooterYAdjustment) * invertY)
|
|
|
|
-- Create header/footer.
|
|
|
|
local headerFooter = _G.CreateFrame("Frame", self:CreateElementName(name), windowFrame)
|
|
headerFooter:SetHeight(height or BsSkin.windowHeaderFooterHeight)
|
|
|
|
-- Set position.
|
|
headerFooter:SetPoint(anchorTopBottom .. "LEFT", windowFrame, xOffset, yOffset)
|
|
headerFooter:SetPoint(anchorTopBottom .. "RIGHT", windowFrame, -xOffset, yOffset)
|
|
|
|
return headerFooter
|
|
end
|
|
|
|
--- Add a window title to the given window frame.
|
|
---@param name string Unique name for the element (will be passed to `Ui:CreateElementName()`).
|
|
---@param windowFrame table Parent frame.
|
|
---@param text string Title text.
|
|
---@param anchor string? Default: `TOPLEFT`.
|
|
---@param xOffset number? Default: `BsSkin.windowPadding`.
|
|
---@param yOffset number? Default: `-BsSkin.windowPadding`.
|
|
---@return table titleText FontString
|
|
function Ui:CreateWindowTitle(name, windowFrame, text, anchor, xOffset, yOffset)
|
|
local titleText = self:CreateShadowedFontString(windowFrame, self:CreateElementName(name), "GameFontNormal")
|
|
titleText:SetPoint(
|
|
anchor or "TOPLEFT",
|
|
windowFrame,
|
|
xOffset or BsSkin.windowPadding,
|
|
yOffset or -BsSkin.windowPadding
|
|
)
|
|
titleText:SetJustifyH("LEFT")
|
|
titleText:SetJustifyV("TOP")
|
|
titleText:SetText(text)
|
|
return titleText
|
|
end
|
|
|
|
--- Add a close button to the given window frame.
|
|
---@param name string Unique name for the element (will be passed to `Ui:CreateElementName()`).
|
|
---@param windowFrame table Parent frame.
|
|
---@param anchor string? Default: `TOPRIGHT`.
|
|
---@param xOffset number? Default: `BsSkin.windowPadding`. Always is adjusted by `BsSkin.closeButtonXOffsetAdjustment`.
|
|
---@param yOffset number? Default: `-BsSkin.windowPadding`. Always is adjusted by `BsSkin.closeButtonYOffsetAdjustment`.
|
|
---@param clickFunction function|boolean? OnClick event handler. If not provided, one will be created automatically. Pass `false` to not add a click handler at all.
|
|
---@return table closeButton Button.
|
|
function Ui:CreateCloseButton(name, windowFrame, anchor, xOffset, yOffset, clickFunction)
|
|
local closeButton = _G.CreateFrame("Button", self:CreateElementName(name), windowFrame)
|
|
closeButton.bagshuiData = {}
|
|
|
|
-- Add textures, set size and position.
|
|
BsSkin.closeButtonSkinFunc(closeButton)
|
|
closeButton:SetWidth(BsSkin.closeButtonSize)
|
|
closeButton:SetHeight(BsSkin.closeButtonSize)
|
|
closeButton:SetPoint(
|
|
anchor or "TOPRIGHT",
|
|
(xOffset or -BsSkin.windowPadding) + BsSkin.closeButtonXOffsetAdjustment,
|
|
(yOffset or -BsSkin.windowPadding) + BsSkin.closeButtonYOffsetAdjustment
|
|
)
|
|
closeButton:SetHitRectInsets(
|
|
BsSkin.closeButtonHitRectInsets,
|
|
BsSkin.closeButtonHitRectInsets,
|
|
BsSkin.closeButtonHitRectInsets,
|
|
BsSkin.closeButtonHitRectInsets
|
|
)
|
|
|
|
-- Add close function.
|
|
if clickFunction ~= false then
|
|
-- When an explicit function isn't passed, we need to create the close function.
|
|
if type(clickFunction) ~= "function" then
|
|
clickFunction = nil
|
|
local parentWindow = self:FindWindowFrame(windowFrame)
|
|
|
|
if parentWindow then
|
|
-- We found a window frame, so create the function to hide it.
|
|
clickFunction = function()
|
|
Bagshui:CloseMenus()
|
|
parentWindow:Hide()
|
|
end
|
|
else
|
|
Bagshui:PrintWarning(
|
|
"UI WARNING: No parent frame found for close button '"
|
|
.. tostring(name)
|
|
.. "' (child of frame "
|
|
.. tostring(windowFrame:GetName())
|
|
.. ") -- frame may not be closable!"
|
|
)
|
|
end
|
|
end
|
|
|
|
if clickFunction then
|
|
closeButton:SetScript("OnClick", clickFunction)
|
|
end
|
|
end
|
|
|
|
return closeButton
|
|
end
|
|
|
|
--- Obscure and disable the contents of a window frame so a modal dialog can be displayed on top.
|
|
---@param window table Bagshui window frame.
|
|
---@param shadeOn boolean Whether to show or hide the shade.
|
|
---@param text string? Text to display in the middle of the shade.
|
|
function Ui:SetWindowShade(window, shadeOn, text)
|
|
if not window.bagshuiData and window.bagshuiData.isWindow then
|
|
return
|
|
end
|
|
|
|
if shadeOn then
|
|
if not window.bagshuiData.shadeFrame then
|
|
window.bagshuiData.shadeFrame = _G.CreateFrame("Frame", nil, window)
|
|
|
|
local inset = (type(BsSkin.frameDefaultBorderStyle) == "table" and BsSkin.frameDefaultBorderStyle.insets)
|
|
or BsSkin.frameBorderInsets
|
|
or BS_BORDER.CURVED.insets
|
|
window.bagshuiData.shadeFrame:SetPoint("TOPLEFT", window, "TOPLEFT", inset, -inset)
|
|
window.bagshuiData.shadeFrame:SetPoint("BOTTOMRIGHT", window, "BOTTOMRIGHT", -inset, inset)
|
|
|
|
self:SetFrameBackdrop(window.bagshuiData.shadeFrame, BsSkin.frameDefaultBorderStyle)
|
|
window.bagshuiData.shadeFrame:SetBackdropColor(0.1, 0.1, 0.1, 0.65)
|
|
window.bagshuiData.shadeFrame:SetBackdropBorderColor(0, 0, 0, 0.1)
|
|
|
|
window.bagshuiData.shadeFrameText = self:CreateShadowedFontString(window.bagshuiData.shadeFrame)
|
|
window.bagshuiData.shadeFrameText:SetPoint("CENTER", window.bagshuiData.shadeFrame)
|
|
window.bagshuiData.shadeFrameText:SetJustifyH("CENTER")
|
|
|
|
-- Need to keep the window's dragability.
|
|
window.bagshuiData.shadeFrame:EnableMouse(true)
|
|
window.bagshuiData.shadeFrame:RegisterForDrag("LeftButton")
|
|
self:PassMouseEventsThrough(window.bagshuiData.shadeFrame, window)
|
|
end
|
|
|
|
if text then
|
|
window.bagshuiData.shadeFrameText:SetText(tostring(text))
|
|
window.bagshuiData.shadeFrameText:Show()
|
|
else
|
|
window.bagshuiData.shadeFrameText:Hide()
|
|
end
|
|
|
|
window.bagshuiData.shadeFrame:SetFrameLevel(window:GetFrameLevel() + 10)
|
|
window.bagshuiData.shadeFrame:Show()
|
|
else
|
|
if window.bagshuiData.shadeFrame then
|
|
window.bagshuiData.shadeFrame:Hide()
|
|
end
|
|
end
|
|
end
|
|
end)
|