TradeSkillMaster/Core/UI/Elements/Button.lua

286 lines
10 KiB
Lua

-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
--- Button UI Element Class.
-- A button is a clickable element which has text drawn over top of it. It is a subclass of the @{Text} class.
-- @classmod Button
local _, TSM = ...
local Button = TSM.Include("LibTSMClass").DefineClass("Button", TSM.UI.Text)
local Theme = TSM.Include("Util.Theme")
local ItemInfo = TSM.Include("Service.ItemInfo")
local UIElements = TSM.Include("UI.UIElements")
UIElements.Register(Button)
TSM.UI.Button = Button
local ICON_SPACING = 4
-- ============================================================================
-- Public Class Methods
-- ============================================================================
function Button.__init(self)
local frame = UIElements.CreateFrame(self, "Button")
self.__super:__init(frame)
frame.backgroundTexture = frame:CreateTexture(nil, "BACKGROUND")
-- create the highlight
frame.highlight = frame:CreateTexture(nil, "HIGHLIGHT")
frame.highlight:SetAllPoints()
frame.highlight:SetBlendMode("BLEND")
frame:SetHighlightTexture(frame.highlight)
-- create the icon
frame.icon = frame:CreateTexture(nil, "ARTWORK")
self._font = "BODY_BODY1"
self._justifyH = "CENTER"
self._background = nil
self._iconTexturePack = nil
self._iconPosition = nil
self._highlightEnabled = false
end
function Button.Acquire(self)
self:_GetBaseFrame():Enable()
self:_GetBaseFrame():RegisterForClicks("LeftButtonUp")
self:_GetBaseFrame():SetHitRectInsets(0, 0, 0, 0)
self.__super:Acquire()
end
function Button.Release(self)
local frame = self:_GetBaseFrame()
frame:UnlockHighlight()
self._background = nil
self._iconTexturePack = nil
self._iconPosition = nil
self._highlightEnabled = false
self.__super:Release()
self._font = "BODY_BODY1"
self._justifyH = "CENTER"
end
--- Sets the background of the button.
-- @tparam Button self The button object
-- @tparam ?string|number|nil background Either a texture pack string, itemString, WoW file id, theme color key, or nil
-- @treturn Button The button object
function Button.SetBackground(self, background)
assert(background == nil or type(background) == "string" or type(background) == "number")
self._background = background
return self
end
--- Sets the background and size of the button based on a texture pack string.
-- @tparam Button self The button object
-- @tparam string texturePack A texture pack string to set the background to and base the size on
-- @treturn Button The button object
function Button.SetBackgroundAndSize(self, texturePack)
self:SetBackground(texturePack)
self:SetSize(TSM.UI.TexturePacks.GetSize(texturePack))
return self
end
--- Sets whether or not the highlight is enabled.
-- @tparam Button self The button object
-- @tparam boolean enabled Whether or not the highlight is enabled
-- @treturn Button The button object
function Button.SetHighlightEnabled(self, enabled)
self._highlightEnabled = enabled
return self
end
--- Sets the icon that shows within the button.
-- @tparam Button self The button object
-- @tparam[opt=nil] string texturePack A texture pack string to set the icon and its size to
-- @tparam[opt=nil] string position The positin of the icon
-- @treturn Button The button object
function Button.SetIcon(self, texturePack, position)
if texturePack or position then
assert(TSM.UI.TexturePacks.IsValid(texturePack))
assert(position == "LEFT" or position == "LEFT_NO_TEXT" or position == "CENTER" or position == "RIGHT")
self._iconTexturePack = texturePack
self._iconPosition = position
else
self._iconTexturePack = nil
self._iconPosition = nil
end
return self
end
--- Set whether or not the button is disabled.
-- @tparam Button self The button object
-- @tparam boolean disabled Whether or not the button should be disabled
-- @treturn Button The button object
function Button.SetDisabled(self, disabled)
if disabled then
self:_GetBaseFrame():Disable()
else
self:_GetBaseFrame():Enable()
end
return self
end
--- Registers the button for drag events.
-- @tparam Button self The button object
-- @tparam string button The mouse button to register for drag events from
-- @treturn Button The button object
function Button.RegisterForDrag(self, button)
self:_GetBaseFrame():RegisterForDrag(button)
return self
end
--- Click on the button.
-- @tparam Button self The button object
function Button.Click(self)
self:_GetBaseFrame():Click()
end
--- Enable right-click events for the button.
-- @tparam Button self The button object
-- @treturn Button The button object
function Button.EnableRightClick(self)
self:_GetBaseFrame():RegisterForClicks("LeftButtonUp", "RightButtonUp")
return self
end
--- Set the hit rectangle insets for the button.
-- @tparam Button self The button object
-- @tparam number left How much the left side of the hit rectangle is inset
-- @tparam number right How much the right side of the hit rectangle is inset
-- @tparam number top How much the top side of the hit rectangle is inset
-- @tparam number bottom How much the bottom side of the hit rectangle is inset
-- @treturn Button The button object
function Button.SetHitRectInsets(self, left, right, top, bottom)
self:_GetBaseFrame():SetHitRectInsets(left, right, top, bottom)
return self
end
--- Set whether or not to lock the button's highlight.
-- @tparam Button self The action button object
-- @tparam boolean locked Whether or not to lock the action button's highlight
-- @treturn Button The action button object
function Button.SetHighlightLocked(self, locked)
if locked then
self:_GetBaseFrame():LockHighlight()
else
self:_GetBaseFrame():UnlockHighlight()
end
return self
end
function Button.Draw(self)
local frame = self:_GetBaseFrame()
frame.text:Show()
self.__super:Draw()
frame.backgroundTexture:SetTexture(nil)
frame.backgroundTexture:SetTexCoord(0, 1, 0, 1)
frame.backgroundTexture:SetVertexColor(1, 1, 1, 1)
if self._background == nil then
frame.backgroundTexture:Hide()
elseif type(self._background) == "string" and TSM.UI.TexturePacks.IsValid(self._background) then
-- this is a texture pack
frame.backgroundTexture:Show()
frame.backgroundTexture:ClearAllPoints()
frame.backgroundTexture:SetPoint("CENTER")
TSM.UI.TexturePacks.SetTextureAndSize(frame.backgroundTexture, self._background)
elseif type(self._background) == "string" and strmatch(self._background, "^[ip]:%d+") then
-- this is an itemString
frame.backgroundTexture:Show()
frame.backgroundTexture:ClearAllPoints()
frame.backgroundTexture:SetAllPoints()
frame.backgroundTexture:SetTexture(ItemInfo.GetTexture(self._background))
elseif type(self._background) == "string" then
-- this is a theme color key
frame.backgroundTexture:Show()
frame.backgroundTexture:ClearAllPoints()
frame.backgroundTexture:SetAllPoints()
frame.backgroundTexture:SetColorTexture(Theme.GetColor(self._background):GetFractionalRGBA())
elseif type(self._background) == "number" then
-- this is a wow file id
frame.backgroundTexture:Show()
frame.backgroundTexture:ClearAllPoints()
frame.backgroundTexture:SetAllPoints()
frame.backgroundTexture:SetTexture(self._background)
else
error("Invalid background: "..tostring(self._background))
end
-- set the text color
local textColor = frame:IsEnabled() and self:_GetTextColor() or Theme.GetColor("ACTIVE_BG_ALT")
frame.text:SetTextColor(textColor:GetFractionalRGBA())
-- set the highlight texture
if self._highlightEnabled then
frame.highlight:SetColorTexture(Theme.GetColor(self._background):GetTint("+HOVER"):GetFractionalRGBA())
else
frame.highlight:SetColorTexture(0, 0, 0, 0)
end
if self._iconTexturePack then
TSM.UI.TexturePacks.SetTextureAndSize(frame.icon, self._iconTexturePack)
frame.icon:Show()
frame.icon:ClearAllPoints()
frame.icon:SetVertexColor(textColor:GetFractionalRGBA())
local iconWidth = TSM.UI.TexturePacks.GetWidth(self._iconTexturePack) + ICON_SPACING
if self._iconPosition == "LEFT" then
frame.icon:SetPoint("RIGHT", frame.text, "LEFT", -ICON_SPACING, 0)
frame.text:ClearAllPoints()
if self._justifyH == "CENTER" then
local xOffset = iconWidth / 2
frame.text:SetPoint("TOP", xOffset, -self:_GetPadding("TOP"))
frame.text:SetPoint("BOTTOM", xOffset, self:_GetPadding("BOTTOM"))
frame.text:SetWidth(frame.text:GetStringWidth())
elseif self._justifyH == "LEFT" then
frame.text:SetPoint("TOPLEFT", iconWidth + self:_GetPadding("LEFT"), -self:_GetPadding("TOP"))
frame.text:SetPoint("BOTTOMRIGHT", -self:_GetPadding("RIGHT"), self:_GetPadding("BOTTOM"))
else
error("Unsupported justifyH: "..tostring(self._justifyH))
end
elseif self._iconPosition == "LEFT_NO_TEXT" then
frame.icon:SetPoint("LEFT", self:_GetPadding("LEFT"), 0)
frame.text:ClearAllPoints()
frame.text:Hide()
elseif self._iconPosition == "CENTER" then
frame.icon:SetPoint("CENTER")
frame.text:ClearAllPoints()
frame.text:Hide()
elseif self._iconPosition == "RIGHT" then
frame.icon:SetPoint("RIGHT", -self:_GetPadding("RIGHT"), 0)
local xOffset = iconWidth
frame.text:ClearAllPoints()
-- TODO: support non-left-aligned text
frame.text:SetPoint("TOPLEFT", self:_GetPadding("LEFT"), -self:_GetPadding("TOP"))
frame.text:SetPoint("BOTTOMRIGHT", -xOffset, self:_GetPadding("BOTTOM"))
else
error("Invalid iconPosition: "..tostring(self._iconPosition))
end
else
frame.icon:Hide()
frame.text:ClearAllPoints()
frame.text:SetPoint("TOPLEFT", self:_GetPadding("LEFT"), -self:_GetPadding("TOP"))
frame.text:SetPoint("BOTTOMRIGHT", -self:_GetPadding("RIGHT"), self:_GetPadding("BOTTOM"))
end
end
-- ============================================================================
-- Private Class Methods
-- ============================================================================
function Button._GetMinimumDimension(self, dimension)
if dimension == "WIDTH" and self._autoWidth then
return self:GetStringWidth() + (self._iconTexturePack and TSM.UI.TexturePacks.GetWidth(self._iconTexturePack) or 0)
else
return self.__super:_GetMinimumDimension(dimension)
end
end