annotate Button.lua @ 304:c63d74f26c22

Added tag 1.1 beta 12 for changeset 86f99ec6d3e5
author Flick
date Wed, 14 Nov 2012 16:46:54 -0800
parents e337b39dc491
children
rev   line source
Flick@276 1 local _, ns = ...
Flick@276 2 local ReAction = ns.ReAction
flickerstreak@122 3 local L = ReAction.L
flickerstreak@183 4 local LKB = ReAction.LKB
flickerstreak@122 5 local _G = _G
flickerstreak@122 6 local CreateFrame = CreateFrame
flickerstreak@122 7 local GetBindingKey = GetBindingKey
flickerstreak@122 8 local format = string.format
flickerstreak@122 9
flickerstreak@122 10 -- private
flickerstreak@122 11 local trash = CreateFrame("Frame")
flickerstreak@122 12 local frameList = { }
flickerstreak@122 13 local idPools = { }
flickerstreak@122 14
flickerstreak@122 15 local function kb_onEnter( frame )
flickerstreak@183 16 LKB:Set(frame)
flickerstreak@122 17 end
flickerstreak@122 18
flickerstreak@122 19 -- Button class
flickerstreak@218 20 local buttonTypeID = "Button"
flickerstreak@218 21 local Button = {
flickerstreak@218 22 defaultBarConfig = {
flickerstreak@218 23 type = buttonTypeID,
flickerstreak@218 24 btnWidth = 36,
flickerstreak@218 25 btnHeight = 36,
flickerstreak@218 26 btnRows = 1,
flickerstreak@218 27 btnColumns = 12,
flickerstreak@218 28 spacing = 3
flickerstreak@218 29 },
Flick@277 30 -- barType = L["Button Bar"], -- derived classes must declare
Flick@277 31 -- buttonTypeID = "Button" -- derived classes must declare
flickerstreak@218 32 }
flickerstreak@122 33
flickerstreak@122 34 ReAction.Button = Button -- export to ReAction
flickerstreak@122 35
Flick@277 36 function Button:New( config, bar, idx, inherits, buttonType )
flickerstreak@122 37 buttonType = buttonType or "CheckButton"
flickerstreak@122 38
Flick@277 39 local name = format("ReAction_%s_%s_%d",bar:GetName(), self.buttonTypeID, idx)
Flick@277 40
flickerstreak@122 41 -- create new self
flickerstreak@122 42 self = setmetatable(
flickerstreak@122 43 {
flickerstreak@122 44 bar = bar,
flickerstreak@122 45 idx = idx,
flickerstreak@129 46 config = config,
flickerstreak@122 47 name = name,
flickerstreak@122 48 },
flickerstreak@122 49 { __index = self } )
flickerstreak@122 50
flickerstreak@122 51 -- have to recycle frames with the same name: CreateFrame() doesn't overwrite
flickerstreak@122 52 -- existing globals. Can't set to nil in the global because it's then tainted.
flickerstreak@122 53 -- Caller is responsible for ensuring global uniqueness of names.
flickerstreak@122 54 local f = name and frameList[name]
flickerstreak@122 55 if f then
flickerstreak@122 56 f:SetParent(bar:GetFrame())
flickerstreak@122 57 else
flickerstreak@122 58 f = CreateFrame(buttonType, name, bar:GetFrame(), inherits)
flickerstreak@122 59 if name then
flickerstreak@122 60 frameList[name] = f
flickerstreak@122 61 end
flickerstreak@122 62 end
flickerstreak@122 63
flickerstreak@122 64 self.frame = f
flickerstreak@122 65
flickerstreak@131 66 local frames = { }
flickerstreak@131 67 self.frames = frames
flickerstreak@131 68 frames.icon = _G[name.."Icon"]
flickerstreak@131 69 frames.flash = _G[name.."Flash"]
flickerstreak@131 70 frames.hotkey = _G[name.."HotKey"]
flickerstreak@131 71 frames.count = _G[name.."Count"]
flickerstreak@131 72 frames.name = _G[name.."Name"]
flickerstreak@131 73 frames.border = _G[name.."Border"]
flickerstreak@131 74 frames.cooldown = _G[name.."Cooldown"]
flickerstreak@131 75 frames.normalTexture = _G[name.."NormalTexture"]
flickerstreak@131 76
flickerstreak@122 77 if config then
flickerstreak@122 78 config.name = name
flickerstreak@122 79 end
flickerstreak@122 80
flickerstreak@122 81 -- install LibKeyBound handlers onto frame
flickerstreak@122 82 function f:GetActionName()
flickerstreak@122 83 return format("%s:%s", bar:GetName(), idx)
flickerstreak@122 84 end
flickerstreak@122 85
Flick@259 86 -- mouse and clicking
Flick@259 87 -- set click handlers in subclasses
Flick@259 88 f:EnableMouse(true)
Flick@259 89 f:RegisterForClicks( bar:GetConfig().clickDown and "AnyDown" or "AnyUp" )
flickerstreak@122 90 local clickBinding = format("CLICK %s:LeftButton", name)
flickerstreak@122 91 function f:GetHotkey()
flickerstreak@183 92 return LKB:ToShortKey(GetBindingKey(clickBinding))
flickerstreak@122 93 end
flickerstreak@122 94
flickerstreak@122 95 return self
flickerstreak@122 96 end
flickerstreak@122 97
flickerstreak@122 98 function Button:Destroy()
flickerstreak@126 99 local f = self:GetFrame()
flickerstreak@132 100 f:UnregisterAllEvents()
flickerstreak@132 101 self:ReleaseActionID(self:GetActionID())
flickerstreak@126 102 if f then
flickerstreak@126 103 f:Hide()
flickerstreak@126 104 f:SetParent(trash)
flickerstreak@126 105 f:ClearAllPoints()
flickerstreak@126 106 end
flickerstreak@122 107 end
flickerstreak@122 108
flickerstreak@128 109 function Button:GetBar()
flickerstreak@128 110 return self.bar
flickerstreak@128 111 end
flickerstreak@128 112
flickerstreak@122 113 function Button:GetFrame()
flickerstreak@122 114 return self.frame
flickerstreak@122 115 end
flickerstreak@122 116
Flick@234 117 function Button:GetIndex()
Flick@234 118 return self.idx
Flick@234 119 end
Flick@234 120
flickerstreak@122 121 function Button:GetName()
flickerstreak@122 122 return self.name
flickerstreak@122 123 end
flickerstreak@122 124
flickerstreak@218 125 function Button:GetDefaultBarConfig()
flickerstreak@218 126 return self.defaultBarConfig
flickerstreak@218 127 end
flickerstreak@218 128
flickerstreak@218 129 function Button:GetBarType()
flickerstreak@218 130 return self.barType
flickerstreak@218 131 end
flickerstreak@218 132
Flick@231 133 function Button:GetButtonTypeID()
Flick@231 134 return self.buttonTypeID
Flick@231 135 end
Flick@231 136
flickerstreak@122 137 function Button:GetConfig()
flickerstreak@122 138 return self.config
flickerstreak@122 139 end
flickerstreak@122 140
flickerstreak@122 141 function Button:GetActionID()
flickerstreak@122 142 -- derived classes should override this
flickerstreak@122 143 return nil
flickerstreak@122 144 end
flickerstreak@122 145
flickerstreak@122 146 function Button:SetActionIDPool( poolID, maxID )
flickerstreak@122 147 self.actionPoolID = poolID
flickerstreak@122 148 self.actionMaxID = maxID
flickerstreak@122 149 end
flickerstreak@122 150
Flick@234 151 function Button:SetupBar( bar )
Flick@234 152 local config = bar:GetConfig()
Flick@234 153 if not config.buttons then
Flick@234 154 config.buttons = { }
Flick@234 155 end
Flick@234 156 local btnCfg = config.buttons
Flick@234 157
Flick@234 158 local r, c = bar:GetButtonGrid()
Flick@234 159 local n = r*c
Flick@235 160 local cfgN = n
Flick@234 161
Flick@234 162 local hint = nil
Flick@234 163 local i = 1
Flick@234 164 repeat
Flick@234 165 local b = bar:GetButton(i)
Flick@234 166 if b then
Flick@234 167 if i > n then
Flick@234 168 bar:RemoveButton(b)
Flick@234 169 b:Destroy()
Flick@235 170 if i > cfgN then
Flick@235 171 btnCfg[i] = nil
Flick@235 172 end
Flick@234 173 else
Flick@234 174 b:Refresh()
Flick@234 175 hint = b:GetActionID()
Flick@234 176 end
Flick@234 177 elseif i <= n then
Flick@234 178 local cfg = btnCfg[i] or { }
Flick@234 179 local success, r = pcall(self.New, self, cfg, bar, i, hint) -- note call semantics for derived class constructors
Flick@234 180 if success and r then
Flick@234 181 b = r
Flick@234 182 bar:AddButton(i,b)
Flick@234 183 btnCfg[i] = cfg
Flick@234 184 b:Refresh()
Flick@234 185 hint = b:GetActionID()
Flick@234 186 else
Flick@234 187 n = i - 1
Flick@234 188 if not success then
Flick@236 189 bar:ClipNButtons(n)
Flick@236 190 cfgN = n
Flick@279 191 if r then
Flick@279 192 geterrorhandler()(r)
Flick@279 193 end
Flick@234 194 end
Flick@234 195 end
Flick@234 196 end
Flick@234 197 i = i + 1
Flick@234 198 until b == nil
Flick@234 199 end
Flick@234 200
flickerstreak@122 201 function Button:AcquireActionID( id, hint, unique )
flickerstreak@122 202 local poolID = self.actionPoolID
flickerstreak@122 203 local maxID = self.actionMaxID
flickerstreak@122 204 if not poolID or not maxID then
flickerstreak@122 205 error("AcquireActionID: must setup pool first with SetActionIDPool")
flickerstreak@122 206 end
Flick@299 207 hint = tonumber(hint)
Flick@299 208 if hint and (hint < 1 or hint > maxID) then
Flick@299 209 hint = nil
Flick@299 210 end
flickerstreak@123 211 local pool = idPools[poolID]
flickerstreak@122 212 if not pool then
flickerstreak@122 213 pool = { nWraps = 0, useCount = { } }
flickerstreak@122 214 for i = 1, maxID do
flickerstreak@122 215 pool.useCount[i] = 0
flickerstreak@122 216 end
flickerstreak@123 217 idPools[poolID] = pool
flickerstreak@122 218 end
flickerstreak@122 219 local useCount = pool.useCount
flickerstreak@122 220 if id == nil then
flickerstreak@122 221 repeat
flickerstreak@126 222 local nWraps = pool.nWraps or 0
Flick@299 223 if hint and (useCount[hint] == 0 or useCount[hint] == nWraps) then
flickerstreak@122 224 id = hint
flickerstreak@122 225 else
flickerstreak@122 226 local start = hint or 1
flickerstreak@122 227 for i = start, maxID do
Flick@299 228 if useCount[i] == 0 or useCount[i] == nWraps then
flickerstreak@122 229 id = i
flickerstreak@122 230 break
flickerstreak@122 231 end
flickerstreak@122 232 end
flickerstreak@122 233 if not id then
flickerstreak@122 234 for i = 1, start do
Flick@299 235 if useCount[i] == 0 or useCount[i] == nWraps then
flickerstreak@122 236 id = i
flickerstreak@122 237 break
flickerstreak@122 238 end
flickerstreak@122 239 end
flickerstreak@122 240 end
flickerstreak@122 241 end
flickerstreak@122 242 if id == nil then
flickerstreak@122 243 if unique then
Flick@282 244 ReAction:UserError(L["All action IDs for bars of type '%s' are in use, cannot create any more buttons"]:format(self.barType))
Flick@279 245 error(nil) -- no error message, user has already been notified, so don't put in Lua error handler
flickerstreak@122 246 end
flickerstreak@122 247 pool.nWraps = nWraps + 1
flickerstreak@122 248 end
flickerstreak@126 249 until id ~= nil
flickerstreak@122 250 end
flickerstreak@122 251 useCount[id] = (useCount[id] or 0) + 1
flickerstreak@122 252 return id
flickerstreak@122 253 end
flickerstreak@122 254
flickerstreak@122 255 function Button:ReleaseActionID( id )
flickerstreak@122 256 local poolID = self.actionPoolID
flickerstreak@122 257 if not poolID then
flickerstreak@122 258 error("ReleaseActionID: must setup pool first with SetActionIDPool")
flickerstreak@122 259 end
flickerstreak@123 260 local pool = idPools[poolID]
flickerstreak@122 261 if pool and id and pool.useCount[id] then
flickerstreak@122 262 pool.useCount[id] = pool.useCount[id] - 1
flickerstreak@122 263 pool.nWraps = min(pool.useCount[id], pool.nWraps)
flickerstreak@122 264 end
flickerstreak@122 265 end
flickerstreak@122 266
flickerstreak@122 267 function Button:Refresh()
flickerstreak@129 268 local f = self:GetFrame()
flickerstreak@129 269 self.bar:PlaceButton( self, f:GetWidth(), f:GetHeight() )
flickerstreak@122 270 end
flickerstreak@122 271
flickerstreak@122 272 function Button:SetKeybindMode( mode )
flickerstreak@122 273 local f = self.frame
flickerstreak@122 274 if mode then
flickerstreak@122 275 self.oldOnEnter = f:GetScript("OnEnter")
flickerstreak@122 276 f:SetScript("OnEnter", kb_onEnter)
flickerstreak@124 277 elseif self.oldOnEnter then
flickerstreak@122 278 f:SetScript("OnEnter", self.oldOnEnter)
flickerstreak@122 279 self.oldOnEnter = nil
flickerstreak@122 280 end
flickerstreak@128 281 self:ShowGridTemp(mode)
flickerstreak@122 282 self:UpdateKeybindModeDisplay( mode )
flickerstreak@122 283 end
flickerstreak@122 284
flickerstreak@122 285 function Button:UpdateKeybindModeDisplay( mode )
flickerstreak@131 286 local border = self.frames.border or _G[format("%sBorder",tostring(self:GetName()))]
flickerstreak@131 287 if border then
flickerstreak@122 288 if mode then
flickerstreak@183 289 border:SetVertexColor(LKB:GetColorKeyBoundMode())
flickerstreak@131 290 border:Show()
flickerstreak@122 291 else
flickerstreak@131 292 border:Hide()
flickerstreak@122 293 end
flickerstreak@122 294 end
flickerstreak@122 295 end
flickerstreak@122 296
flickerstreak@122 297 function Button:UpdateHotkey( hotkey )
flickerstreak@131 298 hotkey = hotkey or self.frames.hotkey
flickerstreak@122 299 if not hotkey then
flickerstreak@129 300 hotkey = _G[self:GetName().."HotKey"]
flickerstreak@131 301 self.frames.hotkey = hotkey
flickerstreak@122 302 end
flickerstreak@122 303 if hotkey then
flickerstreak@122 304 local txt = self.frame:GetHotkey()
flickerstreak@122 305 hotkey:SetText( txt )
flickerstreak@122 306 if txt == nil or txt == "" then
flickerstreak@122 307 hotkey:Hide()
flickerstreak@122 308 else
flickerstreak@122 309 hotkey:Show()
flickerstreak@122 310 end
flickerstreak@122 311 end
flickerstreak@122 312 end
flickerstreak@122 313
flickerstreak@122 314 function Button:GetActionIDLabel( create )
flickerstreak@129 315 local f = self:GetFrame()
flickerstreak@122 316 if not f.actionIDLabel and create then
flickerstreak@122 317 local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
flickerstreak@122 318 label:SetAllPoints()
flickerstreak@122 319 label:SetJustifyH("CENTER")
flickerstreak@122 320 label:SetShadowColor(0,0,0,1)
flickerstreak@122 321 label:SetShadowOffset(2,-2)
flickerstreak@122 322 f.actionIDLabel = label -- store the label with the frame for recycling
flickerstreak@122 323 end
flickerstreak@122 324 return f.actionIDLabel
flickerstreak@122 325 end
flickerstreak@122 326
flickerstreak@122 327 function Button:UpdateActionIDLabel( show )
flickerstreak@122 328 local label = self:GetActionIDLabel( show )
flickerstreak@122 329 if label then
flickerstreak@122 330 if show then
flickerstreak@122 331 local id = self:GetActionID()
flickerstreak@122 332 if id then
flickerstreak@122 333 label:SetText(tostring(id))
flickerstreak@122 334 label:Show()
flickerstreak@122 335 return
flickerstreak@122 336 end
flickerstreak@122 337 end
flickerstreak@122 338 label:Hide()
flickerstreak@122 339 end
flickerstreak@122 340 end
flickerstreak@122 341
flickerstreak@122 342 function Button:SetNormalVertexColor( r, g, b, a )
flickerstreak@213 343 if ReAction.LBF then
flickerstreak@213 344 ReAction.LBF:SetNormalVertexColor(self:GetFrame(), r, g, b, a)
flickerstreak@122 345 else
flickerstreak@129 346 self:GetFrame():GetNormalTexture():SetVertexColor(r,g,b,a)
flickerstreak@122 347 end
flickerstreak@122 348 end
flickerstreak@122 349
flickerstreak@122 350 function Button:GetNormalVertexColor()
flickerstreak@213 351 if ReAction.LBF then
flickerstreak@213 352 return ReAction.LBF:GetNormalVertexColor(self:GetFrame())
flickerstreak@122 353 else
flickerstreak@129 354 return self:GetFrame():GetNormalTexture():GetVertexColor()
flickerstreak@122 355 end
flickerstreak@122 356 end
flickerstreak@122 357
flickerstreak@122 358 function Button:UpdateShowGrid()
flickerstreak@122 359 -- does nothing by default
flickerstreak@122 360 end
flickerstreak@128 361
flickerstreak@128 362 function Button:ShowGridTemp(show)
flickerstreak@128 363 -- does nothing by default
flickerstreak@128 364 end
flickerstreak@128 365
flickerstreak@128 366 function Button:ShowGrid(show)
flickerstreak@128 367 -- does nothing by default
flickerstreak@128 368 end