flickerstreak@7: -- The ReAction.ActionDisplay mixin defines 'regular' action button display functionality flickerstreak@7: -- and is an implementation of the ReAction.IDisplay and ReAction.ActionType.IDisplay interfaces. flickerstreak@7: -- flickerstreak@7: -- This Mixin assumes that it has been mixed in with a ReAction-derived class which implements flickerstreak@7: -- the ReAction.IActionType and ReAction.IColorScheme interfaces. flickerstreak@7: -- flickerstreak@7: -- This mixin uses properties of self.config to define display elements: flickerstreak@7: -- flickerstreak@7: -- self.config = { flickerstreak@8: -- keyBindLoc = "POSITION", -- keybind anchor location flickerstreak@8: -- stackCountLoc = "POSITION", -- stack count anchor location flickerstreak@8: -- showKeyBind = true/false, -- show keybind labels flickerstreak@8: -- showStackCount = true/false, -- show stack count labels flickerstreak@8: -- showMacroText = true/false, -- show macro name labels flickerstreak@8: -- showGrid = true/false, -- always show empty buttons flickerstreak@8: -- hideCooldown = true/false, -- hide the cooldown timer flickerstreak@8: -- hideGlobalCooldown = true/false, -- hide cooldown timers if duration < 1.5 seconds (global) flickerstreak@8: -- opacity = { flickerstreak@8: -- default = 0-100 [100], -- button opacity when the action is usable (default opacity) flickerstreak@8: -- notUsable = 0-100 [100], -- button opacity when the action is not usable flickerstreak@8: -- oom = 0-100 [notUsable], -- button opacity when the action is not usable due to OOM flickerstreak@8: -- ooRange = 0-100 [notUsable], -- button opacity when the action is not usable due to out of range flickerstreak@8: -- empty = 0-100 [0], -- button opacity when the action slot is empty flickerstreak@8: -- }, flickerstreak@8: -- hideEmptySlots = true/false, -- show/hide empty buttons rather than change opacity to 0 flickerstreak@7: -- } flickerstreak@7: -- flickerstreak@7: flickerstreak@7: local AceOO = AceLibrary("AceOO-2.0") flickerstreak@7: flickerstreak@7: ReAction.ActionDisplay = AceOO.Mixin { flickerstreak@7: -- ReAction.IDisplay interface flickerstreak@7: "SetupDisplay", flickerstreak@7: "UpdateDisplay", flickerstreak@7: "TempShow", flickerstreak@7: "GetActionFrame", flickerstreak@7: "GetBaseButtonSize", flickerstreak@7: "DisplayID", flickerstreak@7: "DisplayHotkey", flickerstreak@7: flickerstreak@7: -- ReAction.ActionType.IDisplay interface flickerstreak@7: "DisplayUsable", flickerstreak@7: "DisplayEquipped", flickerstreak@7: "DisplayAutoRepeat", flickerstreak@7: "DisplayInUse", flickerstreak@7: "DisplayIcon", flickerstreak@7: "DisplayName", flickerstreak@7: "DisplayCount", flickerstreak@7: "DisplayCooldown", flickerstreak@7: flickerstreak@7: -- Event handlers flickerstreak@7: "PostClick", flickerstreak@7: "OnDragStart", flickerstreak@7: "OnReceiveDrag", flickerstreak@7: "OnEnter", flickerstreak@7: "OnLeave", flickerstreak@7: "OnUpdate", flickerstreak@7: flickerstreak@7: -- internal functions flickerstreak@7: "ApplyLayout", flickerstreak@7: "ApplyStyle", flickerstreak@7: "StartFlash", flickerstreak@7: "StopFlash", flickerstreak@7: "IsFlashing", flickerstreak@7: "DisplayVisibility", flickerstreak@7: } flickerstreak@7: flickerstreak@7: local RAAD = ReAction.ActionDisplay flickerstreak@7: flickerstreak@7: flickerstreak@7: -- private constants flickerstreak@7: local _G = getfenv(0) flickerstreak@7: flickerstreak@7: local equippedActionBorderColor = { r=0.00, g=1.00, b=0.00, a=0.35 } -- transparent green flickerstreak@7: local actionIDColor = { r=1.00, g=0.82, b=0.00, a=1.00 } -- gold flickerstreak@7: flickerstreak@7: -- private functions flickerstreak@7: -- extract and return color fields from a table, to be fed into SetVertexColor()/SetTextColor() flickerstreak@7: local function tcolor(c) flickerstreak@7: return c.r, c.g, c.b, c.a flickerstreak@7: end flickerstreak@7: flickerstreak@7: flickerstreak@7: ----------------------------------- flickerstreak@7: -- Interface Implementation Methods flickerstreak@7: ----------------------------------- flickerstreak@7: function RAAD:SetupDisplay( name ) flickerstreak@7: -- create the button widget flickerstreak@7: local b = CreateFrame("CheckButton", name, nil, "SecureActionButtonTemplate, ActionButtonTemplate") flickerstreak@7: flickerstreak@7: -- store references to the various sub-frames of ActionButtonTemplate so we don't have to look it up all the time flickerstreak@7: self.frames = { flickerstreak@7: button = b, flickerstreak@7: hotkey = _G[name.."HotKey"], flickerstreak@7: count = _G[name.."Count"], flickerstreak@7: cooldown = _G[name.."Cooldown"], flickerstreak@7: macro = _G[name.."Name"], flickerstreak@7: icon = _G[name.."Icon"], flickerstreak@7: border = _G[name.."Border"], flickerstreak@7: flash = _G[name.."Flash"], flickerstreak@7: normalTexture = _G[name.."NormalTexture"], flickerstreak@7: actionID = nil, -- defer creating actionID font string until it's actually requested flickerstreak@7: } flickerstreak@7: flickerstreak@7: -- ??? odd: why do we have to increment the cooldown frame level to get it to show? flickerstreak@7: -- (otherwise it's behind the icon). The default UI doesn't have to (or at least I can't flickerstreak@7: -- find where it does) but for some reason we have to here. flickerstreak@7: self.frames.cooldown:SetFrameLevel(self.frames.cooldown:GetFrameLevel() + 1) flickerstreak@7: flickerstreak@7: b:EnableMouse() flickerstreak@7: b:RegisterForDrag("LeftButton", "RightButton") flickerstreak@7: b:RegisterForClicks("AnyUp") flickerstreak@7: b:SetScript("PostClick", function(arg1) self:PostClick(arg1) end) flickerstreak@7: b:SetScript("OnDragStart", function(arg1) self:OnDragStart(arg1) end) flickerstreak@7: b:SetScript("OnReceiveDrag", function() self:OnReceiveDrag() end) flickerstreak@7: b:SetScript("OnEnter", function() self:OnEnter() end) flickerstreak@7: b:SetScript("OnLeave", function() self:OnLeave() end) flickerstreak@7: -- defer setting OnUpdate until actions are actually attached flickerstreak@7: flickerstreak@7: self.tmpShow_ = 0 flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:UpdateDisplay() flickerstreak@7: self:ApplyLayout() flickerstreak@7: self:ApplyStyle() flickerstreak@7: self:DisplayVisibility() flickerstreak@7: -- refresh the action ID display flickerstreak@7: if ReAction.showIDs_ then flickerstreak@8: self:DisplayID(true) flickerstreak@7: end flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:TempShow( visible ) flickerstreak@7: visible = visible and true or false -- force data integrity flickerstreak@7: self.showTmp_ = max(0, (self.showTmp_ or 0) + (visible and 1 or -1)) flickerstreak@7: self:DisplayVisibility() flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:GetActionFrame() flickerstreak@7: return self.frames.button flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:GetBaseButtonSize() flickerstreak@7: return 36 flickerstreak@7: end flickerstreak@7: flickerstreak@8: function RAAD:DisplayID( show ) flickerstreak@7: local f = self.frames.actionID flickerstreak@8: if show then flickerstreak@7: if not f then flickerstreak@7: -- create the actionID label flickerstreak@7: f = self.frames.button:CreateFontString(nil,"ARTWORK","NumberFontNormalSmall") flickerstreak@7: f:SetPoint("BOTTOMLEFT") flickerstreak@7: f:SetTextColor( tcolor(actionIDColor) ) flickerstreak@7: self.frames.actionID = f flickerstreak@7: end flickerstreak@8: f:SetText(tostring(self:GetID())) flickerstreak@7: f:Show() flickerstreak@7: elseif f then flickerstreak@7: f:Hide() flickerstreak@7: end flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:DisplayHotkey(txt) flickerstreak@7: self.frames.hotkey:SetText(string.upper(txt or "")) flickerstreak@7: self:UpdateUsable() flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:DisplayUsable( isUsable, notEnoughMana, outOfRange ) flickerstreak@7: local f = self.frames flickerstreak@7: f.icon:SetVertexColor( self:GetIconColor(isUsable, notEnoughMana, outOfRange) ) flickerstreak@7: f.button:GetNormalTexture():SetVertexColor( self:GetBorderColor(isUsable, notEnoughMana, outOfRange) ) flickerstreak@7: f.hotkey:SetTextColor( self:GetHotkeyColor(isUsable, notEnoughMana, outOfRange, f.hotkey:GetText()) ) flickerstreak@8: flickerstreak@8: local o flickerstreak@8: if isUsable then flickerstreak@8: o = self.config.opacity and self.config.opacity.usable or 1 flickerstreak@8: else flickerstreak@8: o = self.config.opacity and self.config.opacity.notUsable or 1 flickerstreak@8: if notEnoughMana then flickerstreak@8: o = self.config.opacity and self.config.opacity.oom or o flickerstreak@8: elseif outOfRange then flickerstreak@8: o = self.config.opacity and self.config.opacity.ooRange or o flickerstreak@8: end flickerstreak@8: end flickerstreak@8: flickerstreak@8: self.currentOpacity = o -- store for use in DisplayVisibility flickerstreak@8: self:DisplayVisibility() flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:DisplayEquipped( equipped ) flickerstreak@7: local b = self.frames.border flickerstreak@7: if equipped then flickerstreak@7: b:Show() flickerstreak@7: else flickerstreak@7: b:Hide() flickerstreak@7: end flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:DisplayAutoRepeat( r ) flickerstreak@7: if r then flickerstreak@7: self:StartFlash() flickerstreak@7: else flickerstreak@7: self:StopFlash() flickerstreak@7: end flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:DisplayInUse( inUse ) flickerstreak@7: self.frames.button:SetChecked( inUse and 1 or 0 ) flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:DisplayIcon( texture ) flickerstreak@7: local f = self.frames.button flickerstreak@7: local icon = self.frames.icon flickerstreak@7: if texture then flickerstreak@7: icon:SetTexture(texture) flickerstreak@7: icon:Show() flickerstreak@7: self.rangeTimer = -1 flickerstreak@7: f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2") flickerstreak@7: if f:GetScript("OnUpdate") == nil then flickerstreak@7: f:SetScript("OnUpdate", function(frame, elapsed) self:OnUpdate(elapsed) end) flickerstreak@7: end flickerstreak@7: else flickerstreak@7: icon:Hide() flickerstreak@7: self.rangeTimer = nil flickerstreak@7: f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot") flickerstreak@7: f:SetScript("OnUpdate",nil) flickerstreak@7: end flickerstreak@7: self:DisplayVisibility() flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:DisplayCooldown( start, duration, enable ) flickerstreak@8: enable = enable and not self.config.hideCooldown and (not self.config.hideGlobalCooldown or duration > 1.5) flickerstreak@7: CooldownFrame_SetTimer(self.frames.cooldown, start, duration, enable) flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:DisplayName( name ) flickerstreak@7: self.frames.macro:SetText(name and tostring(name) or "") flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:DisplayCount( count ) flickerstreak@7: self.frames.count:SetText(count and tostring(count) or "") flickerstreak@7: end flickerstreak@7: flickerstreak@7: flickerstreak@7: flickerstreak@7: flickerstreak@7: flickerstreak@7: ---------------------- flickerstreak@7: -- Event Handlers flickerstreak@7: ---------------------- flickerstreak@7: function RAAD:PostClick() flickerstreak@7: self:UpdateInUse() flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:OnDragStart() flickerstreak@7: if LOCK_ACTIONBAR ~= "1" or IsShiftKeyDown() then flickerstreak@7: self:PickupAction() flickerstreak@7: end flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:OnReceiveDrag() flickerstreak@7: self:PlaceAction() flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:OnEnter() flickerstreak@7: self:SetTooltip() -- from ReAction base class flickerstreak@7: self.tooltipTime = TOOLTIP_UPDATE_TIME flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:OnLeave() flickerstreak@7: self:ClearTooltip() -- from ReAction base class flickerstreak@7: self.tooltipTime = nil flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:OnUpdate(elapsed) flickerstreak@7: -- handle flashing flickerstreak@7: if self:IsFlashing() then flickerstreak@7: self.flashtime = self.flashtime - elapsed flickerstreak@7: if self.flashtime <= 0 then flickerstreak@7: local overtime = -self.flashtime flickerstreak@7: if overtime >= ATTACK_BUTTON_FLASH_TIME then flickerstreak@7: overtime = 0 flickerstreak@7: end flickerstreak@7: self.flashtime = ATTACK_BUTTON_FLASH_TIME - overtime flickerstreak@7: flickerstreak@7: local f = self.frames.flash flickerstreak@7: if f then flickerstreak@7: if f:IsVisible() then flickerstreak@7: f:Hide() flickerstreak@7: else flickerstreak@7: f:Show() flickerstreak@7: end flickerstreak@7: end flickerstreak@7: end flickerstreak@7: end flickerstreak@7: flickerstreak@7: -- Handle range indicator flickerstreak@7: if self.rangeTimer then flickerstreak@7: self.rangeTimer = self.rangeTimer - elapsed flickerstreak@7: if self.rangeTimer <= 0 then flickerstreak@7: self:UpdateUsable() flickerstreak@7: self.rangeTimer = TOOLTIP_UPDATE_TIME flickerstreak@7: end flickerstreak@7: end flickerstreak@7: flickerstreak@7: -- handle tooltip update flickerstreak@7: if self.tooltipTime then flickerstreak@7: self.tooltipTime = self.tooltipTime - elapsed flickerstreak@7: if self.tooltipTime <= 0 then flickerstreak@7: if GameTooltip:IsOwned(self.frames.button) then flickerstreak@7: self:UpdateTooltip() flickerstreak@7: self.tooltipTime = TOOLTIP_UPDATE_TIME flickerstreak@7: else flickerstreak@7: self.tooltipTime = nil flickerstreak@7: end flickerstreak@7: end flickerstreak@7: end flickerstreak@7: end flickerstreak@7: flickerstreak@7: flickerstreak@7: flickerstreak@7: ---------------------- flickerstreak@7: -- Internal methods flickerstreak@7: ---------------------- flickerstreak@7: flickerstreak@7: local function placeLabel( label, anchor ) flickerstreak@7: local top = string.match(anchor,"TOP") flickerstreak@7: local bottom = string.match(anchor, "BOTTOM") flickerstreak@7: label:ClearAllPoints() flickerstreak@7: label:SetWidth(40) flickerstreak@7: label:SetPoint(top or bottom or "CENTER",0,top and 2 or bottom and -2 or 0) flickerstreak@7: local j flickerstreak@7: if string.match(anchor,"LEFT") then flickerstreak@7: j = "LEFT" flickerstreak@7: elseif string.match(anchor,"RIGHT") then flickerstreak@7: j = "RIGHT" flickerstreak@7: else flickerstreak@7: j = "CENTER" flickerstreak@7: end flickerstreak@7: label:SetJustifyH(j) flickerstreak@7: end flickerstreak@7: flickerstreak@7: flickerstreak@7: function RAAD:ApplyLayout() flickerstreak@7: local f = self.frames flickerstreak@7: flickerstreak@7: if self.config.keyBindLoc then flickerstreak@7: placeLabel(f.hotkey, self.config.keyBindLoc) flickerstreak@7: end flickerstreak@7: flickerstreak@7: if self.config.stackCountLoc then flickerstreak@7: placeLabel(f.count, self.config.stackCountLoc) flickerstreak@7: end flickerstreak@7: flickerstreak@7: if self.config.showKeyBind then flickerstreak@7: f.hotkey:Show() flickerstreak@7: else flickerstreak@7: f.hotkey:Hide() flickerstreak@7: end flickerstreak@7: flickerstreak@7: if self.config.showStackCount then flickerstreak@7: f.count:Show() flickerstreak@7: else flickerstreak@7: f.count:Hide() flickerstreak@7: end flickerstreak@7: flickerstreak@7: if self.config.showMacroName then flickerstreak@7: f.macro:Show() flickerstreak@7: else flickerstreak@7: f.macro:Hide() flickerstreak@7: end flickerstreak@7: flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:ApplyStyle() flickerstreak@7: local f = self.frames flickerstreak@7: -- for now, just a static style flickerstreak@7: f.hotkey:SetFontObject(NumberFontNormal) flickerstreak@7: f.count:SetFontObject(NumberFontNormalYellow) flickerstreak@7: f.border:SetVertexColor( tcolor(equippedActionBorderColor) ) flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:StartFlash() flickerstreak@7: self.flashing = true flickerstreak@7: self.flashtime = 0 flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:StopFlash() flickerstreak@7: self.flashing = false flickerstreak@7: self.frames.flash:Hide() flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:IsFlashing() flickerstreak@7: return self.flashing flickerstreak@7: end flickerstreak@7: flickerstreak@7: function RAAD:DisplayVisibility() flickerstreak@7: local b = self.frames.button flickerstreak@7: flickerstreak@7: if b:GetAttribute("statehidden") then flickerstreak@7: -- can't hide/show in combat flickerstreak@7: if not InCombatLockdown() then flickerstreak@7: b:Hide() flickerstreak@7: end flickerstreak@8: elseif self.showTmp_ and self.showTmp_ > 0 then flickerstreak@8: b:GetNormalTexture():SetAlpha(0.5) flickerstreak@8: if self:IsActionEmpty() then flickerstreak@8: self.frames.cooldown:Hide() flickerstreak@8: if not InCombatLockdown() and not b:IsShown() then flickerstreak@8: b:Show() flickerstreak@8: end flickerstreak@8: end flickerstreak@8: b:SetAlpha(1) flickerstreak@7: elseif not self:IsActionEmpty() then flickerstreak@7: b:GetNormalTexture():SetAlpha(1.0) flickerstreak@8: b:SetAlpha(self.currentOpacity or (self.config.opacity and self.config.opacity.usable) or 1) flickerstreak@7: else flickerstreak@8: if self.config.hideEmptySlots then flickerstreak@8: if not InCombatLockdown() then flickerstreak@8: b:Hide() flickerstreak@8: end flickerstreak@8: else flickerstreak@8: b:SetAlpha(self.config.opacity and self.config.opacity.empty or 0) flickerstreak@8: end flickerstreak@7: end flickerstreak@7: end flickerstreak@7: