comparison Editor.lua @ 185:2e7a322e0195

move ConfigUI module to Editor non-module, make it more self-contained
author Flick <flickerstreak@gmail.com>
date Fri, 22 Oct 2010 23:48:02 +0000
parents modules/ConfigUI.lua@1ee86bbb05a0
children d58055179c16
comparison
equal deleted inserted replaced
184:1ee86bbb05a0 185:2e7a322e0195
1 local addonName, addonTable = ...
2 local ReAction = addonTable.ReAction
3 local L = ReAction.L
4 local _G = _G
5 local wipe = wipe
6
7 local AceConfigReg = LibStub("AceConfigRegistry-3.0")
8 local AceConfigDialog = LibStub("AceConfigDialog-3.0")
9
10
11 local pointTable = {
12 CENTER = L["Center"],
13 LEFT = L["Left"],
14 RIGHT = L["Right"],
15 TOP = L["Top"],
16 BOTTOM = L["Bottom"],
17 TOPLEFT = L["Top Left"],
18 TOPRIGHT = L["Top Right"],
19 BOTTOMLEFT = L["Bottom Left"],
20 BOTTOMRIGHT = L["Bottom Right"],
21 }
22
23 local Editor = { }
24
25 function Editor:New()
26 -- create new self
27 self = setmetatable( { }, { __index = self } )
28
29 self.barOptMap = setmetatable({},{__mode="v"})
30 self.tmp = { }
31 self.configID = "ReAction-Editor"
32
33 self.gui = LibStub("AceGUI-3.0"):Create("Frame")
34
35 local frame = self.gui.frame
36 frame:SetClampedToScreen(true)
37 frame:Hide()
38
39 frame:SetScript("OnHide",
40 function(...)
41 ReAction:SetConfigMode(false)
42 end)
43
44 self.options = {
45 type = "group",
46 name = L["Select Bar:"],
47 desc = "foo foo foo",
48 handler = self,
49 childGroups = "select",
50 args = {
51 launchConfig = {
52 type = "execute",
53 name = L["Global Config"],
54 desc = L["Opens ReAction global configuration settings panel"],
55 func = function()
56 if ReAction.db.profile.editorCloseOnLaunch then
57 self:Close()
58 end
59 ReAction:ShowOptions()
60 end,
61 order = 1
62 },
63 closeThis = {
64 type = "toggle",
65 name = L["Close Editor"],
66 desc = L["Close the Bar Editor when opening the ReAction global Interface Options"],
67 get = function() return ReAction.db.profile.editorCloseOnLaunch end,
68 set = function(info, val) ReAction.db.profile.editorCloseOnLaunch = val end,
69 order = 2,
70 },
71 hdr = {
72 type = "header",
73 name = "",
74 order = 3,
75 },
76 desc = {
77 type = "description",
78 name = L["Use the mouse to arrange and resize the bars on screen. Tooltips on bars indicate additional functionality."],
79 width = "double",
80 order = 4,
81 },
82 _new = {
83 type = "group",
84 name = L["New Bar..."],
85 order = 5,
86 args = {
87 desc = {
88 type = "description",
89 name = L["Choose a name, type, and initial grid for your new action bar:"],
90 order = 1,
91 },
92 name = {
93 type = "input",
94 name = L["Bar Name"],
95 desc = L["Enter a name for your new action bar"],
96 get = function() return self.tmp.barName or "" end,
97 set = function(info, val) self.tmp.barName = val end,
98 order = 2,
99 },
100 type = {
101 type = "select",
102 name = L["Button Type"],
103 get = function() return self.tmp.barType or ReAction:GetDefaultBarType() or "" end,
104 set = function(info, val)
105 local c = ReAction:GetBarTypeConfig(val)
106 self.tmp.barType = val
107 self.tmp.barSize = c.defaultButtonSize or self.tmp.barSize
108 self.tmp.barRows = c.defaultBarRows or self.tmp.barRows
109 self.tmp.barCols = c.defaultBarCols or self.tmp.barCols
110 self.tmp.barSpacing = c.defaultBarSpacing or self.tmp.barSpacing
111 end,
112 values = "GetBarTypes",
113 order = 3,
114 },
115 go = {
116 type = "execute",
117 name = L["Create Bar"],
118 func = "CreateBar",
119 order = 4,
120 },
121 grid = {
122 type = "group",
123 name = L["Button Grid"],
124 inline = true,
125 order = 5,
126 args = {
127 rows = {
128 type = "range",
129 name = L["Rows"],
130 get = function() return self.tmp.barRows or 1 end,
131 set = function(info, val) self.tmp.barRows = val end,
132 width = "full",
133 min = 1,
134 max = 32,
135 step = 1,
136 order = 2,
137 },
138 cols = {
139 type = "range",
140 name = L["Columns"],
141 get = function() return self.tmp.barCols or 12 end,
142 set = function(info, val) self.tmp.barCols = val end,
143 width = "full",
144 min = 1,
145 max = 32,
146 step = 1,
147 order = 3,
148 },
149 sz = {
150 type = "range",
151 name = L["Size"],
152 get = function() return self.tmp.barSize or 36 end,
153 set = function(info, val) self.tmp.barSize = val end,
154 width = "full",
155 min = 10,
156 max = 72,
157 step = 1,
158 order = 4,
159 },
160 spacing = {
161 type = "range",
162 name = L["Spacing"],
163 get = function() return self.tmp.barSpacing or 3 end,
164 set = function(info, val) self.tmp.barSpacing = val end,
165 width = "full",
166 min = 0,
167 max = 24,
168 step = 1,
169 order = 5,
170 }
171 },
172 },
173 }
174 }
175 },
176 }
177
178 self.title = ("%s - %s"):format(L["ReAction"],L["Bar Editor"])
179 self.gui:SetTitle(self.title)
180
181 self.gui:SetCallback("OnClose",
182 function()
183 ReAction:SetConfigMode(false)
184 end )
185
186 AceConfigReg:RegisterOptionsTable(self.configID, self.options)
187 AceConfigDialog:SetDefaultSize(self.configID, 700, 540)
188
189 ReAction.RegisterCallback(self,"OnCreateBar")
190 ReAction.RegisterCallback(self,"OnDestroyBar")
191 ReAction.RegisterCallback(self,"OnEraseBar")
192 ReAction.RegisterCallback(self,"OnRenameBar")
193
194 for name, bar in ReAction:IterateBars() do
195 self:CreateBarTree(bar)
196 end
197
198 return self
199 end
200
201
202 function Editor:Open(bar, ...)
203 if bar then
204 AceConfigDialog:SelectGroup(self.configID, self.barOptMap[bar:GetName()], ...)
205 end
206 AceConfigDialog:Open(self.configID,self.gui)
207 self.gui:SetTitle(self.title)
208 end
209
210 function Editor:Close()
211 if self.gui then
212 print("closing...")
213 self.gui:ReleaseChildren()
214 self.gui:Hide()
215 end
216 end
217
218 function Editor:Refresh()
219 AceConfigReg:NotifyChange(self.configID)
220 end
221
222 function Editor:CreateBarTree(bar)
223 local name = bar:GetName()
224 -- AceConfig doesn't allow spaces, etc, in arg key names, and they must be
225 -- unique strings. So generate a unique key (it can be whatever) for the bar
226 local args = self.options.args
227 local key
228 local i = 1
229 repeat
230 key = ("bar%s"):format(i)
231 i = i+1
232 until args[key] == nil
233 self.barOptMap[name] = key
234 args[key] = {
235 type = "group",
236 name = name,
237 childGroups = "tab",
238 order = i+100,
239 args = {
240 general = {
241 type = "group",
242 name = L["General"],
243 order = 1,
244 args = {
245 name = {
246 type = "input",
247 name = L["Rename Bar"],
248 get = function() return bar:GetName() end,
249 set = function(info, value) return ReAction:RenameBar(bar, value) end,
250 order = 1,
251 },
252 delete = {
253 type = "execute",
254 name = L["Delete Bar"],
255 desc = function() return bar:GetName() end,
256 confirm = true,
257 func = function() ReAction:EraseBar(bar) end,
258 order = 2
259 },
260 anchor = {
261 type = "group",
262 name = L["Anchor"],
263 inline = true,
264 args = {
265 frame = {
266 type = "input",
267 name = L["Frame"],
268 desc = L["The frame that the bar is anchored to"],
269 get = function() local _, f = bar:GetAnchor(); return f end,
270 set = function(info, val) bar:SetAnchor(nil,val) end,
271 validate = function(info, name)
272 if name then
273 local f = ReAction:GetBar(name)
274 if f then
275 return true
276 else
277 f = _G[name]
278 if f and type(f) == "table" and f.IsObjectType and f:IsObjectType("Frame") then
279 local _, explicit = f:IsProtected()
280 return explicit
281 end
282 end
283 end
284 return false
285 end,
286 width = "double",
287 order = 1
288 },
289 point = {
290 type = "select",
291 name = L["Point"],
292 desc = L["Anchor point on the bar frame"],
293 style = "dropdown",
294 get = function() return bar:GetAnchor() end,
295 set = function(info, val) bar:SetAnchor(val) end,
296 values = pointTable,
297 order = 2,
298 },
299 relativePoint = {
300 type = "select",
301 name = L["Relative Point"],
302 desc = L["Anchor point on the target frame"],
303 style = "dropdown",
304 get = function() local p,f,r = bar:GetAnchor(); return r end,
305 set = function(info, val) bar:SetAnchor(nil,nil,val) end,
306 values = pointTable,
307 order = 3,
308 },
309 x = {
310 type = "input",
311 pattern = "\-?%d+",
312 name = L["X offset"],
313 get = function() local p,f,r,x = bar:GetAnchor(); return ("%d"):format(x) end,
314 set = function(info,val) bar:SetAnchor(nil,nil,nil,val) end,
315 order = 4
316 },
317 y = {
318 type = "input",
319 pattern = "\-?%d+",
320 name = L["Y offset"],
321 get = function() local p,f,r,x,y = bar:GetAnchor(); return ("%d"):format(y) end,
322 set = function(info,val) bar:SetAnchor(nil,nil,nil,nil,val) end,
323 order = 5
324 },
325 },
326 order = 3
327 },
328 alpha = {
329 type = "range",
330 name = L["Transparency"],
331 get = function() return bar:GetAlpha() end,
332 set = function(info, val) bar:SetAlpha(val) end,
333 min = 0,
334 max = 1,
335 isPercent = true,
336 step = 0.01,
337 bigStep = 0.05,
338 order = 4,
339 },
340 },
341 },
342 }
343 }
344 self:RefreshBarOptions()
345 end
346
347 function Editor:RefreshBarOptions()
348 for name, key in pairs(self.barOptMap) do
349 local bar = ReAction:GetBar(name)
350 if bar and key and self.options.args[key] then
351 self.options.args[key].plugins = self:GenerateBarOptionsTable(bar)
352 end
353 end
354 AceConfigReg:NotifyChange(self.configID)
355 end
356
357 function Editor:OnCreateBar(evt, bar)
358 if not self.tmp.creating then
359 -- a bit of hack to work around OnCreateBar event handler ordering
360 self:CreateBarTree(bar)
361 end
362 end
363
364 function Editor:OnDestroyBar(evt, bar, name)
365 local key = self.barOptMap[name]
366 if key then
367 self.options.args[key] = nil
368 end
369 self:Refresh()
370 end
371
372 function Editor:OnEraseBar(evt, name)
373 local key = self.barOptMap[name]
374 self.barOptMap[name] = nil
375 if key then
376 self.options.args[key] = nil
377 self:Refresh()
378 end
379 end
380
381 function Editor:OnRenameBar(evt, bar, oldname, newname)
382 local key = self.barOptMap[oldname]
383 self.barOptMap[oldname], self.barOptMap[newname] = nil, key
384 if key then
385 self.options.args[key].name = newname
386 self:Refresh()
387 end
388 end
389
390 local _scratch = { }
391 function Editor:GetBarTypes()
392 wipe(_scratch)
393 return ReAction:GetBarTypeOptions(_scratch)
394 end
395
396 function Editor:CreateBar()
397 if self.tmp.barName and self.tmp.barName ~= "" then
398 self.tmp.creating = true
399 local bar = ReAction:CreateBar(self.tmp.barName, self.tmp.barType or ReAction:GetDefaultBarType(), self.tmp.barRows, self.tmp.barCols, self.tmp.barSize, self.tmp.barSpacing)
400 if bar then
401 self:CreateBarTree(bar)
402 AceConfigDialog:SelectGroup(self.configID, self.barOptMap[self.tmp.barName])
403 self.tmp.barName = nil
404 end
405 self.tmp.creating = false
406 end
407 end
408
409 function Editor:GenerateBarOptionsTable( bar )
410 local opts = { }
411 if not ReAction.barOptionGenerators then
412 return
413 end
414
415 for module, func in pairs(ReAction.barOptionGenerators) do
416 local success, r
417 if type(func) == "string" then
418 success, r = pcall(module[func], module, bar)
419 else
420 success, r = pcall(func, bar)
421 end
422 if success then
423 if r then
424 opts[module:GetName()] = { [module:GetName()] = r }
425 end
426 else
427 geterrorhandler()(r)
428 end
429 end
430 return opts
431 end
432
433
434
435 ---- Export to ReAction ----
436 function ReAction:ShowEditor(bar, ...)
437 if InCombatLockdown() then
438 self:UserError(L["ReAction config mode disabled during combat."])
439 else
440 self.editor = self.editor or Editor:New()
441 self.editor:Open(bar, ...)
442 self:SetConfigMode(true)
443 end
444 end
445
446 function ReAction:CloseEditor()
447 if self.editor then
448 self.editor:Close()
449 end
450 end
451
452 function ReAction:RefreshEditor()
453 if self.editor then
454 self.editor:RefreshBarOptions()
455 end
456 end
457
458 function ReAction:RegisterBarOptionGenerator( module, func )
459 if not module or type(module) ~= "table" then -- doesn't need to be a proper module, strictly
460 error("ReAction:RegisterBarOptionGenerator() : Invalid module")
461 end
462 if type(func) == "string" then
463 if not module[func] then
464 error(("ReAction:RegisterBarOptionGenerator() : Invalid method '%s'"):format(func))
465 end
466 elseif func and type(func) ~= "function" then
467 error("ReAction:RegisterBarOptionGenerator() : Invalid function")
468 end
469 self.barOptionGenerators = self.barOptionGenerators or { }
470 self.barOptionGenerators[module] = func
471
472 if self.editor then
473 self.editor:RefreshBarOptions()
474 end
475 end
476