annotate Editor.lua @ 193:576c50e51fc5

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