comparison modules/ReAction_ConfigUI/ReAction_ConfigUI.lua @ 60:44649a10378d

Fixed options handling to create a separate table for each bar instead of a shared table with proxy handler. Also simplified options registration and moved some options around.
author Flick <flickerstreak@gmail.com>
date Sat, 10 May 2008 00:08:01 +0000
parents 7430a8dd4e90
children 2ee41dcd673f
comparison
equal deleted inserted replaced
59:7430a8dd4e90 60:44649a10378d
10 local _G = _G 10 local _G = _G
11 local AceConfigReg = LibStub("AceConfigRegistry-3.0") 11 local AceConfigReg = LibStub("AceConfigRegistry-3.0")
12 local AceConfigDialog = LibStub("AceConfigDialog-3.0") 12 local AceConfigDialog = LibStub("AceConfigDialog-3.0")
13 13
14 -- some constants 14 -- some constants
15 local pointTable = { 15 local configName = "ReAction"
16 CENTER = L["Center"],
17 LEFT = L["Left"],
18 RIGHT = L["Right"],
19 TOP = L["Top"],
20 BOTTOM = L["Bottom"],
21 TOPLEFT = L["Top Left"],
22 TOPRIGHT = L["Top Right"],
23 BOTTOMLEFT = L["Bottom Left"],
24 BOTTOMRIGHT = L["Bottom Right"],
25 }
26 16
27 -- module declaration 17 -- module declaration
28 local moduleID = "ConfigUI" 18 local moduleID = "ConfigUI"
29 local module = ReAction:NewModule( moduleID, 19 local module = ReAction:NewModule( moduleID,
30 "AceEvent-3.0" 20 "AceEvent-3.0"
39 editorCloseOnLaunch = true, 29 editorCloseOnLaunch = true,
40 } 30 }
41 } 31 }
42 ) 32 )
43 33
44 ReAction.RegisterCallback(self,"OnOptionsRegistered") 34 self:RegisterEvent("PLAYER_REGEN_DISABLED")
35 ReAction.RegisterCallback(self,"OnOptionsRegistered","OnOptionsRefreshed")
45 ReAction.RegisterCallback(self,"OnOptionsRefreshed") 36 ReAction.RegisterCallback(self,"OnOptionsRefreshed")
46 ReAction.RegisterCallback(self,"OnCreateBar")
47 ReAction.RegisterCallback(self,"OnEraseBar")
48 ReAction.RegisterCallback(self,"OnRenameBar")
49 self:InitializeOptions() 37 self:InitializeOptions()
50 self:RegisterEvent("PLAYER_REGEN_DISABLED")
51 end
52
53
54 -- Creates a dispatcher to act as a handler and translate method calls from
55 -- handler:method(info,value) to module:method(bar,value). If the opts table has
56 -- a handler set, that will be used instead of module.
57 -- Note: we replace the top level table if it's a group, giving it a new handler.
58 local function CreateModuleBarDispatcher(module,bar,opts)
59 local g = { }
60 if opts.type == "group" then
61 for k,v in pairs(opts) do
62 g[k] = v
63 end
64 else
65 g.type = "group"
66 g.name = module:GetName()
67 g.args = {
68 arg1 = opts
69 }
70 end
71 local handler = opts.handler or module
72 g.handler = setmetatable( {}, {
73 __index = function(self, idx)
74 local f = rawget(self,idx)
75 if not f then
76 f = function(_, info, ...)
77 return handler[idx](handler, bar, ...)
78 end
79 rawset(self,idx,f) -- cache for future use
80 end
81 return f
82 end
83 })
84 return g
85 end
86
87
88 function module:OnOptionsRegistered(evt, context, module, opts)
89 local c = self.configOptions.args[context]
90 if context == "bar" then
91 for name,bar in pairs(ReAction.bars) do
92 local key = self.barOptMap[name]
93 if key then
94 self.editorOpts.args[key].plugins[module:GetName()] = { [module:GetName()] = CreateModuleBarDispatcher(module,bar,opts) }
95 end
96 end
97 elseif c then
98 for k, v in pairs(opts) do
99 c.args[k] = v
100 end
101 end
102 end 38 end
103 39
104 function module:OnOptionsRefreshed(evt) 40 function module:OnOptionsRefreshed(evt)
105 AceConfigReg:NotifyChange("ReAction") 41 AceConfigReg:NotifyChange(configName)
106 AceConfigReg:NotifyChange("ReAction-Editor") 42 if self.editor then self.editor:Refresh() end
107 end
108
109 function module:OnCreateBar(evt, bar)
110 local name = bar:GetName()
111 -- AceConfig doesn't allow spaces, etc, in arg key names, and they must be
112 -- unique strings. So generate a unique key (it can be whatever) for the bar
113 local args = self.editorOpts.args
114 local key
115 local i = 1
116 repeat
117 key = ("bar%s"):format(i)
118 i = i+1
119 until args[key] == nil
120 self.barOptMap[name] = key
121 args[key] = {
122 type = "group",
123 name = name,
124 childGroups = "tab",
125 args = {
126 general = {
127 type = "group",
128 name = L["General"],
129 order = 1,
130 args = {
131 name = {
132 type = "input",
133 name = L["Rename Bar"],
134 get = function() return bar:GetName() end,
135 set = function(info, value) return ReAction:RenameBar(bar, value) end,
136 order = 1,
137 },
138 delete = {
139 type = "execute",
140 name = L["Delete Bar"],
141 desc = function() return bar:GetName() end,
142 confirm = true,
143 func = function() ReAction:EraseBar(bar) end,
144 order = 2
145 },
146 anchor = {
147 type = "group",
148 name = L["Anchor"],
149 inline = true,
150 args = {
151 frame = {
152 type = "input",
153 name = L["Frame"],
154 desc = L["The frame that the bar is anchored to"],
155 get = function() local _, f = bar:GetAnchor(); return f end,
156 set = function(info, val) bar:SetAnchor(nil,val) end,
157 validate = function(info, name)
158 if name then
159 local f = ReAction:GetBar(name)
160 if f then
161 return true
162 else
163 f = _G[name]
164 if f and type(f) == "table" and f.IsObjectType and f:IsObjectType("Frame") then
165 return true
166 end
167 end
168 end
169 return false
170 end,
171 width = "double",
172 order = 1
173 },
174 point = {
175 type = "select",
176 name = L["Point"],
177 desc = L["Anchor point on the bar frame"],
178 style = "dropdown",
179 get = function() return bar:GetAnchor() end,
180 set = function(info, val) bar:SetAnchor(val) end,
181 values = pointTable,
182 order = 2,
183 },
184 relativePoint = {
185 type = "select",
186 name = L["Relative Point"],
187 desc = L["Anchor point on the target frame"],
188 style = "dropdown",
189 get = function() local p,f,r = bar:GetAnchor(); return r end,
190 set = function(info, val) bar:SetAnchor(nil,nil,val) end,
191 values = pointTable,
192 order = 3,
193 },
194 x = {
195 type = "input",
196 pattern = "\-?%d+",
197 name = L["X offset"],
198 get = function() local p,f,r,x = bar:GetAnchor(); return ("%d"):format(x) end,
199 set = function(info,val) bar:SetAnchor(nil,nil,nil,val) end,
200 order = 4
201 },
202 y = {
203 type = "input",
204 pattern = "\-?%d+",
205 name = L["Y offset"],
206 get = function() local p,f,r,x,y = bar:GetAnchor(); return ("%d"):format(y) end,
207 set = function(info,val) bar:SetAnchor(nil,nil,nil,nil,val) end,
208 order = 5
209 },
210 },
211 order = 3
212 },
213 },
214 },
215 },
216 plugins = { },
217 }
218
219 -- Create a dispatcher for all the module options tables registered to ReAction under the 'bar' context
220 for module, opts in pairs(ReAction:GetOptions("bar")) do
221 args[key].plugins[module:GetName()] = { [module:GetName()] = CreateModuleBarDispatcher(module, bar, opts) }
222 end
223 end
224
225 function module:OnEraseBar(evt, name)
226 local key = self.barOptMap[name]
227 self.barOptMap[name] = nil
228 if key then
229 self.editorOpts.args[key] = nil
230 self:RefreshBarEditor()
231 end
232 end
233
234 function module:OnRenameBar(evt, oldname, newname)
235 local key = self.barOptMap[oldname]
236 self.barOptMap[oldname], self.barOptMap[newname] = nil, key
237 if key then
238 self.editorOpts.args[key].name = newname
239 self:RefreshBarEditor()
240 end
241 end 43 end
242 44
243 function module:PLAYER_REGEN_DISABLED() 45 function module:PLAYER_REGEN_DISABLED()
244 if self.editor then 46 if self.editor then
245 self.editor:Hide() 47 self.editor:Hide()
250 -- any user errors should be flashed to the UIErrorsFrame 52 -- any user errors should be flashed to the UIErrorsFrame
251 UIErrorsFrame:AddMessage(msg) 53 UIErrorsFrame:AddMessage(msg)
252 end 54 end
253 55
254 function module:OpenConfig() 56 function module:OpenConfig()
255 InterfaceOptionsFrame_OpenToFrame("ReAction") 57 InterfaceOptionsFrame_OpenToFrame(configName)
256 end
257
258 function module:LaunchBarEditor(bar)
259 if InCombatLockdown() then
260 self:UserError(L["ReAction config mode disabled during combat."])
261 else
262 if not self.editor then
263 -- use a local container to work around AceConfigDialog closing
264 -- both the bar editor and the global options when interface options is closed
265 local ed = LibStub("AceGUI-3.0"):Create("Frame")
266 ed.frame:SetClampedToScreen(true)
267 local old_OnUpdate = ed.frame:GetScript("OnUpdate")
268 ed.frame:SetScript("OnUpdate", function(dt)
269 if old_OnUpdate then
270 old_OnUpdate(dt)
271 end
272 if ed.closePending then
273 InterfaceOptionsFrame:Hide()
274 ed.closePending = false
275 end
276 if ed.selfClosePending then
277 ed:Hide()
278 AceConfigReg:NotifyChange("ReAction")
279 ed.selfClosePending = false
280 end
281 end )
282 ed:SetCallback("OnClose",
283 function()
284 ReAction:SetConfigMode(false)
285 end )
286 self.editor = ed
287 AceConfigDialog:SetDefaultSize("ReAction-Editor", 640, 420)
288 end
289
290 AceConfigDialog:Open("ReAction-Editor", self.editor)
291 ReAction:SetConfigMode(true)
292 end
293 end
294
295 function module:RefreshBarEditor()
296 AceConfigReg:NotifyChange("ReAction-Editor")
297 if self.editor and self.editor.frame:IsShown() then
298 AceConfigDialog:Open("ReAction-Editor", self.editor)
299 end
300 end
301
302 function module:GetBarTypes()
303 local opts = self.optBarTypes or { }
304 self.optBarTypes = { }
305 for k,v in pairs(opts) do
306 opts[k] = nil
307 end
308 for k in pairs(ReAction.defaultBarConfig) do
309 opts[k] = k
310 end
311 return opts
312 end
313
314 function module:CreateBar()
315 if self.tmpBarName and self.tmpBarName ~= "" then
316 ReAction:CreateBar(self.tmpBarName, self.tmpBarType or ReAction.defaultBarConfigChoice, self.tmpBarRows, self.tmpBarCols, self.tmpBarSize, self.tmpBarSpacing)
317 self.tmpBarName = nil
318 end
319 end 58 end
320 59
321 function module:InitializeOptions() 60 function module:InitializeOptions()
322 -- general config options 61 ReAction:RegisterOptions(self, {
323 local opts = {
324 type = "group",
325 name = "ReAction",
326 childGroups = "tab",
327 args = {
328 _desc = {
329 type = "description",
330 name = L["Customizable replacement for Blizzard's Action Bars"],
331 order = 1,
332 },
333 _launchEditor = { 62 _launchEditor = {
334 type = "execute", 63 type = "execute",
335 handler = self, 64 handler = self,
336 name = L["Edit Bars..."], 65 name = L["Edit Bars..."],
337 desc = L["Show the ReAction Bar Editor dialogue"], 66 desc = L["Show the ReAction Bar Editor dialogue"],
352 desc = L["Close the Interface Options window when launching the ReAction Bar Editor"], 81 desc = L["Close the Interface Options window when launching the ReAction Bar Editor"],
353 get = function() return self.db.profile.closeOnLaunch end, 82 get = function() return self.db.profile.closeOnLaunch end,
354 set = function(info, val) self.db.profile.closeOnLaunch = val end, 83 set = function(info, val) self.db.profile.closeOnLaunch = val end,
355 order = 3, 84 order = 3,
356 }, 85 },
357 global = { 86 }, true) -- global
358 type = "group", 87
359 name = L["Global Settings"], 88 AceConfigReg:RegisterOptionsTable(configName,ReAction.options)
360 desc = L["Global configuration settings"], 89 self.frame = AceConfigDialog:AddToBlizOptions(configName, configName)
361 args = { },
362 order = 3,
363 },
364 _profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(ReAction.db),
365 module = {
366 type = "group",
367 childGroups = "select",
368 name = L["Module Settings"],
369 desc = L["Configuration settings for each module"],
370 args = { },
371 order = -1,
372 },
373 },
374 plugins = { }
375 }
376 self.configOptions = opts
377 opts.args._profile.order = -2
378 AceConfigReg:RegisterOptionsTable("ReAction",opts)
379 self.frame = AceConfigDialog:AddToBlizOptions("ReAction", "ReAction")
380 self.frame.obj:SetCallback("default", 90 self.frame.obj:SetCallback("default",
381 function() 91 function()
382 ReAction.db:ResetProfile() 92 ReAction.db:ResetProfile()
383 module:OpenConfig() 93 self:OnOptionsRefreshed()
384 end ) 94 end )
385 95 end
386 -- import options from registered modules 96
387 for c, tbl in pairs(opts.args) do 97
388 for _, m in pairs(ReAction:GetOptions(c)) do 98
389 for k, v in pairs(m) do 99
390 tbl.args[k] = v 100 -- Bar Editor --
101 local function NewEditor()
102 -- private variables
103 local editorName = "ReAction-Editor"
104 local barOptMap = { }
105 local tmp = { }
106 local pointTable = {
107 CENTER = L["Center"],
108 LEFT = L["Left"],
109 RIGHT = L["Right"],
110 TOP = L["Top"],
111 BOTTOM = L["Bottom"],
112 TOPLEFT = L["Top Left"],
113 TOPRIGHT = L["Top Right"],
114 BOTTOMLEFT = L["Bottom Left"],
115 BOTTOMRIGHT = L["Bottom Right"],
116 }
117
118
119 -- use a local GUI container to work around AceConfigDialog closing
120 -- both the bar editor and the global options when interface options is closed
121 local editor = LibStub("AceGUI-3.0"):Create("Frame")
122 local frame = editor.frame
123 frame:SetClampedToScreen(true)
124 local old_OnUpdate = frame:GetScript("OnUpdate")
125 frame:SetScript("OnUpdate", function(dt)
126 if old_OnUpdate then
127 old_OnUpdate(dt)
391 end 128 end
392 end 129 if editor.closePending then
393 end 130 InterfaceOptionsFrame:Hide()
394 131 editor.closePending = false
395 ReAction:RegisterOptions("module",self, { 132 end
396 configUI = { 133 if editor.selfClosePending then
397 type = "group", 134 ed:Hide()
398 name = "Config UI", 135 AceConfigReg:NotifyChange(configName)
399 desc = "description", 136 editor.selfClosePending = false
400 args = { 137 end
401 foo = { 138 end )
402 type = "toggle", 139 editor:SetCallback("OnClose",
403 handler = self, 140 function()
404 name = "foo", 141 ReAction:SetConfigMode(false)
405 desc = "description", 142 end )
406 get = function() return true end, 143 AceConfigDialog:SetDefaultSize(editorName, 700, 420)
407 set = function() end, 144
408 } 145
409 } 146 local options = {
410 },
411 })
412
413 -- bar editor options
414 local editorOpts = {
415 type = "group", 147 type = "group",
416 name = ("ReAction - %s"):format(L["Bar Editor"]), 148 name = ("ReAction - %s"):format(L["Bar Editor"]),
417 handler = self, 149 handler = editor,
418 childGroups = "tree", 150 childGroups = "tree",
419 args = { 151 args = {
420 desc = { 152 desc = {
421 type = "description", 153 type = "description",
422 name = L["Use the mouse to arrange and resize the bars on screen. Tooltips on bars indicate additional functionality."], 154 name = L["Use the mouse to arrange and resize the bars on screen. Tooltips on bars indicate additional functionality."],
425 launchConfig = { 157 launchConfig = {
426 type = "execute", 158 type = "execute",
427 name = L["Global Config"], 159 name = L["Global Config"],
428 desc = L["Opens ReAction global configuration settings panel"], 160 desc = L["Opens ReAction global configuration settings panel"],
429 func = function() 161 func = function()
430 self:OpenConfig() 162 module:OpenConfig()
431 -- you can't close a dialog in response to an options click, because the end of the 163 -- you can't close a dialog in response to an options click, because the end of the
432 -- handler for all the button events calls lib:Open() 164 -- handler for all the button events calls lib:Open()
433 -- So, schedule a close on the next OnUpdate 165 -- So, schedule a close on the next OnUpdate
434 if self.db.profile.editorCloseOnLaunch then 166 if module.db.profile.editorCloseOnLaunch then
435 self.editor.selfClosePending = true 167 editor.selfClosePending = true
436 end 168 end
437 end, 169 end,
438 order = 2 170 order = 2
439 }, 171 },
440 closeThis = { 172 closeThis = {
441 type = "toggle", 173 type = "toggle",
442 name = L["Close on Launch"], 174 name = L["Close on Launch"],
443 desc = L["Close the Bar Editor when opening the ReAction global Interface Options"], 175 desc = L["Close the Bar Editor when opening the ReAction global Interface Options"],
444 get = function() return self.db.profile.editorCloseOnLaunch end, 176 get = function() return module.db.profile.editorCloseOnLaunch end,
445 set = function(info, val) self.db.profile.editorCloseOnLaunch = val end, 177 set = function(info, val) module.db.profile.editorCloseOnLaunch = val end,
446 order = 3, 178 order = 3,
447 }, 179 },
448 new = { 180 new = {
449 type = "group", 181 type = "group",
450 name = L["New Bar..."], 182 name = L["New Bar..."],
457 }, 189 },
458 name = { 190 name = {
459 type = "input", 191 type = "input",
460 name = L["Bar Name"], 192 name = L["Bar Name"],
461 desc = L["Enter a name for your new action bar"], 193 desc = L["Enter a name for your new action bar"],
462 get = function() return self.tmpBarName or "" end, 194 get = function() return tmp.barName or "" end,
463 set = function(info, val) self.tmpBarName = val end, 195 set = function(info, val) tmp.barName = val end,
464 order = 2, 196 order = 2,
465 }, 197 },
466 type = { 198 type = {
467 type = "select", 199 type = "select",
468 name = L["Button Type"], 200 name = L["Button Type"],
469 get = function() return self.tmpBarType or ReAction.defaultBarConfigChoice or "" end, 201 get = function() return tmp.barType or ReAction.defaultBarConfigChoice or "" end,
470 set = function(info, val) 202 set = function(info, val)
471 local c = ReAction.defaultBarConfig[val] 203 local c = ReAction.defaultBarConfig[val]
472 self.tmpBarType = val 204 tmp.barType = val
473 self.tmpBarSize = c.defaultButtonSize or self.tmpBarSize 205 tmp.barSize = c.defaultButtonSize or tmp.barSize
474 self.tmpBarRows = c.defaultBarRows or self.tmpBarRows 206 tmp.barRows = c.defaultBarRows or tmp.barRows
475 self.tmpBarCols = c.defaultBarCols or self.tmpBarCols 207 tmp.barCols = c.defaultBarCols or tmp.barCols
476 self.tmpBarSpacing = c.defaultBarSpacing or self.tmpBarSpacing 208 tmp.barSpacing = c.defaultBarSpacing or tmp.barSpacing
477 end, 209 end,
478 values = "GetBarTypes", 210 values = "GetBarTypes",
479 order = 3, 211 order = 3,
480 }, 212 },
481 grid = { 213 grid = {
489 order = 1, 221 order = 1,
490 }, 222 },
491 rows = { 223 rows = {
492 type = "range", 224 type = "range",
493 name = L["Rows"], 225 name = L["Rows"],
494 get = function() return self.tmpBarRows or 1 end, 226 get = function() return tmp.barRows or 1 end,
495 set = function(info, val) self.tmpBarRows = val end, 227 set = function(info, val) tmp.barRows = val end,
496 width = "half", 228 width = "half",
497 min = 1, 229 min = 1,
498 max = 32, 230 max = 32,
499 step = 1, 231 step = 1,
500 order = 2, 232 order = 2,
501 }, 233 },
502 cols = { 234 cols = {
503 type = "range", 235 type = "range",
504 name = L["Columns"], 236 name = L["Columns"],
505 get = function() return self.tmpBarCols or 12 end, 237 get = function() return tmp.barCols or 12 end,
506 set = function(info, val) self.tmpBarCols = val end, 238 set = function(info, val) tmp.barCols = val end,
507 width = "half", 239 width = "half",
508 min = 1, 240 min = 1,
509 max = 32, 241 max = 32,
510 step = 1, 242 step = 1,
511 order = 3, 243 order = 3,
512 }, 244 },
513 sz = { 245 sz = {
514 type = "range", 246 type = "range",
515 name = L["Size"], 247 name = L["Size"],
516 get = function() return self.tmpBarSize or 36 end, 248 get = function() return tmp.barSize or 36 end,
517 set = function(info, val) self.tmpBarSize = val end, 249 set = function(info, val) tmp.barSize = val end,
518 width = "half", 250 width = "half",
519 min = 10, 251 min = 10,
520 max = 72, 252 max = 72,
521 step = 1, 253 step = 1,
522 order = 4, 254 order = 4,
523 }, 255 },
524 spacing = { 256 spacing = {
525 type = "range", 257 type = "range",
526 name = L["Spacing"], 258 name = L["Spacing"],
527 get = function() return self.tmpBarSpacing or 3 end, 259 get = function() return tmp.barSpacing or 3 end,
528 set = function(info, val) self.tmpBarSpacing = val end, 260 set = function(info, val) tmp.barSpacing = val end,
529 width = "half", 261 width = "half",
530 min = 0, 262 min = 0,
531 max = 24, 263 max = 24,
532 step = 1, 264 step = 1,
533 order = 5, 265 order = 5,
549 } 281 }
550 } 282 }
551 } 283 }
552 } 284 }
553 } 285 }
554 self.editorOpts = editorOpts 286 AceConfigReg:RegisterOptionsTable(editorName, options)
555 self.barOptMap = { } 287
556 AceConfigReg:RegisterOptionsTable("ReAction-Editor",editorOpts) 288 function editor:Open()
557 end 289 AceConfigDialog:Open(editorName,self)
558 290 end
291
292 function editor:Refresh()
293 AceConfigReg:NotifyChange(editorName)
294 if frame:IsShown() then
295 self:Open() -- do I need this?
296 end
297 end
298
299 function editor:CreateBarTree(bar)
300 local name = bar:GetName()
301 -- AceConfig doesn't allow spaces, etc, in arg key names, and they must be
302 -- unique strings. So generate a unique key (it can be whatever) for the bar
303 local args = options.args
304 local key
305 local i = 1
306 repeat
307 key = ("bar%s"):format(i)
308 i = i+1
309 until args[key] == nil
310 barOptMap[name] = key
311 args[key] = {
312 type = "group",
313 name = name,
314 childGroups = "tab",
315 args = {
316 general = {
317 type = "group",
318 name = L["General"],
319 order = 1,
320 args = {
321 name = {
322 type = "input",
323 name = L["Rename Bar"],
324 get = function() return bar:GetName() end,
325 set = function(info, value) return ReAction:RenameBar(bar, value) end,
326 order = 1,
327 },
328 delete = {
329 type = "execute",
330 name = L["Delete Bar"],
331 desc = function() return bar:GetName() end,
332 confirm = true,
333 func = function() ReAction:EraseBar(bar) end,
334 order = 2
335 },
336 anchor = {
337 type = "group",
338 name = L["Anchor"],
339 inline = true,
340 args = {
341 frame = {
342 type = "input",
343 name = L["Frame"],
344 desc = L["The frame that the bar is anchored to"],
345 get = function() local _, f = bar:GetAnchor(); return f end,
346 set = function(info, val) bar:SetAnchor(nil,val) end,
347 validate = function(info, name)
348 if name then
349 local f = ReAction:GetBar(name)
350 if f then
351 return true
352 else
353 f = _G[name]
354 if f and type(f) == "table" and f.IsObjectType and f:IsObjectType("Frame") then
355 return true
356 end
357 end
358 end
359 return false
360 end,
361 width = "double",
362 order = 1
363 },
364 point = {
365 type = "select",
366 name = L["Point"],
367 desc = L["Anchor point on the bar frame"],
368 style = "dropdown",
369 get = function() return bar:GetAnchor() end,
370 set = function(info, val) bar:SetAnchor(val) end,
371 values = pointTable,
372 order = 2,
373 },
374 relativePoint = {
375 type = "select",
376 name = L["Relative Point"],
377 desc = L["Anchor point on the target frame"],
378 style = "dropdown",
379 get = function() local p,f,r = bar:GetAnchor(); return r end,
380 set = function(info, val) bar:SetAnchor(nil,nil,val) end,
381 values = pointTable,
382 order = 3,
383 },
384 x = {
385 type = "input",
386 pattern = "\-?%d+",
387 name = L["X offset"],
388 get = function() local p,f,r,x = bar:GetAnchor(); return ("%d"):format(x) end,
389 set = function(info,val) bar:SetAnchor(nil,nil,nil,val) end,
390 order = 4
391 },
392 y = {
393 type = "input",
394 pattern = "\-?%d+",
395 name = L["Y offset"],
396 get = function() local p,f,r,x,y = bar:GetAnchor(); return ("%d"):format(y) end,
397 set = function(info,val) bar:SetAnchor(nil,nil,nil,nil,val) end,
398 order = 5
399 },
400 },
401 order = 3
402 },
403 },
404 },
405 }
406 }
407 self:RefreshBarTree(bar)
408 end
409
410 function editor:RefreshBarTree(bar)
411 local opts = options.args[barOptMap[bar:GetName()]]
412 opts.plugins = { }
413 for name, module in ReAction:IterateModules() do
414 if module.GetBarOptions then
415 opts.plugins[module:GetName()] = { [module:GetName()] = module:GetBarOptions(bar) }
416 end
417 end
418 end
419
420 function editor:OnCreateBar(evt, bar)
421 self:CreateBarTree(bar)
422 end
423
424 function editor:OnEraseBar(evt, name)
425 local key = barOptMap[name]
426 barOptMap[name] = nil
427 if key then
428 options.args[key] = nil
429 self:Refresh()
430 end
431 end
432
433 function editor:OnRenameBar(evt, oldname, newname)
434 local key = barOptMap[oldname]
435 barOptMap[oldname], barOptMap[newname] = nil, key
436 if key then
437 options.args[key].name = newname
438 self:Refresh()
439 end
440 end
441
442 local _scratch = { }
443 function editor:GetBarTypes()
444 for k,v in pairs(_scratch) do
445 _scratch[k] = nil
446 end
447 for k in pairs(ReAction.defaultBarConfig) do
448 _scratch[k] = k
449 end
450 return _scratch
451 end
452
453 function editor:CreateBar()
454 if tmp.barName and tmp.barName ~= "" then
455 ReAction:CreateBar(tmp.barName, tmp.barType or ReAction.defaultBarConfigChoice, tmp.barRows, tmp.barCols, tmp.barSize, tmp.barSpacing)
456 tmp.barName = nil
457 end
458 end
459
460 ReAction.RegisterCallback(editor,"OnCreateBar")
461 ReAction.RegisterCallback(editor,"OnEraseBar")
462 ReAction.RegisterCallback(editor,"OnRenameBar")
463
464 for name, bar in pairs(ReAction.bars) do
465 editor:CreateBarTree(bar)
466 end
467
468 return editor
469 end
470
471
472 function module:LaunchBarEditor(bar)
473 if InCombatLockdown() then
474 self:UserError(L["ReAction config mode disabled during combat."])
475 else
476 if not self.editor then
477 self.editor = NewEditor()
478 end
479 self.editor:Open()
480 ReAction:SetConfigMode(true)
481 end
482 end
483