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