comparison modules/ReAction_Action/ReAction_Action.lua @ 77:da8ba8783924

- added revision updater to each code file - Changed button/bar class mechanic to metatable-based - Changed buttons to live within a sub-frame, to play nicely between show-empty-buttons and hidestates - bar frame is now available only via accessor - Changed some semantics with AddButton/PlaceButton - Cleaned up action buttons options, fixed hide-when-empty option - moved show-action-ID-label as a button method - converted drag overlay from nested-frame to :Raise() - fixed ReAction:SetConfigMode() to not call event when mode doesn't change - Fixed ordering for dynamic state tab (always last)
author Flick <flickerstreak@gmail.com>
date Mon, 23 Jun 2008 22:27:50 +0000
parents 06cd74bdc7da
children 502cdb5666e2
comparison
equal deleted inserted replaced
76:c8c8610fd864 77:da8ba8783924
1 --[[ 1 --[[
2 ReAction Action button module. 2 ReAction Action button module.
3 3
4 The button module implements standard action button functionality by wrapping Blizzard's 4 The button module implements standard action button functionality by wrapping Blizzard's
5 ActionButton frame and associated functions. It also provides some button layout 5 ActionButton frame and associated functions.
6 modification tools. 6
7 It also provides support for multiple pages (interacting with the State module) as well
8 as optional action remapping for possessed targets (mind control).
7 9
8 --]] 10 --]]
9 11
10 -- local imports 12 -- local imports
11 local ReAction = ReAction 13 local ReAction = ReAction
12 local L = ReAction.L 14 local L = ReAction.L
13 local _G = _G 15 local _G = _G
14 local CreateFrame = CreateFrame 16 local CreateFrame = CreateFrame
15 17
18 ReAction:UpdateRevision("$Revision: 103 $")
19
16 -- module declaration 20 -- module declaration
17 local moduleID = "Action" 21 local moduleID = "Action"
18 local module = ReAction:NewModule( moduleID ) 22 local module = ReAction:NewModule( moduleID )
19 23
24 -- Button class declaration
25 local Button = { }
26
20 -- private -- 27 -- private --
21 local function GetBarConfig(bar)
22 return module.db.profile.bars[bar:GetName()]
23 end
24
25 local function RefreshLite(bar) 28 local function RefreshLite(bar)
26 local btns = module.buttons[bar] 29 local btns = module.buttons[bar]
27 if btns then 30 if btns then
28 for _, b in ipairs(btns) do 31 for _, b in ipairs(btns) do
29 b:Refresh() 32 b:Refresh()
30 end 33 end
31 end 34 end
32 end 35 end
33 36
34 37 -- Event handlers
35 -- module methods
36 function module:OnInitialize() 38 function module:OnInitialize()
37 self.db = ReAction.db:RegisterNamespace( moduleID, 39 self.db = ReAction.db:RegisterNamespace( moduleID,
38 { 40 {
39 profile = { 41 profile = {
40 buttons = { }, 42 buttons = { },
42 } 44 }
43 } 45 }
44 ) 46 )
45 self.buttons = { } 47 self.buttons = { }
46 48
47 ReAction:RegisterOptions(self, {
48 [moduleID] = {
49 type = "group",
50 name = L["Action Bars"],
51 args = {
52 hideEmpty = {
53 type = "toggle",
54 name = L["Hide Empty Buttons"],
55 get = function() return self.db.profile.hideEmptyButtons end,
56 set = function(info, val) module:SetHideEmptyButtons(val) end,
57 }
58 }
59 }
60 })
61
62 ReAction:RegisterBarOptionGenerator(self, "GetBarOptions") 49 ReAction:RegisterBarOptionGenerator(self, "GetBarOptions")
63 50
64 ReAction.RegisterCallback(self, "OnCreateBar", "OnRefreshBar") 51 ReAction.RegisterCallback(self, "OnCreateBar", "OnRefreshBar")
65 ReAction.RegisterCallback(self, "OnDestroyBar") 52 ReAction.RegisterCallback(self, "OnDestroyBar")
66 ReAction.RegisterCallback(self, "OnRefreshBar") 53 ReAction.RegisterCallback(self, "OnRefreshBar")
106 for i = 1, n do 93 for i = 1, n do
107 if btnCfg[i] == nil then 94 if btnCfg[i] == nil then
108 btnCfg[i] = {} 95 btnCfg[i] = {}
109 end 96 end
110 if btns[i] == nil then 97 if btns[i] == nil then
111 local ok, b = pcall(self.BtnClass.New, self.BtnClass, bar, i, btnCfg[i], barCfg) 98 local b = Button:New(bar, i, btnCfg[i], barCfg)
112 if ok and b then 99 btns[i] = b
113 btns[i] = b 100 bar:AddButton(i,b)
114 bar:AddButton(i,b)
115 end
116 end 101 end
117 end 102 end
118 for i = n+1, #btns do 103 for i = n+1, #btns do
119 if btns[i] then 104 if btns[i] then
120 bar:RemoveButton(btns[i]) 105 bar:RemoveButton(btns[i])
151 136
152 b = self.db.profile.bars 137 b = self.db.profile.bars
153 b[newname], b[oldname] = b[oldname], nil 138 b[newname], b[oldname] = b[oldname], nil
154 end 139 end
155 140
156 function module:SetHideEmptyButtons(hide)
157 if hide ~= self.db.profile.hideEmptyButtons then
158 for _, bar in pairs(self.buttons) do
159 for _, b in pairs(bar) do
160 if hide then
161 ActionButton_HideGrid(b.frame)
162 else
163 ActionButton_ShowGrid(b.frame)
164 end
165 end
166 end
167 self.db.profile.hideEmptyButtons = hide
168 end
169 end
170
171 function module:OnConfigModeChanged(event, mode) 141 function module:OnConfigModeChanged(event, mode)
172 for _, bar in ReAction:IterateBars() do 142 for _, bar in pairs(self.buttons) do
173 if bar and self.buttons[bar] then 143 for _, b in pairs(bar) do
174 for _, b in pairs(self.buttons[bar]) do 144 b:ShowGrid(mode)
175 if b then 145 b:ShowActionIDLabel(mode)
176 if mode then 146 end
177 ActionButton_ShowGrid(b.frame)
178 self:showActionIDLabel(b)
179 else
180 ActionButton_HideGrid(b.frame)
181 self:hideActionIDLabel(b)
182 end
183 end
184 end
185 end
186 end
187 end
188
189 function module:showActionIDLabel(button)
190 if not button.actionIDLabel and button:GetActionID() then
191 local f = button:GetFrame()
192 local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
193 label:SetAllPoints()
194 label:SetJustifyH("CENTER")
195 label:SetShadowColor(0,0,0,1)
196 label:SetShadowOffset(2,-2)
197 label:SetText(tostring(button:GetActionID()))
198 button.actionIDLabel = label
199 f:HookScript("OnAttributeChanged",
200 function(frame, attr, value)
201 if attr == "state-parent" then
202 label:SetText(tostring(button:GetActionID()))
203 end
204 end)
205 end
206 button.actionIDLabel:Show()
207 end
208
209 function module:hideActionIDLabel(button)
210 if button.actionIDLabel then
211 button.actionIDLabel:Hide()
212 end 147 end
213 end 148 end
214 149
215 150
216 ---- Options ---- 151 ---- Options ----
152 local Handler = { }
153
154 local options = {
155 hideEmpty = {
156 name = L["Hide Empty Buttons"],
157 desc = L["Hide buttons when empty. This option is not supported for multi-state bars"],
158 order = 1,
159 type = "toggle",
160 get = "GetHideEmpty",
161 set = "SetHideEmpty",
162 },
163 }
164
217 function module:GetBarOptions(bar) 165 function module:GetBarOptions(bar)
218 return { 166 return {
219 type = "group", 167 type = "group",
220 name = L["Action Buttons"], 168 name = L["Action Buttons"],
221 hidden = function() return bar.config.type ~= moduleID end, 169 handler = Handler:New(bar),
222 args = { 170 hidden = "Hidden",
223 } 171 args = options
224 } 172 }
225 end 173 end
226 174
175 -- options handler private
176 do
177 local function GetBarConfig( bar )
178 return module.db.profile.bars[bar:GetName()]
179 end
180
181 function Handler:New(bar)
182 return setmetatable( { bar = bar }, { __index = Handler } )
183 end
184
185 function Handler:Hidden()
186 return self.bar.config.type ~= moduleID
187 end
188
189 function Handler:SetHideEmpty(info, value)
190 local c = GetBarConfig(self.bar)
191 if value ~= c.hideEmpty then
192 for b in self.bar:IterateButtons() do
193 b:ShowGrid(not value)
194 end
195 c.hideEmpty = value
196 end
197 end
198
199 function Handler:GetHideEmpty()
200 return GetBarConfig(self.bar).hideEmpty
201 end
202 end
203
204
205 ------ Button class ------
227 206
228 -- use-count of action IDs 207 -- use-count of action IDs
229 local nActionIDs = 120 208 local nActionIDs = 120
230 local ActionIDList = setmetatable( {}, { 209 local ActionIDList = setmetatable( {}, {
231 __index = function(self, idx) 210 __index = function(self, idx)
254 end 233 end
255 rawset(self,idx,value) 234 rawset(self,idx,value)
256 end 235 end
257 }) 236 })
258 237
259 238 function Button:New( bar, idx, config, barConfig )
260 239 -- create new self
261 240 self = setmetatable( { }, {__index = Button} )
262 ------ Button class ------
263 local Button = { }
264
265 local function Constructor( self, bar, idx, config, barConfig )
266 self.bar, self.idx, self.config, self.barConfig = bar, idx, config, barConfig 241 self.bar, self.idx, self.config, self.barConfig = bar, idx, config, barConfig
267
268 local barFrame = bar:GetFrame()
269 242
270 config.name = config.name or ("ReAction_%s_%d"):format(bar:GetName(),idx) 243 config.name = config.name or ("ReAction_%s_%d"):format(bar:GetName(),idx)
271 self.name = config.name 244 self.name = config.name
272 config.actionID = ActionIDList[config.actionID] -- gets a free one if none configured 245 config.actionID = ActionIDList[config.actionID] -- gets a free one if none configured
273 self.nPages = 1 246 self.nPages = 1
274 247
275 local f = CreateFrame("CheckButton", self.name, barFrame, "ActionBarButtonTemplate") 248 local f = CreateFrame("CheckButton", self.name, bar:GetButtonFrame(), "ActionBarButtonTemplate")
276
277 -- TODO: re-implement ActionButton event handlers that don't do secure stuff
278 249
279 -- this will probably cause taint and/or performance problems, using right now for display/debugging purposes 250 -- this will probably cause taint and/or performance problems, using right now for display/debugging purposes
280 f:SetScript("OnAttributeChanged", ActionButton_UpdateAction) 251 f:SetScript("OnAttributeChanged", ActionButton_UpdateAction)
281 252
282 f:SetAttribute("action", config.actionID) 253 f:SetAttribute("action", config.actionID)
283 -- install mind control action support for all buttons here just for simplicity 254 -- install mind control action support for all buttons here just for simplicity
284 if self.idx <= 12 then 255 if self.idx <= 12 then
285 f:SetAttribute("action-mc", 120 + self.idx) 256 f:SetAttribute("action-mc", 120 + self.idx)
286 end 257 end
287 258
288 barFrame:SetAttribute("addchild",f)
289
290 self.frame = f 259 self.frame = f
260 self.normalTexture = getglobal(format("%sNormalTexture",f:GetName()))
261
262 -- initialize the hide state
263 self:ShowGrid(not barConfig.hideEmpty)
264 if ReAction:GetConfigMode() then
265 self:ShowGrid(true)
266 end
267
268 -- show the ID label if applicable
269 self:ShowActionIDLabel(ReAction:GetConfigMode())
270
291 self:Refresh() 271 self:Refresh()
292 272 return self
293 if not module.db.profile.hideEmptyButtons then
294 ActionButton_ShowGrid(self.frame)
295 end
296
297 if ReAction.configMode then
298 ActionButton_ShowGrid(self.frame)
299 module:showActionIDLabel(self)
300 end
301 end 273 end
302 274
303 function Button:Destroy() 275 function Button:Destroy()
304 local f = self.frame 276 local f = self.frame
305 f:UnregisterAllEvents() 277 f:UnregisterAllEvents()
365 -- TODO: 337 -- TODO:
366 -- apply next-page, prev-page, and direct-page keybinds (via bar:SetStateKeybind abstraction) 338 -- apply next-page, prev-page, and direct-page keybinds (via bar:SetStateKeybind abstraction)
367 end 339 end
368 end 340 end
369 341
370 -- export as a class-factory to module 342 function Button:ShowGrid( show )
371 module.BtnClass = { 343 if not InCombatLockdown() then
372 New = function(self, ...) 344 -- new in 2.4.1: can't call ActionButton_ShowGrid/HideGrid because they won't update the attribute
373 local x = { } 345 local f = self.frame
374 for k,v in pairs(Button) do 346 local count = f:GetAttribute("showgrid")
375 x[k] = v 347 if show then
376 end 348 count = count + 1
377 Constructor(x, ...) 349 else
378 return x 350 count = count - 1
379 end 351 end
380 } 352 if count < 0 then
353 count = 0
354 end
355 f:SetAttribute("showgrid",count)
356
357 if count >= 1 and not f:GetAttribute("statehidden") then
358 self.normalTexture:SetVertexColor(1.0, 1.0, 1.0, 0.5);
359 f:Show()
360 elseif count < 1 and not HasAction(self:GetActionID()) then
361 f:Hide()
362 end
363 end
364 end
365
366 function Button:ShowActionIDLabel( show )
367 if show then
368 local id = self:GetActionID()
369 if not self.actionIDLabel and id and id ~= 0 then
370 local f = self:GetFrame()
371 local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
372 label:SetAllPoints()
373 label:SetJustifyH("CENTER")
374 label:SetShadowColor(0,0,0,1)
375 label:SetShadowOffset(2,-2)
376 label:SetText(tostring(id))
377 self.actionIDLabel = label
378 f:HookScript("OnAttributeChanged",
379 function(frame, attr, value)
380 if attr == "state-parent" then
381 label:SetText(tostring(self:GetActionID()))
382 end
383 end)
384 end
385 self.actionIDLabel:Show()
386 elseif self.actionIDLabel then
387 self.actionIDLabel:Hide()
388 end
389 end
390