Mercurial > wow > reaction
diff Button.lua @ 245:65f2805957a0
No real reason to store some of the code in a subdirectory.
author | Flick |
---|---|
date | Sat, 26 Mar 2011 12:35:08 -0700 |
parents | classes/Button.lua@dcdc0235d489 |
children | 46b59a9ded76 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Button.lua Sat Mar 26 12:35:08 2011 -0700 @@ -0,0 +1,359 @@ +--[[ + 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 + return nil + 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