flickerstreak@25
|
1 --[[
|
flickerstreak@62
|
2 ReAction bar state driver interface
|
flickerstreak@25
|
3
|
flickerstreak@25
|
4 --]]
|
flickerstreak@25
|
5
|
flickerstreak@25
|
6 -- local imports
|
flickerstreak@25
|
7 local ReAction = ReAction
|
flickerstreak@25
|
8 local L = ReAction.L
|
flickerstreak@25
|
9 local _G = _G
|
flickerstreak@25
|
10 local InCombatLockdown = InCombatLockdown
|
flickerstreak@25
|
11
|
flickerstreak@25
|
12 -- module declaration
|
flickerstreak@25
|
13 local moduleID = "State"
|
flickerstreak@25
|
14 local module = ReAction:NewModule( moduleID )
|
flickerstreak@25
|
15
|
flickerstreak@62
|
16
|
flickerstreak@62
|
17 -- module event handlers
|
flickerstreak@25
|
18 function module:OnInitialize()
|
flickerstreak@62
|
19 self.db = ReAction.db:RegisterNamespace( moduleID,
|
flickerstreak@25
|
20 {
|
flickerstreak@62
|
21 profile = {
|
flickerstreak@62
|
22 bars = { },
|
flickerstreak@62
|
23 presets = { }
|
flickerstreak@62
|
24 }
|
flickerstreak@25
|
25 }
|
flickerstreak@25
|
26 )
|
flickerstreak@62
|
27 self.states = { }
|
flickerstreak@62
|
28 self.options = setmetatable({},{__mode="k"})
|
flickerstreak@25
|
29 end
|
flickerstreak@25
|
30
|
flickerstreak@62
|
31
|
flickerstreak@62
|
32
|
flickerstreak@62
|
33 -- ReAction module interface
|
flickerstreak@62
|
34 function module:ApplyToBar(bar)
|
flickerstreak@62
|
35 self:RefreshBar(bar)
|
flickerstreak@62
|
36 end
|
flickerstreak@62
|
37
|
flickerstreak@62
|
38 function module:RefreshBar(bar)
|
flickerstreak@62
|
39 local c = self.db.profile.bars[bar:GetName()]
|
flickerstreak@62
|
40 if c then
|
flickerstreak@62
|
41 --self:BuildStates(bar)
|
flickerstreak@62
|
42 --self:BuildRules(bar)
|
flickerstreak@62
|
43 end
|
flickerstreak@62
|
44 end
|
flickerstreak@62
|
45
|
flickerstreak@62
|
46 function module:RemoveFromBar(bar)
|
flickerstreak@62
|
47 end
|
flickerstreak@62
|
48
|
flickerstreak@62
|
49 function module:EraseBarConfig(barName)
|
flickerstreak@62
|
50 self.db.profile.bars[barName] = nil
|
flickerstreak@62
|
51 end
|
flickerstreak@62
|
52
|
flickerstreak@62
|
53 function module:RenameBarConfig(oldname, newname)
|
flickerstreak@62
|
54 local b = self.db.profile.bars
|
flickerstreak@62
|
55 bars[newname], bars[oldname] = bars[oldname], nil
|
flickerstreak@62
|
56 end
|
flickerstreak@62
|
57
|
flickerstreak@62
|
58 function module:ApplyConfigMode(mode,bars)
|
flickerstreak@62
|
59 -- swap out hidestates
|
flickerstreak@62
|
60 end
|
flickerstreak@62
|
61
|
flickerstreak@62
|
62
|
flickerstreak@62
|
63
|
flickerstreak@62
|
64
|
flickerstreak@62
|
65 -- Private --
|
flickerstreak@62
|
66
|
flickerstreak@62
|
67 -- traverse a table tree by key list and fetch the result or first nil
|
flickerstreak@62
|
68 local function tfetch(t, ...)
|
flickerstreak@62
|
69 for i = 1, select('#', ...) do
|
flickerstreak@62
|
70 t = t and t[select(i, ...)]
|
flickerstreak@62
|
71 end
|
flickerstreak@62
|
72 return t
|
flickerstreak@62
|
73 end
|
flickerstreak@62
|
74
|
flickerstreak@62
|
75 -- traverse a table tree by key list and build tree as necessary
|
flickerstreak@62
|
76 local function tbuild(t, ...)
|
flickerstreak@62
|
77 for i = 1, select('#', ...) do
|
flickerstreak@62
|
78 local key = select(i, ...)
|
flickerstreak@62
|
79 if not t[key] then t[key] = { } end
|
flickerstreak@62
|
80 t = t[key]
|
flickerstreak@62
|
81 end
|
flickerstreak@62
|
82 return t
|
flickerstreak@62
|
83 end
|
flickerstreak@62
|
84
|
flickerstreak@62
|
85
|
flickerstreak@62
|
86 local rules
|
flickerstreak@62
|
87 local BuildRuleString
|
flickerstreak@62
|
88 do
|
flickerstreak@62
|
89 local function ClassCheck(...)
|
flickerstreak@62
|
90 for i = 1, select('#',...) do
|
flickerstreak@62
|
91 local _, c = UnitClass("player")
|
flickerstreak@62
|
92 if c == select(i,...) then
|
flickerstreak@62
|
93 return false
|
flickerstreak@62
|
94 end
|
flickerstreak@62
|
95 end
|
flickerstreak@62
|
96 return true
|
flickerstreak@62
|
97 end
|
flickerstreak@62
|
98
|
flickerstreak@62
|
99 -- The structure of this table is important: each row is designed to be unpack()ed
|
flickerstreak@62
|
100 -- into variables as defined in the header comment row.
|
flickerstreak@62
|
101 -- The 'fields' subtable (index 4) structure is also important: its subtables
|
flickerstreak@62
|
102 -- are ordered to match appearances of '%s' (string-substitutions) in the corresponding
|
flickerstreak@62
|
103 -- rules[] format-string entry. Each subtable's single element's key is the storage key used
|
flickerstreak@62
|
104 -- in the user db, and the name of the group-element table in the config tree, so it too
|
flickerstreak@62
|
105 -- is important.
|
flickerstreak@62
|
106 --
|
flickerstreak@62
|
107 -- While this allows for very compact code and data storage, the scheme is admittedly obtuse,
|
flickerstreak@62
|
108 -- so I document it here for my own sanity.
|
flickerstreak@62
|
109 --
|
flickerstreak@62
|
110 rules = {
|
flickerstreak@62
|
111 -- rule name hidden fields
|
flickerstreak@62
|
112 { "stance", L["Warrior Stance"], ClassCheck("WARRIOR"), { {battle = L["Battle Stance"]}, {defensive = L["Defensive Stance"]}, {berserker = L["Berserker Stance"]} } },
|
flickerstreak@62
|
113 { "form", L["Druid Form"], ClassCheck("DRUID"), { {bear = L["Bear"]}, {cat = L["Cat"]}, {treeOrMoonkin = L["Tree/Moonkin"]}, {caster = L["Normal"]}, } },
|
flickerstreak@62
|
114 { "stealth", L["Stealth"], ClassCheck("ROGUE","DRUID"), { {stealth = L["Stealth"]}, {normal = L["Normal"]} } },
|
flickerstreak@62
|
115 { "shadow", L["Shadowform"], ClassCheck("PRIEST"), { {shadowform = L["Shadowform"]}, {normal = L["Normal"]} } },
|
flickerstreak@62
|
116 { "pet", L["Pet"], ClassCheck("HUNTER","WARLOCK"), { {pet = L["With Pet"]}, {nopet = L["Without Pet"]} } },
|
flickerstreak@62
|
117 { "target", L["Target"], false, { {hostile = L["Hostile Target"]}, {friendly = L["Friendly Target"]}, {none = L["No Target"]} } },
|
flickerstreak@62
|
118 { "focus", L["Focus"], false, { {hostile = L["Hostile Focus"]}, {friendly = L["Friendly Focus"]}, {none = L["No Focus"]} } },
|
flickerstreak@62
|
119 { "group", L["In Group"], false, { {raid = L["Raid"]}, {party = L["Party"]}, {solo = L["Solo"]} } },
|
flickerstreak@62
|
120 { "key", L["Key Press"], false, { {state = L["On Key Press"]}, {keybinding = false} } }, -- keybinding has no state-selector, it's implemented elsewhere
|
flickerstreak@62
|
121 { "combat", L["Combat"], false, { {combat = L["In Combat"]}, {nocombat = L["Out of Combat"]} } },
|
flickerstreak@62
|
122 { "custom", L["Custom"], false, { {rule = false} } }, -- custom has no state-selector, it's implemented elsewhere
|
flickerstreak@62
|
123 }
|
flickerstreak@62
|
124
|
flickerstreak@62
|
125 do
|
flickerstreak@62
|
126 local forms = { }
|
flickerstreak@62
|
127 for i = 1, GetNumShapeshiftForms() do
|
flickerstreak@62
|
128 local icon, name = GetShapeshiftFormInfo(i)
|
flickerstreak@62
|
129 -- TODO: need to find out if name is localized, it probably is
|
flickerstreak@62
|
130 forms[name] = i;
|
flickerstreak@62
|
131 end
|
flickerstreak@62
|
132 local dStance = forms["Defensive Stance"] or 2
|
flickerstreak@62
|
133 local zStance = forms["Berserker Stance"] or 3
|
flickerstreak@62
|
134 local bForm = forms["Dire Bear Form"] or forms["Bear Form"] or 1
|
flickerstreak@62
|
135 local cForm = forms["Cat Form"] or 3
|
flickerstreak@62
|
136 local tForm = forms["Tree of Life"] or forms["Moonkin Form"] or 5
|
flickerstreak@62
|
137
|
flickerstreak@62
|
138 -- TODO: do the macro conditional strings need to be localized?
|
flickerstreak@62
|
139 local ruleformats = {
|
flickerstreak@62
|
140 stance = ("[stance:1] %%s; [stance:%d] %%s; [stance:%d] %%s"):format(dStance,zStance),
|
flickerstreak@62
|
141 form = ("[form:%d] %%s; [form:%d] %%s; [form:%d] %%s; %%s"):format(bForm,cForm,tForm),
|
flickerstreak@62
|
142 stealth = "[stealth] %s; %s",
|
flickerstreak@62
|
143 shadow = "[stance:1] %s; %s",
|
flickerstreak@62
|
144 pet = "[pet] %s; %s",
|
flickerstreak@62
|
145 target = "[harm] %s; [help] %s; %s",
|
flickerstreak@62
|
146 focus = "[target=focus,harm] %s; [target=focus,help] %s; %s",
|
flickerstreak@62
|
147 group = "[group:raid] %s; [group] %s; %s",
|
flickerstreak@62
|
148 combat = "[combat] %s; %s",
|
flickerstreak@62
|
149 custom = "%s",
|
flickerstreak@62
|
150 }
|
flickerstreak@62
|
151
|
flickerstreak@62
|
152 local fieldmap = { }
|
flickerstreak@62
|
153 for i = 1, #rules do
|
flickerstreak@62
|
154 fieldmap[rules[i][1]] = rules[i][4]
|
flickerstreak@62
|
155 end
|
flickerstreak@62
|
156
|
flickerstreak@62
|
157 local _scratch = { }
|
flickerstreak@62
|
158 function BuildRuleString(bar, name)
|
flickerstreak@62
|
159 local rule, data = module:GetRule(bar,name)
|
flickerstreak@62
|
160 if not rule then return "" end
|
flickerstreak@62
|
161 local fields = fieldmap[rule]
|
flickerstreak@62
|
162 for i = 1, #fields do
|
flickerstreak@62
|
163 _scratch[i] = data[next(fields[i])] -- TODO: insert default state here
|
flickerstreak@62
|
164 end
|
flickerstreak@62
|
165 for i = #fields+1, #_scratch do
|
flickerstreak@62
|
166 _scratch[i] = nil
|
flickerstreak@62
|
167 end
|
flickerstreak@62
|
168 local success, value = pcall(string.format, ruleformats[rule], unpack(_scratch))
|
flickerstreak@62
|
169 return success and value or "<error>"
|
flickerstreak@62
|
170 end
|
flickerstreak@62
|
171 end
|
flickerstreak@62
|
172
|
flickerstreak@25
|
173
|
flickerstreak@25
|
174 end
|
flickerstreak@25
|
175
|
flickerstreak@25
|
176
|
flickerstreak@62
|
177
|
flickerstreak@62
|
178 -- API --
|
flickerstreak@62
|
179
|
flickerstreak@62
|
180 function module:BuildStates( bar )
|
flickerstreak@62
|
181 local c = tfetch(self.db.profile.bars, bar:GetName(), "states")
|
flickerstreak@62
|
182 if c then
|
flickerstreak@62
|
183 for name, s in pairs(c) do
|
flickerstreak@62
|
184 -- TODO: new state here
|
flickerstreak@62
|
185 end
|
flickerstreak@62
|
186 end
|
flickerstreak@25
|
187 end
|
flickerstreak@25
|
188
|
flickerstreak@62
|
189 function module:CreateState( bar, name )
|
flickerstreak@62
|
190 local c = tbuild(self.db.profile.bars, bar:GetName(), "states")
|
flickerstreak@62
|
191 if c[name] then
|
flickerstreak@62
|
192 ReAction:UserError(L["State named '%s' already exists"]:format(name))
|
flickerstreak@62
|
193 else
|
flickerstreak@62
|
194 c[name] = { }
|
flickerstreak@62
|
195 -- TODO: new state here
|
flickerstreak@62
|
196 end
|
flickerstreak@62
|
197 end
|
flickerstreak@25
|
198
|
flickerstreak@62
|
199 function module:DeleteState( bar, name )
|
flickerstreak@62
|
200 local c = tfetch(self.db.profile.bars, bar:GetName(), "states")
|
flickerstreak@62
|
201 if c[name] then
|
flickerstreak@62
|
202 -- TODO: delete state
|
flickerstreak@62
|
203 c[name] = nil
|
flickerstreak@62
|
204 end
|
flickerstreak@62
|
205 end
|
flickerstreak@25
|
206
|
flickerstreak@62
|
207 function module:BuildRules( bar )
|
flickerstreak@62
|
208 for bar, c in pairs(self.db.profile.bars) do
|
flickerstreak@62
|
209 if c.rules then
|
flickerstreak@62
|
210 for name, t in pairs(c.rules) do
|
flickerstreak@62
|
211 local rule, config = next(t)
|
flickerstreak@62
|
212 self:SetRule(bar, name, rule, config)
|
flickerstreak@62
|
213 end
|
flickerstreak@62
|
214 end
|
flickerstreak@62
|
215 end
|
flickerstreak@62
|
216 end
|
flickerstreak@25
|
217
|
flickerstreak@62
|
218 function module:CreateRule( bar, name, rule, config )
|
flickerstreak@62
|
219 local c = tbuild(self.db.profile.bars, bar:GetName(), "rules")
|
flickerstreak@62
|
220 if c[name] then
|
flickerstreak@62
|
221 ReAction:UserError(L["Rule named '%s' already exists"]:format(name))
|
flickerstreak@62
|
222 else
|
flickerstreak@62
|
223 tbuild(self.db.profile.bars, bar:GetName(), "rules", name)
|
flickerstreak@62
|
224 if rule then
|
flickerstreak@62
|
225 self:SetRule(bar,name,rule,config)
|
flickerstreak@62
|
226 end
|
flickerstreak@62
|
227 end
|
flickerstreak@62
|
228 end
|
flickerstreak@62
|
229
|
flickerstreak@62
|
230 function module:DeleteRule( bar, name )
|
flickerstreak@62
|
231 local c = tfetch(self.db.profile.bars, bar:GetName(), "rules")
|
flickerstreak@62
|
232 if c[name] then
|
flickerstreak@62
|
233 local f = bar:GetFrame()
|
flickerstreak@62
|
234 -- TODO: delete rule
|
flickerstreak@62
|
235 c[name] = nil
|
flickerstreak@62
|
236 end
|
flickerstreak@62
|
237 end
|
flickerstreak@62
|
238
|
flickerstreak@62
|
239 function module:UpdateRule( bar, name )
|
flickerstreak@62
|
240 local rule, c = self:GetRule(bar,name)
|
flickerstreak@62
|
241 -- TODO: remove all relevant outdated attributes
|
flickerstreak@62
|
242 -- TODO: set new attributes
|
flickerstreak@62
|
243 end
|
flickerstreak@62
|
244
|
flickerstreak@62
|
245 function module:GetRule(bar, name)
|
flickerstreak@62
|
246 local c = tfetch(self.db.profile.bars, bar:GetName(), "rules", name)
|
flickerstreak@62
|
247 if c then
|
flickerstreak@62
|
248 return next(c) -- returns key, value (= rulename, configtable)
|
flickerstreak@62
|
249 end
|
flickerstreak@62
|
250 end
|
flickerstreak@62
|
251
|
flickerstreak@62
|
252 function module:SetRule(bar, name, rule, config)
|
flickerstreak@62
|
253 tbuild(self.db.profile.bars, bar:GetName(), "rules")[name] = { [rule] = (config or {}) }
|
flickerstreak@62
|
254 self:UpdateRule(bar,name)
|
flickerstreak@62
|
255 end
|
flickerstreak@62
|
256
|
flickerstreak@62
|
257
|
flickerstreak@62
|
258 -- options --
|
flickerstreak@62
|
259 local CreateBarOptions
|
flickerstreak@62
|
260 do
|
flickerstreak@62
|
261 local function GetRuleConfig(bar, name, rule, field)
|
flickerstreak@62
|
262 return tfetch(module.db.profile.bars, bar:GetName(), "rules", name, rule, field)
|
flickerstreak@62
|
263 end
|
flickerstreak@62
|
264
|
flickerstreak@62
|
265 local function SetRuleConfig( bar, name, rule, field, value )
|
flickerstreak@62
|
266 tbuild(module.db.profile.bars, bar:GetName(), "rules", name, rule)[field] = value
|
flickerstreak@62
|
267 end
|
flickerstreak@62
|
268
|
flickerstreak@62
|
269 local function CreateStateOptions(bar, name)
|
flickerstreak@62
|
270 return {
|
flickerstreak@62
|
271 type = "group",
|
flickerstreak@62
|
272 name = name,
|
flickerstreak@62
|
273 args = {
|
flickerstreak@62
|
274 -- show/hide would go here
|
flickerstreak@62
|
275 -- page # would go here
|
flickerstreak@62
|
276 -- anchoring would go here
|
flickerstreak@62
|
277 __delete__ = {
|
flickerstreak@62
|
278 type = "execute",
|
flickerstreak@62
|
279 name = L["Delete this State"],
|
flickerstreak@62
|
280 func = function(info)
|
flickerstreak@62
|
281 module:DeleteState(bar,name)
|
flickerstreak@62
|
282 module.options[bar].args.states.args[name] = nil
|
flickerstreak@62
|
283 end,
|
flickerstreak@62
|
284 order = -1
|
flickerstreak@62
|
285 },
|
flickerstreak@62
|
286 }
|
flickerstreak@62
|
287 }
|
flickerstreak@62
|
288 end
|
flickerstreak@62
|
289
|
flickerstreak@62
|
290
|
flickerstreak@62
|
291 -- display rule string setting is shared between all rule opts and is transient
|
flickerstreak@62
|
292 -- (mostly used for debugging)
|
flickerstreak@62
|
293 local display = { show = false }
|
flickerstreak@62
|
294
|
flickerstreak@62
|
295 local function CreateRuleOptions(bar, name)
|
flickerstreak@62
|
296 local function get(info)
|
flickerstreak@62
|
297 local rule = info[#info-1]
|
flickerstreak@62
|
298 local field = info[#info]
|
flickerstreak@62
|
299 return GetRuleConfig(bar,name,rule,field) or ""
|
flickerstreak@25
|
300 end
|
flickerstreak@25
|
301
|
flickerstreak@62
|
302 local function set(info, value)
|
flickerstreak@62
|
303 local rule = info[#info-1]
|
flickerstreak@62
|
304 local field = info[#info]
|
flickerstreak@62
|
305 SetRuleConfig(bar,name,rule,field,value)
|
flickerstreak@62
|
306 module:UpdateRule(bar,name)
|
flickerstreak@62
|
307 end
|
flickerstreak@25
|
308
|
flickerstreak@62
|
309 local opts = {
|
flickerstreak@62
|
310 type = "group",
|
flickerstreak@62
|
311 name = name,
|
flickerstreak@62
|
312 childGroups = "inline",
|
flickerstreak@62
|
313 args = {
|
flickerstreak@62
|
314 __select__ = {
|
flickerstreak@62
|
315 type = "select",
|
flickerstreak@62
|
316 name = L["Select Rule Type"],
|
flickerstreak@62
|
317 get = function(info) return module:GetRule(bar,name) or "" end,
|
flickerstreak@62
|
318 set = function(info,value) module:SetRule(bar,name,value) end, -- TODO: get default rule config and pass as final value
|
flickerstreak@62
|
319 values = function()
|
flickerstreak@62
|
320 local v = { }
|
flickerstreak@62
|
321 for i = 1, #rules do
|
flickerstreak@62
|
322 local rule, name, hidden = unpack(rules[i])
|
flickerstreak@62
|
323 if not hidden then
|
flickerstreak@62
|
324 v[rule] = name
|
flickerstreak@62
|
325 end
|
flickerstreak@62
|
326 end
|
flickerstreak@62
|
327 return v
|
flickerstreak@62
|
328 end,
|
flickerstreak@62
|
329 order = 1,
|
flickerstreak@62
|
330 },
|
flickerstreak@62
|
331 __delete__ = {
|
flickerstreak@62
|
332 type = "execute",
|
flickerstreak@62
|
333 name = L["Delete this Rule"],
|
flickerstreak@62
|
334 func = function(info)
|
flickerstreak@62
|
335 module:DeleteRule(bar,name)
|
flickerstreak@62
|
336 module.options[bar].args.rules.args[name] = nil
|
flickerstreak@62
|
337 end,
|
flickerstreak@62
|
338 order = -3
|
flickerstreak@62
|
339 },
|
flickerstreak@62
|
340 --
|
flickerstreak@62
|
341 -- rule selection groups will be inserted here
|
flickerstreak@62
|
342 --
|
flickerstreak@62
|
343 __show__ = {
|
flickerstreak@62
|
344 type = "toggle",
|
flickerstreak@62
|
345 name = L["Show Rule String"],
|
flickerstreak@62
|
346 desc = L["Toggles display of the raw rule string"],
|
flickerstreak@62
|
347 get = function() return display.show end,
|
flickerstreak@62
|
348 set = function(info,value) display.show = value end,
|
flickerstreak@62
|
349 order = -2
|
flickerstreak@62
|
350 },
|
flickerstreak@62
|
351 __rule__ = {
|
flickerstreak@62
|
352 type = "input",
|
flickerstreak@62
|
353 name = L["Rule String"],
|
flickerstreak@62
|
354 disabled = true,
|
flickerstreak@62
|
355 multiline = true,
|
flickerstreak@62
|
356 width = "double",
|
flickerstreak@62
|
357 hidden = function() return not display.show end,
|
flickerstreak@62
|
358 get = function() return BuildRuleString(bar,name) end,
|
flickerstreak@62
|
359 set = function() end,
|
flickerstreak@62
|
360 order = -1
|
flickerstreak@25
|
361 }
|
flickerstreak@25
|
362 }
|
flickerstreak@25
|
363 }
|
flickerstreak@62
|
364
|
flickerstreak@62
|
365 -- unpack rules table
|
flickerstreak@62
|
366 for i = 1, #rules do
|
flickerstreak@62
|
367 local rule, label, _, fields = unpack(rules[i])
|
flickerstreak@62
|
368 local hidden = function()
|
flickerstreak@62
|
369 return module:GetRule(bar,name) ~= rule
|
flickerstreak@62
|
370 end
|
flickerstreak@62
|
371 opts.args[rule] = {
|
flickerstreak@62
|
372 type = "group",
|
flickerstreak@62
|
373 name = label,
|
flickerstreak@62
|
374 hidden = hidden,
|
flickerstreak@62
|
375 disabled = hidden,
|
flickerstreak@62
|
376 inline = true,
|
flickerstreak@62
|
377 args = { }
|
flickerstreak@62
|
378 }
|
flickerstreak@62
|
379 for j = 1, #fields do
|
flickerstreak@62
|
380 local field, label = next(fields[j]) -- extract from table of single key-value pair
|
flickerstreak@62
|
381 if field and label then
|
flickerstreak@62
|
382 opts.args[rule].args[field] = {
|
flickerstreak@62
|
383 type = "select",
|
flickerstreak@62
|
384 name = L["Select State (%s):"]:format(label),
|
flickerstreak@62
|
385 values = function ()
|
flickerstreak@62
|
386 local states = tfetch(module.db.profile.bars,bar:GetName(),"states")
|
flickerstreak@62
|
387 local v = { }
|
flickerstreak@62
|
388 if states then
|
flickerstreak@62
|
389 for k in pairs(states) do
|
flickerstreak@62
|
390 v[k] = k
|
flickerstreak@62
|
391 end
|
flickerstreak@62
|
392 end
|
flickerstreak@62
|
393 return v
|
flickerstreak@62
|
394 end,
|
flickerstreak@62
|
395 set = set,
|
flickerstreak@62
|
396 get = get,
|
flickerstreak@62
|
397 order = 100 + j
|
flickerstreak@62
|
398 }
|
flickerstreak@62
|
399 end
|
flickerstreak@62
|
400 end
|
flickerstreak@62
|
401 end
|
flickerstreak@62
|
402
|
flickerstreak@62
|
403 -- set up special entry for keybinding
|
flickerstreak@62
|
404 opts.args.key.args.binding = {
|
flickerstreak@62
|
405 type = "keybinding",
|
flickerstreak@62
|
406 name = L["Key Binding"],
|
flickerstreak@62
|
407 get = get,
|
flickerstreak@62
|
408 set = set,
|
flickerstreak@62
|
409 order = -1
|
flickerstreak@62
|
410 }
|
flickerstreak@62
|
411
|
flickerstreak@62
|
412 -- set up special entry for custom
|
flickerstreak@62
|
413 opts.args.custom.args.rule = {
|
flickerstreak@62
|
414 type = "input",
|
flickerstreak@62
|
415 name = L["Rule"],
|
flickerstreak@62
|
416 desc = L["Syntax like macro conditions: see preset rules for examples"],
|
flickerstreak@62
|
417 get = get,
|
flickerstreak@62
|
418 set = set,
|
flickerstreak@62
|
419 validate = function (info, rule)
|
flickerstreak@62
|
420 local s = rule:gsub("%s","") -- remove all spaces
|
flickerstreak@62
|
421 if s:match(";$") then -- can't end with semicolon
|
flickerstreak@62
|
422 return L["Invalid custom rule '%s': Rule cannot end with ';'"]:format(rule)
|
flickerstreak@62
|
423 end
|
flickerstreak@62
|
424 if s == "" then
|
flickerstreak@62
|
425 return true
|
flickerstreak@62
|
426 end
|
flickerstreak@62
|
427 -- unfortunately %b and captures don't support the '+' notation, or this would be considerably simpler
|
flickerstreak@62
|
428 repeat
|
flickerstreak@62
|
429 repeat
|
flickerstreak@62
|
430 local c, r = s:match("(%b[])(.*)")
|
flickerstreak@62
|
431 if r then s = r end
|
flickerstreak@62
|
432 until c == nil
|
flickerstreak@62
|
433 local state, s = s:match("(%w+)(.*)")
|
flickerstreak@62
|
434 if not state then
|
flickerstreak@62
|
435 return L["Invalid custom rule '%s': Each expression must have a state"]:format(rule)
|
flickerstreak@62
|
436 end
|
flickerstreak@62
|
437 if not tfetch(module.db.profile.bars,bar:GetName(),"states",state) then
|
flickerstreak@62
|
438 return L["Invalid custom rule '%s': '%s' is not a state"]:format(rule,state)
|
flickerstreak@62
|
439 end
|
flickerstreak@62
|
440 if s:match("^[^;]") then
|
flickerstreak@62
|
441 return L["Invalid custom rule '%s': Expressions must be separated by ';'"]:format(rule)
|
flickerstreak@62
|
442 end
|
flickerstreak@62
|
443 until #s == 0
|
flickerstreak@62
|
444 return true
|
flickerstreak@62
|
445 end,
|
flickerstreak@62
|
446 multiline = true,
|
flickerstreak@62
|
447 order = 1,
|
flickerstreak@62
|
448 }
|
flickerstreak@62
|
449
|
flickerstreak@62
|
450 return opts
|
flickerstreak@25
|
451 end
|
flickerstreak@62
|
452
|
flickerstreak@62
|
453 CreateBarOptions = function(bar)
|
flickerstreak@62
|
454 local private = { }
|
flickerstreak@62
|
455 local options = {
|
flickerstreak@62
|
456 type = "group",
|
flickerstreak@62
|
457 name = L["Dynamic State"],
|
flickerstreak@62
|
458 childGroups = "tab",
|
flickerstreak@62
|
459 disabled = InCombatLockdown,
|
flickerstreak@62
|
460 args = {
|
flickerstreak@62
|
461 states = {
|
flickerstreak@62
|
462 type = "group",
|
flickerstreak@62
|
463 name = L["States"],
|
flickerstreak@62
|
464 childGroups = "tree",
|
flickerstreak@62
|
465 order = 1,
|
flickerstreak@62
|
466 args = {
|
flickerstreak@62
|
467 __new__ = {
|
flickerstreak@62
|
468 type = "group",
|
flickerstreak@62
|
469 name = L["New State..."],
|
flickerstreak@62
|
470 order = 1,
|
flickerstreak@62
|
471 args = {
|
flickerstreak@62
|
472 name = {
|
flickerstreak@62
|
473 type = "input",
|
flickerstreak@62
|
474 name = L["State Name"],
|
flickerstreak@62
|
475 desc = L["Set a name for the new state"],
|
flickerstreak@62
|
476 get = function() return private.newstatename or "" end,
|
flickerstreak@62
|
477 set = function(info,value) private.newstatename = value end,
|
flickerstreak@62
|
478 pattern = "^%w*$",
|
flickerstreak@62
|
479 usage = L["State names must be alphanumeric without spaces"],
|
flickerstreak@62
|
480 order = 1
|
flickerstreak@62
|
481 },
|
flickerstreak@62
|
482 create = {
|
flickerstreak@62
|
483 type = "execute",
|
flickerstreak@62
|
484 name = L["Create State"],
|
flickerstreak@62
|
485 func = function ()
|
flickerstreak@62
|
486 local name = private.newstatename
|
flickerstreak@62
|
487 module:CreateState(bar,name) -- TODO: select default state options and pass as final argument
|
flickerstreak@62
|
488 module.options[bar].args.states.args[name] = CreateStateOptions(bar,name)
|
flickerstreak@62
|
489 private.newstatename = ""
|
flickerstreak@62
|
490 end,
|
flickerstreak@62
|
491 disabled = function()
|
flickerstreak@62
|
492 local name = private.newstatename or ""
|
flickerstreak@62
|
493 return #name == 0 or name:find("%W")
|
flickerstreak@62
|
494 end,
|
flickerstreak@62
|
495 order = 2,
|
flickerstreak@62
|
496 }
|
flickerstreak@62
|
497 }
|
flickerstreak@62
|
498 }
|
flickerstreak@62
|
499 }
|
flickerstreak@62
|
500 },
|
flickerstreak@62
|
501 rules = {
|
flickerstreak@62
|
502 type = "group",
|
flickerstreak@62
|
503 name = L["Transition Rules"],
|
flickerstreak@62
|
504 childGroups = "tree",
|
flickerstreak@62
|
505 order = 2,
|
flickerstreak@62
|
506 args = {
|
flickerstreak@62
|
507 __new__ = {
|
flickerstreak@62
|
508 type = "group",
|
flickerstreak@62
|
509 name = L["New Rule..."],
|
flickerstreak@62
|
510 order = 1,
|
flickerstreak@62
|
511 args = {
|
flickerstreak@62
|
512 name = {
|
flickerstreak@62
|
513 type = "input",
|
flickerstreak@62
|
514 name = L["Rule Name"],
|
flickerstreak@62
|
515 desc = L["Set a name for the new transition rule"],
|
flickerstreak@62
|
516 get = function() return private.newtransname or "" end,
|
flickerstreak@62
|
517 set = function(info,value) private.newtransname = value end,
|
flickerstreak@62
|
518 pattern = "^%w*$",
|
flickerstreak@62
|
519 usage = L["Rule names must be alphanumeric without spaces"],
|
flickerstreak@62
|
520 order = 1
|
flickerstreak@62
|
521 },
|
flickerstreak@62
|
522 create = {
|
flickerstreak@62
|
523 type = "execute",
|
flickerstreak@62
|
524 name = L["Create Rule"],
|
flickerstreak@62
|
525 func = function ()
|
flickerstreak@62
|
526 local name = private.newtransname
|
flickerstreak@62
|
527 module:CreateRule(bar,name) -- TODO: select default rule and add as final argument
|
flickerstreak@62
|
528 module.options[bar].args.rules.args[name] = CreateRuleOptions(bar,name)
|
flickerstreak@62
|
529 private.newtransname = ""
|
flickerstreak@62
|
530 end,
|
flickerstreak@62
|
531 disabled = function ()
|
flickerstreak@62
|
532 local name = private.newtransname or ""
|
flickerstreak@62
|
533 return #name == 0 or name:find("%W")
|
flickerstreak@62
|
534 end,
|
flickerstreak@62
|
535 order = 2,
|
flickerstreak@62
|
536 },
|
flickerstreak@62
|
537 }
|
flickerstreak@62
|
538 }
|
flickerstreak@62
|
539 }
|
flickerstreak@62
|
540 },
|
flickerstreak@62
|
541 presets = {
|
flickerstreak@62
|
542 type = "group",
|
flickerstreak@62
|
543 name = L["Presets"],
|
flickerstreak@62
|
544 order = 3,
|
flickerstreak@62
|
545 args = {
|
flickerstreak@62
|
546 desc = {
|
flickerstreak@62
|
547 type = "description",
|
flickerstreak@62
|
548 name = L["Presets are canned sets of states and transitions. You can create your own presets to add to ReAction's built in defaults."],
|
flickerstreak@62
|
549 order = 1,
|
flickerstreak@62
|
550 },
|
flickerstreak@62
|
551 select = {
|
flickerstreak@62
|
552 type = "select",
|
flickerstreak@62
|
553 name = L["Select Preset"],
|
flickerstreak@62
|
554 set = function(info,value) end,
|
flickerstreak@62
|
555 get = function() return "" end,
|
flickerstreak@62
|
556 values = function() return { } end,
|
flickerstreak@62
|
557 order = 2,
|
flickerstreak@62
|
558 },
|
flickerstreak@62
|
559 load = {
|
flickerstreak@62
|
560 type = "execute",
|
flickerstreak@62
|
561 name = L["Load"],
|
flickerstreak@62
|
562 func = function() end,
|
flickerstreak@62
|
563 width = "half",
|
flickerstreak@62
|
564 order = 3,
|
flickerstreak@62
|
565 },
|
flickerstreak@62
|
566 delete = {
|
flickerstreak@62
|
567 type = "execute",
|
flickerstreak@62
|
568 name = L["Delete"],
|
flickerstreak@62
|
569 disabled = function() return false end,
|
flickerstreak@62
|
570 func = function() end,
|
flickerstreak@62
|
571 width = "half",
|
flickerstreak@62
|
572 order = 4,
|
flickerstreak@62
|
573 },
|
flickerstreak@62
|
574 hdr = {
|
flickerstreak@62
|
575 type = "header",
|
flickerstreak@62
|
576 name = " ",
|
flickerstreak@62
|
577 order = 5,
|
flickerstreak@62
|
578 },
|
flickerstreak@62
|
579 save = {
|
flickerstreak@62
|
580 type = "input",
|
flickerstreak@62
|
581 name = L["Save As..."],
|
flickerstreak@62
|
582 get = function() return "" end,
|
flickerstreak@62
|
583 set = function(info,name) end,
|
flickerstreak@62
|
584 order = 6,
|
flickerstreak@62
|
585 },
|
flickerstreak@62
|
586 },
|
flickerstreak@62
|
587 },
|
flickerstreak@62
|
588 }
|
flickerstreak@62
|
589 }
|
flickerstreak@62
|
590 local states = tfetch(module.db.profile.bars, bar:GetName(), "states")
|
flickerstreak@62
|
591 if states then
|
flickerstreak@62
|
592 for name, config in pairs(states) do
|
flickerstreak@62
|
593 options.args.states.args[name] = CreateStateOptions(bar,name)
|
flickerstreak@62
|
594 end
|
flickerstreak@62
|
595 end
|
flickerstreak@62
|
596 local rules = tfetch(module.db.profile.bars, bar:GetName(), "rules")
|
flickerstreak@62
|
597 if rules then
|
flickerstreak@62
|
598 for name, config in pairs(rules) do
|
flickerstreak@62
|
599 options.args.rules.args[name] = CreateRuleOptions(bar,name)
|
flickerstreak@62
|
600 end
|
flickerstreak@62
|
601 end
|
flickerstreak@62
|
602 return options
|
flickerstreak@62
|
603 end
|
flickerstreak@25
|
604 end
|
flickerstreak@25
|
605
|
flickerstreak@62
|
606 function module:GetBarOptions(bar)
|
flickerstreak@62
|
607 if not self.options[bar] then
|
flickerstreak@62
|
608 self.options[bar] = CreateBarOptions(bar)
|
flickerstreak@62
|
609 end
|
flickerstreak@62
|
610 return self.options[bar]
|
flickerstreak@25
|
611 end
|