annotate Editor.lua @ 194:55af1ebbec65

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