annotate modules/ReAction_Action/ReAction_Action.lua @ 78:502cdb5666e2

Removed OnAttributeChanged handler for action buttons (which was already installed by the Blizzard frame)
author Flick <flickerstreak@gmail.com>
date Tue, 24 Jun 2008 00:10:33 +0000
parents da8ba8783924
children 3499ac7c3a9b
rev   line source
flickerstreak@24 1 --[[
flickerstreak@53 2 ReAction Action button module.
flickerstreak@24 3
flickerstreak@24 4 The button module implements standard action button functionality by wrapping Blizzard's
flickerstreak@77 5 ActionButton frame and associated functions.
flickerstreak@77 6
flickerstreak@77 7 It also provides support for multiple pages (interacting with the State module) as well
flickerstreak@77 8 as optional action remapping for possessed targets (mind control).
flickerstreak@24 9
flickerstreak@24 10 --]]
flickerstreak@24 11
flickerstreak@24 12 -- local imports
flickerstreak@24 13 local ReAction = ReAction
flickerstreak@24 14 local L = ReAction.L
flickerstreak@24 15 local _G = _G
flickerstreak@24 16 local CreateFrame = CreateFrame
flickerstreak@24 17
flickerstreak@77 18 ReAction:UpdateRevision("$Revision: 103 $")
flickerstreak@77 19
flickerstreak@24 20 -- module declaration
flickerstreak@24 21 local moduleID = "Action"
flickerstreak@28 22 local module = ReAction:NewModule( moduleID )
flickerstreak@24 23
flickerstreak@77 24 -- Button class declaration
flickerstreak@77 25 local Button = { }
flickerstreak@77 26
flickerstreak@75 27 -- private --
flickerstreak@75 28 local function RefreshLite(bar)
flickerstreak@75 29 local btns = module.buttons[bar]
flickerstreak@75 30 if btns then
flickerstreak@75 31 for _, b in ipairs(btns) do
flickerstreak@75 32 b:Refresh()
flickerstreak@75 33 end
flickerstreak@75 34 end
flickerstreak@75 35 end
flickerstreak@75 36
flickerstreak@77 37 -- Event handlers
flickerstreak@24 38 function module:OnInitialize()
flickerstreak@28 39 self.db = ReAction.db:RegisterNamespace( moduleID,
flickerstreak@24 40 {
flickerstreak@28 41 profile = {
flickerstreak@75 42 buttons = { },
flickerstreak@75 43 bars = { },
flickerstreak@28 44 }
flickerstreak@24 45 }
flickerstreak@24 46 )
flickerstreak@24 47 self.buttons = { }
flickerstreak@49 48
flickerstreak@63 49 ReAction:RegisterBarOptionGenerator(self, "GetBarOptions")
flickerstreak@63 50
flickerstreak@63 51 ReAction.RegisterCallback(self, "OnCreateBar", "OnRefreshBar")
flickerstreak@63 52 ReAction.RegisterCallback(self, "OnDestroyBar")
flickerstreak@63 53 ReAction.RegisterCallback(self, "OnRefreshBar")
flickerstreak@63 54 ReAction.RegisterCallback(self, "OnEraseBar")
flickerstreak@63 55 ReAction.RegisterCallback(self, "OnRenameBar")
flickerstreak@63 56 ReAction.RegisterCallback(self, "OnConfigModeChanged")
flickerstreak@63 57
flickerstreak@24 58 end
flickerstreak@24 59
flickerstreak@24 60 function module:OnEnable()
flickerstreak@53 61 ReAction:RegisterBarType(L["Action Bar"],
flickerstreak@53 62 {
flickerstreak@53 63 type = moduleID,
flickerstreak@53 64 defaultButtonSize = 36,
flickerstreak@53 65 defaultBarRows = 1,
flickerstreak@53 66 defaultBarCols = 12,
flickerstreak@53 67 defaultBarSpacing = 3
flickerstreak@53 68 }, true)
flickerstreak@24 69 end
flickerstreak@24 70
flickerstreak@24 71 function module:OnDisable()
flickerstreak@53 72 ReAction:UnregisterBarType(L["Action Bar"])
flickerstreak@24 73 end
flickerstreak@24 74
flickerstreak@63 75 function module:OnRefreshBar(event, bar, name)
flickerstreak@53 76 if bar.config.type == moduleID then
flickerstreak@48 77 if self.buttons[bar] == nil then
flickerstreak@48 78 self.buttons[bar] = { }
flickerstreak@48 79 end
flickerstreak@48 80 local btns = self.buttons[bar]
flickerstreak@48 81 local profile = self.db.profile
flickerstreak@63 82 if profile.buttons[name] == nil then
flickerstreak@63 83 profile.buttons[name] = {}
flickerstreak@48 84 end
flickerstreak@75 85 if profile.bars[name] == nil then
flickerstreak@75 86 profile.bars[name] = {}
flickerstreak@75 87 end
flickerstreak@63 88 local btnCfg = profile.buttons[name]
flickerstreak@75 89 local barCfg = profile.bars[name]
flickerstreak@24 90
flickerstreak@48 91 local r, c = bar:GetButtonGrid()
flickerstreak@48 92 local n = r*c
flickerstreak@48 93 for i = 1, n do
flickerstreak@48 94 if btnCfg[i] == nil then
flickerstreak@48 95 btnCfg[i] = {}
flickerstreak@48 96 end
flickerstreak@48 97 if btns[i] == nil then
flickerstreak@77 98 local b = Button:New(bar, i, btnCfg[i], barCfg)
flickerstreak@77 99 btns[i] = b
flickerstreak@77 100 bar:AddButton(i,b)
flickerstreak@48 101 end
flickerstreak@24 102 end
flickerstreak@48 103 for i = n+1, #btns do
flickerstreak@52 104 if btns[i] then
flickerstreak@75 105 bar:RemoveButton(btns[i])
flickerstreak@52 106 btns[i] = btns[i]:Destroy()
flickerstreak@52 107 if btnCfg[i] then
flickerstreak@52 108 btnCfg[i] = nil
flickerstreak@52 109 end
flickerstreak@48 110 end
flickerstreak@24 111 end
flickerstreak@75 112 RefreshLite(bar)
flickerstreak@24 113 end
flickerstreak@24 114 end
flickerstreak@24 115
flickerstreak@63 116 function module:OnDestroyBar(event, bar, name)
flickerstreak@24 117 if self.buttons[bar] then
flickerstreak@24 118 local btns = self.buttons[bar]
flickerstreak@24 119 for _,b in pairs(btns) do
flickerstreak@24 120 if b then
flickerstreak@24 121 b:Destroy()
flickerstreak@24 122 end
flickerstreak@24 123 end
flickerstreak@24 124 self.buttons[bar] = nil
flickerstreak@24 125 end
flickerstreak@24 126 end
flickerstreak@24 127
flickerstreak@63 128 function module:OnEraseBar(event, bar, name)
flickerstreak@63 129 self.db.profile.buttons[name] = nil
flickerstreak@75 130 self.db.profile.bars[name] = nil
flickerstreak@24 131 end
flickerstreak@24 132
flickerstreak@63 133 function module:OnRenameBar(event, bar, oldname, newname)
flickerstreak@48 134 local b = self.db.profile.buttons
flickerstreak@48 135 b[newname], b[oldname] = b[oldname], nil
flickerstreak@75 136
flickerstreak@75 137 b = self.db.profile.bars
flickerstreak@75 138 b[newname], b[oldname] = b[oldname], nil
flickerstreak@48 139 end
flickerstreak@48 140
flickerstreak@63 141 function module:OnConfigModeChanged(event, mode)
flickerstreak@77 142 for _, bar in pairs(self.buttons) do
flickerstreak@77 143 for _, b in pairs(bar) do
flickerstreak@77 144 b:ShowGrid(mode)
flickerstreak@77 145 b:ShowActionIDLabel(mode)
flickerstreak@24 146 end
flickerstreak@24 147 end
flickerstreak@24 148 end
flickerstreak@24 149
flickerstreak@50 150
flickerstreak@60 151 ---- Options ----
flickerstreak@77 152 local Handler = { }
flickerstreak@77 153
flickerstreak@77 154 local options = {
flickerstreak@77 155 hideEmpty = {
flickerstreak@77 156 name = L["Hide Empty Buttons"],
flickerstreak@77 157 desc = L["Hide buttons when empty. This option is not supported for multi-state bars"],
flickerstreak@77 158 order = 1,
flickerstreak@77 159 type = "toggle",
flickerstreak@77 160 get = "GetHideEmpty",
flickerstreak@77 161 set = "SetHideEmpty",
flickerstreak@77 162 },
flickerstreak@77 163 }
flickerstreak@77 164
flickerstreak@60 165 function module:GetBarOptions(bar)
flickerstreak@63 166 return {
flickerstreak@63 167 type = "group",
flickerstreak@63 168 name = L["Action Buttons"],
flickerstreak@77 169 handler = Handler:New(bar),
flickerstreak@77 170 hidden = "Hidden",
flickerstreak@77 171 args = options
flickerstreak@63 172 }
flickerstreak@59 173 end
flickerstreak@59 174
flickerstreak@77 175 -- options handler private
flickerstreak@77 176 do
flickerstreak@77 177 local function GetBarConfig( bar )
flickerstreak@77 178 return module.db.profile.bars[bar:GetName()]
flickerstreak@77 179 end
flickerstreak@77 180
flickerstreak@77 181 function Handler:New(bar)
flickerstreak@77 182 return setmetatable( { bar = bar }, { __index = Handler } )
flickerstreak@77 183 end
flickerstreak@77 184
flickerstreak@77 185 function Handler:Hidden()
flickerstreak@77 186 return self.bar.config.type ~= moduleID
flickerstreak@77 187 end
flickerstreak@77 188
flickerstreak@77 189 function Handler:SetHideEmpty(info, value)
flickerstreak@77 190 local c = GetBarConfig(self.bar)
flickerstreak@77 191 if value ~= c.hideEmpty then
flickerstreak@77 192 for b in self.bar:IterateButtons() do
flickerstreak@77 193 b:ShowGrid(not value)
flickerstreak@77 194 end
flickerstreak@77 195 c.hideEmpty = value
flickerstreak@77 196 end
flickerstreak@77 197 end
flickerstreak@77 198
flickerstreak@77 199 function Handler:GetHideEmpty()
flickerstreak@77 200 return GetBarConfig(self.bar).hideEmpty
flickerstreak@77 201 end
flickerstreak@77 202 end
flickerstreak@77 203
flickerstreak@77 204
flickerstreak@77 205 ------ Button class ------
flickerstreak@50 206
flickerstreak@24 207 -- use-count of action IDs
flickerstreak@53 208 local nActionIDs = 120
flickerstreak@24 209 local ActionIDList = setmetatable( {}, {
flickerstreak@24 210 __index = function(self, idx)
flickerstreak@24 211 if idx == nil then
flickerstreak@53 212 for i = 1, nActionIDs do
flickerstreak@24 213 if rawget(self,i) == nil then
flickerstreak@24 214 rawset(self,i,1)
flickerstreak@24 215 return i
flickerstreak@24 216 end
flickerstreak@24 217 end
flickerstreak@52 218 error("ran out of action IDs")
flickerstreak@24 219 else
flickerstreak@24 220 local c = rawget(self,idx) or 0
flickerstreak@24 221 rawset(self,idx,c+1)
flickerstreak@24 222 return idx
flickerstreak@24 223 end
flickerstreak@24 224 end,
flickerstreak@24 225 __newindex = function(self,idx,value)
flickerstreak@24 226 if value == nil then
flickerstreak@24 227 value = rawget(self,idx)
flickerstreak@24 228 if value == 1 then
flickerstreak@24 229 value = nil
flickerstreak@24 230 elseif value then
flickerstreak@24 231 value = value - 1
flickerstreak@24 232 end
flickerstreak@24 233 end
flickerstreak@24 234 rawset(self,idx,value)
flickerstreak@24 235 end
flickerstreak@24 236 })
flickerstreak@24 237
flickerstreak@77 238 function Button:New( bar, idx, config, barConfig )
flickerstreak@77 239 -- create new self
flickerstreak@77 240 self = setmetatable( { }, {__index = Button} )
flickerstreak@75 241 self.bar, self.idx, self.config, self.barConfig = bar, idx, config, barConfig
flickerstreak@24 242
flickerstreak@56 243 config.name = config.name or ("ReAction_%s_%d"):format(bar:GetName(),idx)
flickerstreak@49 244 self.name = config.name
flickerstreak@24 245 config.actionID = ActionIDList[config.actionID] -- gets a free one if none configured
flickerstreak@75 246 self.nPages = 1
flickerstreak@24 247
flickerstreak@77 248 local f = CreateFrame("CheckButton", self.name, bar:GetButtonFrame(), "ActionBarButtonTemplate")
flickerstreak@24 249
flickerstreak@24 250 f:SetAttribute("action", config.actionID)
flickerstreak@75 251 -- install mind control action support for all buttons here just for simplicity
flickerstreak@75 252 if self.idx <= 12 then
flickerstreak@75 253 f:SetAttribute("action-mc", 120 + self.idx)
flickerstreak@75 254 end
flickerstreak@49 255
flickerstreak@77 256 self.frame = f
flickerstreak@77 257 self.normalTexture = getglobal(format("%sNormalTexture",f:GetName()))
flickerstreak@49 258
flickerstreak@77 259 -- initialize the hide state
flickerstreak@77 260 self:ShowGrid(not barConfig.hideEmpty)
flickerstreak@77 261 if ReAction:GetConfigMode() then
flickerstreak@77 262 self:ShowGrid(true)
flickerstreak@49 263 end
flickerstreak@50 264
flickerstreak@77 265 -- show the ID label if applicable
flickerstreak@77 266 self:ShowActionIDLabel(ReAction:GetConfigMode())
flickerstreak@77 267
flickerstreak@77 268 self:Refresh()
flickerstreak@77 269 return self
flickerstreak@24 270 end
flickerstreak@24 271
flickerstreak@24 272 function Button:Destroy()
flickerstreak@24 273 local f = self.frame
flickerstreak@24 274 f:UnregisterAllEvents()
flickerstreak@24 275 f:Hide()
flickerstreak@24 276 f:SetParent(UIParent)
flickerstreak@24 277 f:ClearAllPoints()
flickerstreak@28 278 if self.name then
flickerstreak@28 279 _G[self.name] = nil
flickerstreak@24 280 end
flickerstreak@52 281 if self.config.actionID then
flickerstreak@52 282 ActionIDList[self.config.actionID] = nil
flickerstreak@52 283 end
flickerstreak@75 284 if self.config.pages then
flickerstreak@75 285 for _, id in ipairs(self.config.pages) do
flickerstreak@75 286 ActionIDList[id] = nil
flickerstreak@75 287 end
flickerstreak@75 288 end
flickerstreak@24 289 self.frame = nil
flickerstreak@24 290 self.config = nil
flickerstreak@24 291 self.bar = nil
flickerstreak@24 292 end
flickerstreak@24 293
flickerstreak@75 294 function Button:Refresh()
flickerstreak@75 295 local f = self.frame
flickerstreak@75 296 self.bar:PlaceButton(self, 36, 36)
flickerstreak@75 297 if self.barConfig.mckeybinds then
flickerstreak@75 298 f:SetAttribute("bindings-mc", self.barConfig.mckeybinds[self.idx])
flickerstreak@75 299 end
flickerstreak@75 300 self:RefreshPages()
flickerstreak@24 301 end
flickerstreak@24 302
flickerstreak@24 303 function Button:GetFrame()
flickerstreak@24 304 return self.frame
flickerstreak@24 305 end
flickerstreak@24 306
flickerstreak@24 307 function Button:GetName()
flickerstreak@24 308 return self.name
flickerstreak@24 309 end
flickerstreak@24 310
flickerstreak@24 311 function Button:GetActionID()
flickerstreak@75 312 return SecureButton_GetModifiedAttribute(self.frame, "action")
flickerstreak@24 313 end
flickerstreak@28 314
flickerstreak@75 315 function Button:RefreshPages()
flickerstreak@75 316 local nPages = 1 --self.bar:GetNumPages()
flickerstreak@75 317 if nPages ~= self.nPages then
flickerstreak@75 318 local f = self:GetFrame()
flickerstreak@75 319 local c = self.config.pages
flickerstreak@75 320 if nPages > 1 and not c then
flickerstreak@75 321 c = { }
flickerstreak@75 322 self.config.pages = c
flickerstreak@75 323 end
flickerstreak@75 324 for i = 1, nPages do
flickerstreak@75 325 c[i] = ActionIDList[c[i]] -- gets a free one if none configured
flickerstreak@75 326 f:SetAttribute(("action-page%d"):format(i))
flickerstreak@75 327 end
flickerstreak@75 328 for i = nPages+1, #c do
flickerstreak@75 329 ActionIDList[c[i]] = nil
flickerstreak@75 330 c[i] = nil
flickerstreak@75 331 f:SetAttribute(("action-page%d"):format(i))
flickerstreak@75 332 end
flickerstreak@75 333
flickerstreak@75 334 -- TODO:
flickerstreak@75 335 -- apply next-page, prev-page, and direct-page keybinds (via bar:SetStateKeybind abstraction)
flickerstreak@75 336 end
flickerstreak@75 337 end
flickerstreak@28 338
flickerstreak@77 339 function Button:ShowGrid( show )
flickerstreak@77 340 if not InCombatLockdown() then
flickerstreak@77 341 -- new in 2.4.1: can't call ActionButton_ShowGrid/HideGrid because they won't update the attribute
flickerstreak@77 342 local f = self.frame
flickerstreak@77 343 local count = f:GetAttribute("showgrid")
flickerstreak@77 344 if show then
flickerstreak@77 345 count = count + 1
flickerstreak@77 346 else
flickerstreak@77 347 count = count - 1
flickerstreak@28 348 end
flickerstreak@77 349 if count < 0 then
flickerstreak@77 350 count = 0
flickerstreak@77 351 end
flickerstreak@77 352 f:SetAttribute("showgrid",count)
flickerstreak@77 353
flickerstreak@77 354 if count >= 1 and not f:GetAttribute("statehidden") then
flickerstreak@77 355 self.normalTexture:SetVertexColor(1.0, 1.0, 1.0, 0.5);
flickerstreak@77 356 f:Show()
flickerstreak@77 357 elseif count < 1 and not HasAction(self:GetActionID()) then
flickerstreak@77 358 f:Hide()
flickerstreak@77 359 end
flickerstreak@28 360 end
flickerstreak@77 361 end
flickerstreak@77 362
flickerstreak@77 363 function Button:ShowActionIDLabel( show )
flickerstreak@77 364 if show then
flickerstreak@77 365 local id = self:GetActionID()
flickerstreak@77 366 if not self.actionIDLabel and id and id ~= 0 then
flickerstreak@77 367 local f = self:GetFrame()
flickerstreak@77 368 local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
flickerstreak@77 369 label:SetAllPoints()
flickerstreak@77 370 label:SetJustifyH("CENTER")
flickerstreak@77 371 label:SetShadowColor(0,0,0,1)
flickerstreak@77 372 label:SetShadowOffset(2,-2)
flickerstreak@77 373 label:SetText(tostring(id))
flickerstreak@77 374 self.actionIDLabel = label
flickerstreak@77 375 f:HookScript("OnAttributeChanged",
flickerstreak@77 376 function(frame, attr, value)
flickerstreak@77 377 if attr == "state-parent" then
flickerstreak@77 378 label:SetText(tostring(self:GetActionID()))
flickerstreak@77 379 end
flickerstreak@77 380 end)
flickerstreak@77 381 end
flickerstreak@77 382 self.actionIDLabel:Show()
flickerstreak@77 383 elseif self.actionIDLabel then
flickerstreak@77 384 self.actionIDLabel:Hide()
flickerstreak@77 385 end
flickerstreak@77 386 end
flickerstreak@77 387