Mercurial > wow > reaction
view Button.lua @ 250:d7a7ef367faf
Fix Lua error when opening global config from editor
author | Flick |
---|---|
date | Mon, 28 Mar 2011 16:23:21 -0700 |
parents | 46b59a9ded76 |
children | c918ff9ac787 |
line wrap: on
line source
--[[ ReAction Button base class --]] -- local imports local addonName, addonTable = ... local ReAction = addonTable.ReAction local L = ReAction.L local LKB = ReAction.LKB local _G = _G local CreateFrame = CreateFrame local GetBindingKey = GetBindingKey local format = string.format -- private local trash = CreateFrame("Frame") local frameList = { } local idPools = { } local function kb_onEnter( frame ) LKB:Set(frame) end -- Button class local buttonTypeID = "Button" local Button = { defaultBarConfig = { type = buttonTypeID, btnWidth = 36, btnHeight = 36, btnRows = 1, btnColumns = 12, spacing = 3 }, barType = L["Button Bar"] } ReAction.Button = Button -- export to ReAction function Button:New( name, config, bar, idx, inherits, buttonType ) buttonType = buttonType or "CheckButton" -- create new self self = setmetatable( { bar = bar, idx = idx, config = config, name = name, }, { __index = self } ) -- have to recycle frames with the same name: CreateFrame() doesn't overwrite -- existing globals. Can't set to nil in the global because it's then tainted. -- Caller is responsible for ensuring global uniqueness of names. local f = name and frameList[name] if f then f:SetParent(bar:GetFrame()) else f = CreateFrame(buttonType, name, bar:GetFrame(), inherits) if name then frameList[name] = f end end self.frame = f local frames = { } self.frames = frames frames.icon = _G[name.."Icon"] frames.flash = _G[name.."Flash"] frames.hotkey = _G[name.."HotKey"] frames.count = _G[name.."Count"] frames.name = _G[name.."Name"] frames.border = _G[name.."Border"] frames.cooldown = _G[name.."Cooldown"] frames.normalTexture = _G[name.."NormalTexture"] if config then config.name = name end -- install LibKeyBound handlers onto frame function f:GetActionName() return format("%s:%s", bar:GetName(), idx) end local clickBinding = format("CLICK %s:LeftButton", name) function f:GetHotkey() return LKB:ToShortKey(GetBindingKey(clickBinding)) end return self end function Button:Destroy() local f = self:GetFrame() f:UnregisterAllEvents() self:ReleaseActionID(self:GetActionID()) if f then f:Hide() f:SetParent(trash) f:ClearAllPoints() end end function Button:GetBar() return self.bar end function Button:GetFrame() return self.frame end function Button:GetIndex() return self.idx end function Button:GetName() return self.name end function Button:GetDefaultBarConfig() return self.defaultBarConfig end function Button:GetBarType() return self.barType end function Button:GetButtonTypeID() return self.buttonTypeID end function Button:GetConfig() return self.config end function Button:GetActionID() -- derived classes should override this return nil end function Button:SetActionIDPool( poolID, maxID ) self.actionPoolID = poolID self.actionMaxID = maxID end function Button:SetupBar( bar ) local config = bar:GetConfig() if not config.buttons then config.buttons = { } end local btnCfg = config.buttons local r, c = bar:GetButtonGrid() local n = r*c local cfgN = n local hint = nil local i = 1 repeat local b = bar:GetButton(i) if b then if i > n then bar:RemoveButton(b) b:Destroy() if i > cfgN then btnCfg[i] = nil end else b:Refresh() hint = b:GetActionID() end elseif i <= n then local cfg = btnCfg[i] or { } local success, r = pcall(self.New, self, cfg, bar, i, hint) -- note call semantics for derived class constructors if success and r then b = r bar:AddButton(i,b) btnCfg[i] = cfg b:Refresh() hint = b:GetActionID() else n = i - 1 if not success then bar:ClipNButtons(n) cfgN = n geterrorhandler()(r) end end end i = i + 1 until b == nil end function Button:AcquireActionID( id, hint, unique ) local poolID = self.actionPoolID local maxID = self.actionMaxID if not poolID or not maxID then error("AcquireActionID: must setup pool first with SetActionIDPool") end local pool = idPools[poolID] if not pool then pool = { nWraps = 0, useCount = { } } for i = 1, maxID do pool.useCount[i] = 0 end idPools[poolID] = pool end local useCount = pool.useCount if id == nil then repeat local nWraps = pool.nWraps or 0 if hint and (useCount[hint] == nil or useCount[hint] == nWraps) then id = hint else local start = hint or 1 for i = start, maxID do if useCount[i] == nil or useCount[i] == nWraps then id = i break end end if not id then for i = 1, start do if useCount[i] == nil or useCount[i] == nWraps then id = i break end end end end if id == nil then if unique then error(("All action IDs for bars of type '%s' are in use, cannot create any more buttons"):format(self.config.barType)) end pool.nWraps = nWraps + 1 end until id ~= nil end useCount[id] = (useCount[id] or 0) + 1 return id end function Button:ReleaseActionID( id ) local poolID = self.actionPoolID if not poolID then error("ReleaseActionID: must setup pool first with SetActionIDPool") end local pool = idPools[poolID] if pool and id and pool.useCount[id] then pool.useCount[id] = pool.useCount[id] - 1 pool.nWraps = min(pool.useCount[id], pool.nWraps) end end function Button:Refresh() local f = self:GetFrame() self.bar:PlaceButton( self, f:GetWidth(), f:GetHeight() ) end function Button:SetKeybindMode( mode ) local f = self.frame if mode then self.oldOnEnter = f:GetScript("OnEnter") f:SetScript("OnEnter", kb_onEnter) elseif self.oldOnEnter then f:SetScript("OnEnter", self.oldOnEnter) self.oldOnEnter = nil end self:ShowGridTemp(mode) self:UpdateKeybindModeDisplay( mode ) end function Button:UpdateKeybindModeDisplay( mode ) local border = self.frames.border or _G[format("%sBorder",tostring(self:GetName()))] if border then if mode then border:SetVertexColor(LKB:GetColorKeyBoundMode()) border:Show() else border:Hide() end end end function Button:UpdateHotkey( hotkey ) hotkey = hotkey or self.frames.hotkey if not hotkey then hotkey = _G[self:GetName().."HotKey"] self.frames.hotkey = hotkey end if hotkey then local txt = self.frame:GetHotkey() hotkey:SetText( txt ) if txt == nil or txt == "" then hotkey:Hide() else hotkey:Show() end end end function Button:GetActionIDLabel( create ) local f = self:GetFrame() if not f.actionIDLabel and create then local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") label:SetAllPoints() label:SetJustifyH("CENTER") label:SetShadowColor(0,0,0,1) label:SetShadowOffset(2,-2) f.actionIDLabel = label -- store the label with the frame for recycling end return f.actionIDLabel end function Button:UpdateActionIDLabel( show ) local label = self:GetActionIDLabel( show ) if label then if show then local id = self:GetActionID() if id then label:SetText(tostring(id)) label:Show() return end end label:Hide() end end function Button:SetNormalVertexColor( r, g, b, a ) if ReAction.LBF then ReAction.LBF:SetNormalVertexColor(self:GetFrame(), r, g, b, a) else self:GetFrame():GetNormalTexture():SetVertexColor(r,g,b,a) end end function Button:GetNormalVertexColor() if ReAction.LBF then return ReAction.LBF:GetNormalVertexColor(self:GetFrame()) else return self:GetFrame():GetNormalTexture():GetVertexColor() end end function Button:UpdateShowGrid() -- does nothing by default end function Button:ShowGridTemp(show) -- does nothing by default end function Button:ShowGrid(show) -- does nothing by default end