comparison modules/Config.lua @ 109:410d036c43b2

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