-- ------------------------------------------------------------------------------ -- -- 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