flickerstreak@122: --[[ flickerstreak@122: ReAction Button base class flickerstreak@122: --]] flickerstreak@122: flickerstreak@122: -- local imports flickerstreak@122: local ReAction = ReAction flickerstreak@122: local L = ReAction.L flickerstreak@122: local _G = _G flickerstreak@122: local CreateFrame = CreateFrame flickerstreak@122: local GetBindingKey = GetBindingKey flickerstreak@122: local format = string.format flickerstreak@122: flickerstreak@122: ReAction:UpdateRevision("$Revision: 154 $") flickerstreak@122: flickerstreak@122: -- libraries flickerstreak@122: local KB = LibStub("LibKeyBound-1.0") flickerstreak@122: local LBF = LibStub("LibButtonFacade",true) -- optional flickerstreak@122: flickerstreak@122: -- private flickerstreak@122: local trash = CreateFrame("Frame") flickerstreak@122: local frameList = { } flickerstreak@122: local idPools = { } flickerstreak@122: flickerstreak@122: local function kb_onEnter( frame ) flickerstreak@122: KB:Set(frame) flickerstreak@122: end flickerstreak@122: flickerstreak@122: -- Button class flickerstreak@122: local Button = { } flickerstreak@122: flickerstreak@122: ReAction.Button = Button -- export to ReAction flickerstreak@122: flickerstreak@122: function Button:New( name, config, bar, idx, inherits, buttonType ) flickerstreak@122: buttonType = buttonType or "CheckButton" flickerstreak@122: flickerstreak@122: -- create new self flickerstreak@122: self = setmetatable( flickerstreak@122: { flickerstreak@122: bar = bar, flickerstreak@122: idx = idx, flickerstreak@122: config = config, flickerstreak@122: name = name, flickerstreak@122: }, flickerstreak@122: { __index = self } ) flickerstreak@122: flickerstreak@122: -- have to recycle frames with the same name: CreateFrame() doesn't overwrite flickerstreak@122: -- existing globals. Can't set to nil in the global because it's then tainted. flickerstreak@122: -- Caller is responsible for ensuring global uniqueness of names. flickerstreak@122: local f = name and frameList[name] flickerstreak@122: if f then flickerstreak@122: f:SetParent(bar:GetFrame()) flickerstreak@122: else flickerstreak@122: f = CreateFrame(buttonType, name, bar:GetFrame(), inherits) flickerstreak@122: if name then flickerstreak@122: frameList[name] = f flickerstreak@122: end flickerstreak@122: end flickerstreak@122: flickerstreak@122: self.frame = f flickerstreak@122: flickerstreak@122: if config then flickerstreak@122: config.name = name flickerstreak@122: end flickerstreak@122: flickerstreak@122: -- install LibKeyBound handlers onto frame flickerstreak@122: function f:GetActionName() flickerstreak@122: return format("%s:%s", bar:GetName(), idx) flickerstreak@122: end flickerstreak@122: flickerstreak@122: local clickBinding = format("CLICK %s:LeftButton", name) flickerstreak@122: function f:GetHotkey() flickerstreak@122: return KB:ToShortKey(GetBindingKey(clickBinding)) flickerstreak@122: end flickerstreak@122: flickerstreak@122: return self flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:Destroy() flickerstreak@122: local f = self.frame flickerstreak@122: gridProxy:RemoveGridFrame(f) flickerstreak@122: f:Hide() flickerstreak@122: f:SetParent(trash) flickerstreak@122: f:ClearAllPoints() flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:GetFrame() flickerstreak@122: return self.frame flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:GetName() flickerstreak@122: return self.name flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:GetConfig() flickerstreak@122: return self.config flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:GetActionID() flickerstreak@122: -- derived classes should override this flickerstreak@122: return nil flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:SetActionIDPool( poolID, maxID ) flickerstreak@122: self.actionPoolID = poolID flickerstreak@122: self.actionMaxID = maxID flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:AcquireActionID( id, hint, unique ) flickerstreak@122: local poolID = self.actionPoolID flickerstreak@122: local maxID = self.actionMaxID flickerstreak@122: if not poolID or not maxID then flickerstreak@122: error("AcquireActionID: must setup pool first with SetActionIDPool") flickerstreak@122: end flickerstreak@123: local pool = idPools[poolID] flickerstreak@122: if not pool then flickerstreak@122: pool = { nWraps = 0, useCount = { } } flickerstreak@122: for i = 1, maxID do flickerstreak@122: pool.useCount[i] = 0 flickerstreak@122: end flickerstreak@123: idPools[poolID] = pool flickerstreak@122: end flickerstreak@122: local useCount = pool.useCount flickerstreak@122: if id == nil then flickerstreak@122: repeat flickerstreak@122: local nWraps = pool.nWraps flickerstreak@122: if useCount[hint] == nil or useCount[hint] == nWraps then flickerstreak@122: id = hint flickerstreak@122: else flickerstreak@122: local start = hint or 1 flickerstreak@122: for i = start, maxID do flickerstreak@122: if useCount[i] == nil or useCount[i] == nWraps then flickerstreak@122: id = i flickerstreak@122: break flickerstreak@122: end flickerstreak@122: end flickerstreak@122: if not id then flickerstreak@122: for i = 1, start do flickerstreak@122: if useCount[i] == nil or useCount[i] == nWraps then flickerstreak@122: id = i flickerstreak@122: break flickerstreak@122: end flickerstreak@122: end flickerstreak@122: end flickerstreak@122: end flickerstreak@122: if id == nil then flickerstreak@122: if unique then flickerstreak@122: return nil flickerstreak@122: end flickerstreak@122: pool.nWraps = nWraps + 1 flickerstreak@122: end flickerstreak@122: until id flickerstreak@122: end flickerstreak@122: useCount[id] = (useCount[id] or 0) + 1 flickerstreak@122: return id flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:ReleaseActionID( id ) flickerstreak@122: local poolID = self.actionPoolID flickerstreak@122: if not poolID then flickerstreak@122: error("ReleaseActionID: must setup pool first with SetActionIDPool") flickerstreak@122: end flickerstreak@123: local pool = idPools[poolID] flickerstreak@122: if pool and id and pool.useCount[id] then flickerstreak@122: pool.useCount[id] = pool.useCount[id] - 1 flickerstreak@122: pool.nWraps = min(pool.useCount[id], pool.nWraps) flickerstreak@122: end flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:Refresh() flickerstreak@122: self.bar:PlaceButton( self, self.frame:GetWidth(), self.frame:GetHeight() ) flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:SetKeybindMode( mode ) flickerstreak@122: local f = self.frame flickerstreak@122: if mode then flickerstreak@122: self.oldOnEnter = f:GetScript("OnEnter") flickerstreak@122: f:SetScript("OnEnter", kb_onEnter) flickerstreak@124: elseif self.oldOnEnter then flickerstreak@122: f:SetScript("OnEnter", self.oldOnEnter) flickerstreak@122: self.oldOnEnter = nil flickerstreak@122: end flickerstreak@122: self:UpdateKeybindModeDisplay( mode ) flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:UpdateKeybindModeDisplay( mode ) flickerstreak@122: self.border = self.border or _G[format("%sBorder",tostring(self:GetName()))] flickerstreak@122: if self.border then flickerstreak@122: if mode then flickerstreak@122: self.border:SetVertexColor(KB:GetColorKeyBoundMode()) flickerstreak@122: self.border:Show() flickerstreak@122: else flickerstreak@122: self.border:Hide() flickerstreak@122: end flickerstreak@122: end flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:UpdateHotkey( hotkey ) flickerstreak@122: hotkey = hotkey or self.hotkey flickerstreak@122: if not hotkey then flickerstreak@122: hotkey = _G[format("%sHotKey", tostring(self:GetName()))] flickerstreak@122: self.hotkey = hotkey flickerstreak@122: end flickerstreak@122: if hotkey then flickerstreak@122: local txt = self.frame:GetHotkey() flickerstreak@122: hotkey:SetText( txt ) flickerstreak@122: if txt == nil or txt == "" then flickerstreak@122: hotkey:Hide() flickerstreak@122: else flickerstreak@122: hotkey:Show() flickerstreak@122: end flickerstreak@122: end flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:GetActionIDLabel( create ) flickerstreak@122: local f = self.frame flickerstreak@122: if not f.actionIDLabel and create then flickerstreak@122: local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") flickerstreak@122: label:SetAllPoints() flickerstreak@122: label:SetJustifyH("CENTER") flickerstreak@122: label:SetShadowColor(0,0,0,1) flickerstreak@122: label:SetShadowOffset(2,-2) flickerstreak@122: f.actionIDLabel = label -- store the label with the frame for recycling flickerstreak@122: end flickerstreak@122: return f.actionIDLabel flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:UpdateActionIDLabel( show ) flickerstreak@122: local label = self:GetActionIDLabel( show ) flickerstreak@122: if label then flickerstreak@122: if show then flickerstreak@122: local id = self:GetActionID() flickerstreak@122: if id then flickerstreak@122: label:SetText(tostring(id)) flickerstreak@122: label:Show() flickerstreak@122: return flickerstreak@122: end flickerstreak@122: end flickerstreak@122: label:Hide() flickerstreak@122: end flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:SetNormalVertexColor( r, g, b, a ) flickerstreak@122: if LBF then flickerstreak@122: LBF:SetNormalVertexColor(self.frame, r, g, b, a) flickerstreak@122: else flickerstreak@122: self.frame:GetNormalTexture():SetVertexColor(r,g,b,a) flickerstreak@122: end flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:GetNormalVertexColor() flickerstreak@122: if LBF then flickerstreak@122: return LBF:GetNormalVertexColor(self.frame) flickerstreak@122: else flickerstreak@122: return self.frame:GetNormalTexture():GetVertexColor() flickerstreak@122: end flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:ShowGrid( show ) flickerstreak@122: if not InCombatLockdown() then flickerstreak@122: local f = self.frame flickerstreak@122: local count = f:GetAttribute("showgrid") flickerstreak@122: if show then flickerstreak@122: count = count + 1 flickerstreak@122: else flickerstreak@122: count = count - 1 flickerstreak@122: end flickerstreak@122: if count < 0 then flickerstreak@122: count = 0 flickerstreak@122: end flickerstreak@122: f:SetAttribute("showgrid",count) flickerstreak@122: self:UpdateShowGrid() flickerstreak@122: end flickerstreak@122: end flickerstreak@122: flickerstreak@122: function Button:UpdateShowGrid() flickerstreak@122: -- does nothing by default flickerstreak@122: end