flickerstreak@63
|
1 --[[
|
flickerstreak@63
|
2 ReAction.lua
|
flickerstreak@63
|
3
|
flickerstreak@182
|
4 The ReAction core manages several collections:
|
flickerstreak@63
|
5 - modules (via AceAddon)
|
flickerstreak@63
|
6 - bars
|
flickerstreak@63
|
7 - bar-type constructors
|
flickerstreak@63
|
8
|
flickerstreak@90
|
9 and publishes events when those collections change. It also implements a couple properties
|
flickerstreak@63
|
10 and has a couple convenience methods which drill down to particular modules.
|
flickerstreak@63
|
11
|
flickerstreak@90
|
12 Most of the "real work" of the addon happens in Bar.lua, Overlay.lua, State.lua, and the various modules.
|
flickerstreak@63
|
13
|
flickerstreak@63
|
14 Events (with handler arguments):
|
flickerstreak@63
|
15 --------------------------------
|
flickerstreak@63
|
16 "OnCreateBar" (bar, name) : after a bar object is created
|
flickerstreak@63
|
17 "OnDestroyBar" (bar, name) : before a bar object is destroyed
|
flickerstreak@63
|
18 "OnEraseBar" (bar, name) : before a bar config is removed from the profile db
|
flickerstreak@63
|
19 "OnRenameBar" (bar, oldname, newname) : after a bar is renamed
|
flickerstreak@63
|
20 "OnRefreshBar" (bar, name) : after a bar's state has been updated
|
flickerstreak@63
|
21 "OnConfigModeChanged" (mode) : after the config mode is changed
|
flickerstreak@63
|
22
|
flickerstreak@63
|
23 ReAction is also an AceAddon-3.0 and contains an AceDB-3.0, which in turn publish more events.
|
flickerstreak@63
|
24 ]]--
|
flickerstreak@185
|
25 local _, addonTable = ...
|
flickerstreak@185
|
26 local ReAction = LibStub("AceAddon-3.0"):NewAddon( "ReAction",
|
flickerstreak@33
|
27 "AceEvent-3.0"
|
flickerstreak@30
|
28 )
|
flickerstreak@185
|
29 ReAction.version = "1.0"
|
flickerstreak@175
|
30 addonTable.ReAction = ReAction
|
flickerstreak@27
|
31
|
flickerstreak@33
|
32 ------ LIBRARIES ------
|
flickerstreak@63
|
33 local callbacks = LibStub("CallbackHandler-1.0"):New(ReAction)
|
flickerstreak@184
|
34 local LKB = LibStub("LibKeyBound-1.0")
|
flickerstreak@33
|
35 local L = LibStub("AceLocale-3.0"):GetLocale("ReAction")
|
flickerstreak@33
|
36 ReAction.L = L
|
flickerstreak@184
|
37 ReAction.LKB = LKB
|
flickerstreak@182
|
38 ReAction.callbacks = callbacks
|
flickerstreak@33
|
39
|
flickerstreak@28
|
40 ------ PRIVATE ------
|
flickerstreak@116
|
41 local private = { }
|
flickerstreak@63
|
42 local bars = {}
|
flickerstreak@63
|
43 local defaultBarConfig = {}
|
flickerstreak@63
|
44
|
flickerstreak@116
|
45
|
flickerstreak@185
|
46 local SelectBar, DestroyBar, InitializeBars, TearDownBars, DeepCopy
|
flickerstreak@28
|
47 do
|
flickerstreak@28
|
48 local pcall = pcall
|
flickerstreak@28
|
49 local geterrorhandler = geterrorhandler
|
flickerstreak@63
|
50 local self = ReAction
|
flickerstreak@63
|
51 local inited = false
|
flickerstreak@28
|
52
|
flickerstreak@63
|
53 function SelectBar(x)
|
flickerstreak@28
|
54 local bar, name
|
flickerstreak@28
|
55 if type(x) == "string" then
|
flickerstreak@28
|
56 name = x
|
flickerstreak@63
|
57 bar = self:GetBar(name)
|
flickerstreak@50
|
58 else
|
flickerstreak@63
|
59 for k,v in pairs(bars) do
|
flickerstreak@50
|
60 if v == x then
|
flickerstreak@28
|
61 name = k
|
flickerstreak@50
|
62 bar = x
|
flickerstreak@28
|
63 end
|
flickerstreak@28
|
64 end
|
flickerstreak@28
|
65 end
|
flickerstreak@28
|
66 return bar, name
|
flickerstreak@28
|
67 end
|
flickerstreak@28
|
68
|
flickerstreak@63
|
69 function DestroyBar(x)
|
flickerstreak@28
|
70 local bar, name = SelectBar(x)
|
flickerstreak@63
|
71 if bar and name then
|
flickerstreak@63
|
72 bars[name] = nil
|
flickerstreak@63
|
73 callbacks:Fire("OnDestroyBar", bar, name)
|
flickerstreak@28
|
74 bar:Destroy()
|
flickerstreak@28
|
75 end
|
flickerstreak@28
|
76 end
|
flickerstreak@28
|
77
|
flickerstreak@63
|
78 function InitializeBars()
|
flickerstreak@63
|
79 if not inited then
|
flickerstreak@63
|
80 for name, config in pairs(self.db.profile.bars) do
|
flickerstreak@28
|
81 if config then
|
flickerstreak@63
|
82 self:CreateBar(name, config)
|
flickerstreak@28
|
83 end
|
flickerstreak@28
|
84 end
|
flickerstreak@101
|
85 -- re-anchor and refresh in case anchor order does not match init order
|
flickerstreak@63
|
86 for name, bar in pairs(bars) do
|
flickerstreak@63
|
87 bar:ApplyAnchor()
|
flickerstreak@101
|
88 callbacks:Fire("OnRefreshBar", bar, name)
|
flickerstreak@63
|
89 end
|
flickerstreak@63
|
90 inited = true
|
flickerstreak@28
|
91 end
|
flickerstreak@28
|
92 end
|
flickerstreak@28
|
93
|
flickerstreak@63
|
94 function TearDownBars()
|
flickerstreak@63
|
95 for name, bar in pairs(bars) do
|
flickerstreak@28
|
96 if bar then
|
flickerstreak@63
|
97 bars[name] = DestroyBar(bar)
|
flickerstreak@28
|
98 end
|
flickerstreak@28
|
99 end
|
flickerstreak@63
|
100 inited = false
|
flickerstreak@28
|
101 end
|
flickerstreak@28
|
102
|
flickerstreak@63
|
103 function DeepCopy(x)
|
flickerstreak@28
|
104 if type(x) ~= "table" then
|
flickerstreak@28
|
105 return x
|
flickerstreak@28
|
106 end
|
flickerstreak@28
|
107 local r = {}
|
flickerstreak@28
|
108 for k,v in pairs(x) do
|
flickerstreak@28
|
109 r[k] = DeepCopy(v)
|
flickerstreak@28
|
110 end
|
flickerstreak@28
|
111 return r
|
flickerstreak@28
|
112 end
|
flickerstreak@28
|
113
|
flickerstreak@28
|
114 end
|
flickerstreak@28
|
115
|
flickerstreak@28
|
116
|
flickerstreak@28
|
117 ------ HANDLERS ------
|
flickerstreak@28
|
118 function ReAction:OnInitialize()
|
flickerstreak@28
|
119 self.db = LibStub("AceDB-3.0"):New("ReAction_DB",
|
flickerstreak@28
|
120 {
|
flickerstreak@28
|
121 profile = {
|
flickerstreak@28
|
122 bars = { },
|
flickerstreak@184
|
123 defaultBar = { },
|
flickerstreak@184
|
124 closeOptionsOnEditorLaunch = true,
|
flickerstreak@185
|
125 editorCloseOnLaunch = true,
|
flickerstreak@28
|
126 }
|
flickerstreak@111
|
127 },
|
flickerstreak@182
|
128 true -- use global 'Default' (locale-specific)
|
flickerstreak@28
|
129 )
|
flickerstreak@184
|
130 LKB.RegisterCallback(self,"LIBKEYBOUND_ENABLED")
|
flickerstreak@184
|
131 LKB.RegisterCallback(self,"LIBKEYBOUND_DISABLED")
|
flickerstreak@88
|
132
|
flickerstreak@182
|
133 self:RegisterEvent("PLAYER_REGEN_DISABLED")
|
flickerstreak@63
|
134
|
flickerstreak@182
|
135 self:InitializeOptions()
|
flickerstreak@28
|
136 end
|
flickerstreak@28
|
137
|
flickerstreak@28
|
138 function ReAction:OnEnable()
|
flickerstreak@28
|
139 InitializeBars()
|
flickerstreak@28
|
140 end
|
flickerstreak@28
|
141
|
flickerstreak@28
|
142 function ReAction:OnDisable()
|
flickerstreak@28
|
143 TearDownBars()
|
flickerstreak@28
|
144 end
|
flickerstreak@28
|
145
|
flickerstreak@33
|
146 function ReAction:PLAYER_REGEN_DISABLED()
|
flickerstreak@63
|
147 if private.configMode == true then
|
flickerstreak@63
|
148 self:UserError(L["ReAction config mode disabled during combat."])
|
flickerstreak@33
|
149 self:SetConfigMode(false)
|
flickerstreak@88
|
150 self:SetKeybindMode(false)
|
flickerstreak@185
|
151 self:CloseEditor()
|
flickerstreak@33
|
152 end
|
flickerstreak@33
|
153 end
|
flickerstreak@33
|
154
|
flickerstreak@88
|
155 function ReAction:LIBKEYBOUND_ENABLED( evt )
|
flickerstreak@88
|
156 self:SetKeybindMode(true)
|
flickerstreak@88
|
157 end
|
flickerstreak@88
|
158
|
flickerstreak@88
|
159 function ReAction:LIBKEYBOUND_DISABLED( evt )
|
flickerstreak@88
|
160 return self:SetKeybindMode(false)
|
flickerstreak@88
|
161 end
|
flickerstreak@88
|
162
|
flickerstreak@33
|
163
|
flickerstreak@28
|
164
|
flickerstreak@28
|
165 ------ API ------
|
flickerstreak@77
|
166
|
flickerstreak@61
|
167 function ReAction:UserError(msg)
|
flickerstreak@61
|
168 -- any user errors should be flashed to the UIErrorsFrame
|
flickerstreak@61
|
169 UIErrorsFrame:AddMessage(msg)
|
flickerstreak@61
|
170 end
|
flickerstreak@61
|
171
|
flickerstreak@184
|
172 function ReAction:RebuildAll()
|
flickerstreak@184
|
173 TearDownBars()
|
flickerstreak@184
|
174 InitializeBars()
|
flickerstreak@184
|
175 end
|
flickerstreak@184
|
176
|
flickerstreak@184
|
177
|
flickerstreak@63
|
178 -- usage:
|
flickerstreak@91
|
179 -- (1) ReAction:CreateBar(name, [cfgTable])
|
flickerstreak@63
|
180 -- (2) ReAction:CreateBar(name, "barType", [nRows], [nCols], [btnSize], [btnSpacing])
|
flickerstreak@91
|
181 function ReAction:CreateBar(name, config, ...)
|
flickerstreak@91
|
182 local profile = self.db.profile
|
flickerstreak@91
|
183
|
flickerstreak@127
|
184 if name then
|
flickerstreak@127
|
185 if bars[name] then
|
flickerstreak@127
|
186 self:UserError(format(L["ReAction: name '%s' already in use"],name))
|
flickerstreak@127
|
187 return nil
|
flickerstreak@127
|
188 end
|
flickerstreak@127
|
189 else
|
flickerstreak@91
|
190 local prefix = L["Bar "]
|
flickerstreak@91
|
191 local i = 1
|
flickerstreak@91
|
192 repeat
|
flickerstreak@91
|
193 name = prefix..i
|
flickerstreak@91
|
194 i = i + 1
|
flickerstreak@91
|
195 until bars[name] == nil
|
flickerstreak@91
|
196 end
|
flickerstreak@91
|
197
|
flickerstreak@91
|
198 if type(config) == "string" then
|
flickerstreak@91
|
199 config = defaultBarConfig[config]
|
flickerstreak@48
|
200 if not config then
|
flickerstreak@91
|
201 error(("ReAction:CreateBar() - unknown bar type '%s'"):format(tostring(select(1,...))))
|
flickerstreak@48
|
202 end
|
flickerstreak@48
|
203 config = DeepCopy(config)
|
flickerstreak@91
|
204 config.btnRows = select(1,...) or config.btnRows or 1
|
flickerstreak@91
|
205 config.btnColumns = select(2,...) or config.btnColumns or 12
|
flickerstreak@91
|
206 config.btnWidth = select(3,...) or config.btnWidth or 36
|
flickerstreak@91
|
207 config.btnHeight = select(3,...) or config.btnHeight or 36
|
flickerstreak@91
|
208 config.spacing = select(4,...) or config.spacing or 3
|
flickerstreak@48
|
209 config.width = config.width or config.btnColumns*(config.btnWidth + config.spacing) + 1
|
flickerstreak@48
|
210 config.height = config.height or config.btnRows*(config.btnHeight + config.spacing) + 1
|
flickerstreak@81
|
211 config.anchor = config.anchor or "UIParent"
|
flickerstreak@81
|
212 config.point = config.point or "BOTTOM"
|
flickerstreak@81
|
213 config.relpoint = config.relpoint or "BOTTOM"
|
flickerstreak@48
|
214 config.y = config.y or 200
|
flickerstreak@48
|
215 config.x = config.x or 0
|
flickerstreak@48
|
216 end
|
flickerstreak@91
|
217 config = config or profile.bars[name] or DeepCopy(profile.defaultBar)
|
flickerstreak@91
|
218
|
flickerstreak@91
|
219 profile.bars[name] = config
|
flickerstreak@91
|
220 local bar = self.Bar:New( name, config ) -- ReAction.Bar defined in Bar.lua
|
flickerstreak@63
|
221 bars[name] = bar
|
flickerstreak@63
|
222 callbacks:Fire("OnCreateBar", bar, name)
|
flickerstreak@63
|
223 if private.configMode then
|
flickerstreak@33
|
224 bar:ShowControls(true)
|
flickerstreak@33
|
225 end
|
flickerstreak@33
|
226
|
flickerstreak@28
|
227 return bar
|
flickerstreak@28
|
228 end
|
flickerstreak@28
|
229
|
flickerstreak@28
|
230 function ReAction:EraseBar(x)
|
flickerstreak@28
|
231 local bar, name = SelectBar(x)
|
flickerstreak@63
|
232 if bar and name then
|
flickerstreak@63
|
233 callbacks:Fire("OnEraseBar", bar, name)
|
flickerstreak@28
|
234 DestroyBar(bar)
|
flickerstreak@28
|
235 self.db.profile.bars[name] = nil
|
flickerstreak@28
|
236 end
|
flickerstreak@28
|
237 end
|
flickerstreak@28
|
238
|
flickerstreak@28
|
239 function ReAction:GetBar(name)
|
flickerstreak@63
|
240 return bars[name]
|
flickerstreak@63
|
241 end
|
flickerstreak@63
|
242
|
flickerstreak@90
|
243 -- returns pairs of name, bar
|
flickerstreak@63
|
244 function ReAction:IterateBars()
|
flickerstreak@63
|
245 return pairs(bars)
|
flickerstreak@28
|
246 end
|
flickerstreak@28
|
247
|
flickerstreak@28
|
248 function ReAction:RenameBar(x, newname)
|
flickerstreak@28
|
249 local bar, name = SelectBar(x)
|
flickerstreak@63
|
250 if type(newname) ~= "string" then
|
flickerstreak@63
|
251 error("ReAction:RenameBar() - second argument must be a string")
|
flickerstreak@63
|
252 end
|
flickerstreak@63
|
253 if bar and name and #newname > 0 then
|
flickerstreak@127
|
254 if newname == name then
|
flickerstreak@127
|
255 return
|
flickerstreak@127
|
256 end
|
flickerstreak@63
|
257 if bars[newname] then
|
flickerstreak@127
|
258 self:UserError(format(L["ReAction: name '%s' already in use"],newname))
|
flickerstreak@47
|
259 else
|
flickerstreak@63
|
260 bars[newname], bars[name] = bars[name], nil
|
flickerstreak@47
|
261 bar:SetName(newname or "")
|
flickerstreak@47
|
262 local cfg = self.db.profile.bars
|
flickerstreak@47
|
263 cfg[newname], cfg[name] = cfg[name], nil
|
flickerstreak@63
|
264 callbacks:Fire("OnRenameBar", bar, name, newname)
|
flickerstreak@28
|
265 end
|
flickerstreak@28
|
266 end
|
flickerstreak@28
|
267 end
|
flickerstreak@28
|
268
|
flickerstreak@63
|
269 function ReAction:RefreshBar(x)
|
flickerstreak@63
|
270 local bar, name = SelectBar(x)
|
flickerstreak@63
|
271 if bar and name then
|
flickerstreak@63
|
272 callbacks:Fire("OnRefreshBar", bar, name)
|
flickerstreak@63
|
273 end
|
flickerstreak@63
|
274 end
|
flickerstreak@63
|
275
|
flickerstreak@53
|
276 function ReAction:RegisterBarType( name, config, isDefaultChoice )
|
flickerstreak@63
|
277 defaultBarConfig[name] = config
|
flickerstreak@48
|
278 if isDefaultChoice then
|
flickerstreak@81
|
279 private.defaultBarConfigChoice = name
|
flickerstreak@48
|
280 end
|
flickerstreak@185
|
281 self:RefreshEditor()
|
flickerstreak@48
|
282 end
|
flickerstreak@48
|
283
|
flickerstreak@53
|
284 function ReAction:UnregisterBarType( name )
|
flickerstreak@63
|
285 defaultBarConfig[name] = nil
|
flickerstreak@63
|
286 if private.defaultBarConfigChoice == name then
|
flickerstreak@63
|
287 private.defaultBarConfigChoice = nil
|
flickerstreak@48
|
288 end
|
flickerstreak@185
|
289 self:RefreshEditor()
|
flickerstreak@48
|
290 end
|
flickerstreak@48
|
291
|
flickerstreak@63
|
292 function ReAction:IterateBarTypes()
|
flickerstreak@63
|
293 return pairs(defaultBarConfig)
|
flickerstreak@63
|
294 end
|
flickerstreak@63
|
295
|
flickerstreak@63
|
296 function ReAction:GetBarTypeConfig(name)
|
flickerstreak@63
|
297 if name then
|
flickerstreak@63
|
298 return defaultBarConfig[name]
|
flickerstreak@63
|
299 end
|
flickerstreak@63
|
300 end
|
flickerstreak@63
|
301
|
flickerstreak@63
|
302 function ReAction:GetBarTypeOptions( fill )
|
flickerstreak@63
|
303 fill = fill or { }
|
flickerstreak@63
|
304 for k in self:IterateBarTypes() do
|
flickerstreak@63
|
305 fill[k] = k
|
flickerstreak@63
|
306 end
|
flickerstreak@63
|
307 return fill
|
flickerstreak@63
|
308 end
|
flickerstreak@63
|
309
|
flickerstreak@63
|
310 function ReAction:GetDefaultBarType()
|
flickerstreak@63
|
311 return private.defaultBarConfigChoice
|
flickerstreak@63
|
312 end
|
flickerstreak@63
|
313
|
flickerstreak@33
|
314 function ReAction:SetConfigMode( mode )
|
flickerstreak@77
|
315 if mode ~= private.configMode then
|
flickerstreak@77
|
316 private.configMode = mode
|
flickerstreak@77
|
317 callbacks:Fire("OnConfigModeChanged", mode)
|
flickerstreak@77
|
318 end
|
flickerstreak@63
|
319 end
|
flickerstreak@63
|
320
|
flickerstreak@63
|
321 function ReAction:GetConfigMode()
|
flickerstreak@63
|
322 return private.configMode
|
flickerstreak@33
|
323 end
|
flickerstreak@38
|
324
|
flickerstreak@88
|
325 function ReAction:SetKeybindMode( mode )
|
flickerstreak@88
|
326 if mode ~= private.kbMode then
|
flickerstreak@88
|
327 if mode then
|
flickerstreak@184
|
328 LKB:Activate()
|
flickerstreak@88
|
329 else
|
flickerstreak@184
|
330 LKB:Deactivate()
|
flickerstreak@88
|
331 end
|
flickerstreak@184
|
332 private.kbMode = LKB:IsShown() or false
|
flickerstreak@88
|
333 end
|
flickerstreak@88
|
334 end
|
flickerstreak@88
|
335
|
flickerstreak@88
|
336 function ReAction:GetKeybindMode( mode )
|
flickerstreak@88
|
337 return private.kbMode
|
flickerstreak@88
|
338 end
|