TradeSkillMaster/Core/UI/Elements/LargeApplicationFrame.lua

205 lines
6.9 KiB
Lua

-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
--- LargeApplicationFrame UI Element Class.
-- This is the base frame of the large TSM windows which have tabs along the top (i.e. MainUI, AuctionUI, CraftingUI).
-- It is a subclass of the @{ApplicationFrame} class.
-- @classmod LargeApplicationFrame
local _, TSM = ...
local LargeApplicationFrame = TSM.Include("LibTSMClass").DefineClass("LargeApplicationFrame", TSM.UI.ApplicationFrame)
local UIElements = TSM.Include("UI.UIElements")
UIElements.Register(LargeApplicationFrame)
TSM.UI.LargeApplicationFrame = LargeApplicationFrame
local private = {}
local NAV_BAR_SPACING = 16
local NAV_BAR_HEIGHT = 24
local NAV_BAR_RELATIVE_LEVEL = 21
local NAV_BAR_TOP_OFFSET = -8
-- ============================================================================
-- Meta Class Methods
-- ============================================================================
function LargeApplicationFrame.__init(self)
self.__super:__init()
self._buttons = {}
self._selectedButton = nil
self._buttonIndex = {}
end
function LargeApplicationFrame.Acquire(self)
self:SetContentFrame(UIElements.New("Frame", "content")
:SetLayout("VERTICAL")
:SetBackgroundColor("FRAME_BG")
)
self.__super:Acquire()
end
function LargeApplicationFrame.Release(self)
wipe(self._buttons)
wipe(self._buttonIndex)
self._selectedButton = nil
self.__super:Release()
end
-- ============================================================================
-- Public Class Methods
-- ============================================================================
--- Sets the context table.
-- This table can be used to preserve position, size, and current page information across lifecycles of the frame and
-- even WoW sessions if it's within the settings DB.
-- @see ApplicationFrame.SetContextTable
-- @tparam LargeApplicationFrame self The large application frame object
-- @tparam table tbl The context table
-- @tparam table defaultTbl Default values (see @{ApplicationFrame.SetContextTable} for fields)
-- @treturn LargeApplicationFrame The large application frame object
function LargeApplicationFrame.SetContextTable(self, tbl, defaultTbl)
assert(defaultTbl.page)
tbl.page = tbl.page or defaultTbl.page
self.__super:SetContextTable(tbl, defaultTbl)
return self
end
--- Adds a top-level navigation button.
-- @tparam LargeApplicationFrame self The large application frame object
-- @tparam string text The button text
-- @tparam function drawCallback The function called when the button is clicked to get the corresponding content
-- @treturn LargeApplicationFrame The large application frame object
function LargeApplicationFrame.AddNavButton(self, text, drawCallback)
local button = UIElements.New("AlphaAnimatedFrame", "NavBar_"..text)
:SetRange(1, 0.3)
:SetDuration(1)
:SetLayout("HORIZONTAL")
:SetRelativeLevel(NAV_BAR_RELATIVE_LEVEL)
:SetContext(drawCallback)
:AddChild(UIElements.New("Button", "button")
:SetText(text)
:SetScript("OnEnter", private.OnNavBarButtonEnter)
:SetScript("OnLeave", private.OnNavBarButtonLeave)
:SetScript("OnClick", private.OnNavBarButtonClicked)
)
self:AddChildNoLayout(button)
tinsert(self._buttons, button)
self._buttonIndex[text] = #self._buttons
if self._buttonIndex[text] == self._contextTable.page then
self:SetSelectedNavButton(text)
end
return self
end
--- Set the selected nav button.
-- @tparam LargeApplicationFrame self The large application frame object
-- @tparam string buttonText The button text
-- @tparam boolean redraw Whether or not to redraw the frame
function LargeApplicationFrame.SetSelectedNavButton(self, buttonText, redraw)
if buttonText == self._selectedButton then
return
end
local index = self._buttonIndex[buttonText]
self._contextTable.page = index
self._selectedButton = buttonText
self._contentFrame:ReleaseAllChildren()
self._contentFrame:AddChild(self._buttons[index]:GetContext()(self))
if redraw then
self:Draw()
end
return self
end
--- Get the selected nav button.
-- @tparam LargeApplicationFrame self The large application frame object
-- @treturn string The text of the selected button
function LargeApplicationFrame.GetSelectedNavButton(self)
return self._selectedButton
end
--- Sets which nav button is pulsing.
-- @tparam LargeApplicationFrame self The large application frame object
-- @tparam ?string buttonText The button text or nil if no nav button should be pulsing
function LargeApplicationFrame.SetPulsingNavButton(self, buttonText)
local index = buttonText and self._buttonIndex[buttonText]
for i, button in ipairs(self._buttons) do
if not index or i ~= index then
button:SetPlaying(false)
elseif not button:IsPlaying() then
button:SetPlaying(true)
end
end
end
function LargeApplicationFrame.Draw(self)
self.__super:Draw()
for i, buttonFrame in ipairs(self._buttons) do
local button = buttonFrame:GetElement("button")
button:SetFont("BODY_BODY1_BOLD")
button:SetTextColor(i == self._contextTable.page and "INDICATOR" or "TEXT_ALT")
button:Draw()
buttonFrame:SetSize(button:GetStringWidth(), NAV_BAR_HEIGHT)
end
local offsetX = 104
for _, buttonFrame in ipairs(self._buttons) do
local buttonWidth = buttonFrame:GetElement("button"):GetStringWidth()
buttonFrame:SetSize(buttonWidth, NAV_BAR_HEIGHT)
buttonFrame:WipeAnchors()
buttonFrame:AddAnchor("TOPLEFT", offsetX, NAV_BAR_TOP_OFFSET)
offsetX = offsetX + buttonWidth + NAV_BAR_SPACING
-- draw the buttons again now that we know their dimensions
buttonFrame:Draw()
end
end
-- ============================================================================
-- Private Class Methods
-- ============================================================================
function LargeApplicationFrame._SetResizing(self, resizing)
for _, button in ipairs(self._buttons) do
if resizing then
button:Hide()
else
button:Show()
end
end
self.__super:_SetResizing(resizing)
end
-- ============================================================================
-- Local Script Handlers
-- ============================================================================
function private.OnNavBarButtonEnter(button)
if button:GetBaseElement():GetSelectedNavButton() == button:GetText() then
return
end
button:SetTextColor("TEXT")
:Draw()
end
function private.OnNavBarButtonLeave(button)
if button:GetBaseElement():GetSelectedNavButton() == button:GetText() then
return
end
button:SetTextColor("TEXT_ALT")
:Draw()
end
function private.OnNavBarButtonClicked(button)
local self = button:GetParentElement():GetParentElement()
self:SetSelectedNavButton(button:GetText(), true)
end