annotate modules/ReAction_ConfigUI/ReAction_ConfigUI.lua @ 47:e12b736c23c3

Added Layout Editor
author Flick <flickerstreak@gmail.com>
date Fri, 11 Apr 2008 22:21:28 +0000
parents aa0b7fd68462
children 7b7d178dec52
rev   line source
flickerstreak@25 1 --[[
flickerstreak@25 2 ReAction Configuration UI module
flickerstreak@25 3
flickerstreak@33 4 Hooks into Blizzard Interface Options AddOns panel
flickerstreak@25 5 --]]
flickerstreak@25 6
flickerstreak@25 7 -- local imports
flickerstreak@25 8 local ReAction = ReAction
flickerstreak@25 9 local L = ReAction.L
flickerstreak@47 10 local AceConfigReg = LibStub("AceConfigRegistry-3.0")
flickerstreak@47 11 local AceConfigDialog = LibStub("AceConfigDialog-3.0")
flickerstreak@25 12
flickerstreak@25 13 -- module declaration
flickerstreak@25 14 local moduleID = "ConfigUI"
flickerstreak@47 15 local module = ReAction:NewModule( moduleID,
flickerstreak@47 16 "AceEvent-3.0"
flickerstreak@47 17 )
flickerstreak@25 18
flickerstreak@25 19 -- module methods
flickerstreak@25 20 function module:OnInitialize()
flickerstreak@47 21 self.db = ReAction.db:RegisterNamespace( moduleID,
flickerstreak@47 22 {
flickerstreak@47 23 profile = {
flickerstreak@47 24 closeOnLaunch = true,
flickerstreak@47 25 editorCloseOnLaunch = true,
flickerstreak@47 26 }
flickerstreak@47 27 }
flickerstreak@47 28 )
flickerstreak@47 29
flickerstreak@30 30 ReAction.RegisterCallback(self,"OnOptionsRegistered")
flickerstreak@33 31 ReAction.RegisterCallback(self,"OnOptionsRefreshed")
flickerstreak@47 32 ReAction.RegisterCallback(self,"OnCreateBar")
flickerstreak@47 33 ReAction.RegisterCallback(self,"OnEraseBar")
flickerstreak@47 34 ReAction.RegisterCallback(self,"OnRenameBar")
flickerstreak@46 35 self:InitializeOptions()
flickerstreak@47 36 self:RegisterEvent("PLAYER_REGEN_DISABLED")
flickerstreak@25 37 end
flickerstreak@25 38
flickerstreak@30 39 function module:OnOptionsRegistered(evt, context, module, opts)
flickerstreak@46 40 local c = self.configOptions.args[context]
flickerstreak@46 41 if c then
flickerstreak@30 42 for k, v in pairs(opts) do
flickerstreak@46 43 c.args[k] = v
flickerstreak@30 44 end
flickerstreak@47 45 elseif c == "bar" then
flickerstreak@47 46
flickerstreak@30 47 end
flickerstreak@25 48 end
flickerstreak@25 49
flickerstreak@33 50 function module:OnOptionsRefreshed(evt)
flickerstreak@33 51 -- TODO: refresh options frame (just OpenConfig again?)
flickerstreak@25 52 end
flickerstreak@25 53
flickerstreak@47 54 function module:OnCreateBar(evt, bar)
flickerstreak@47 55 local name = bar:GetName()
flickerstreak@47 56 -- AceConfig doesn't allow spaces, etc, in arg key names, and they must be
flickerstreak@47 57 -- unique strings. So generate a unique key (it can be whatever) for the bar
flickerstreak@47 58 local key
flickerstreak@47 59 local i = 1
flickerstreak@47 60 repeat
flickerstreak@47 61 key = ("bar%s"):format(i)
flickerstreak@47 62 i = i+1
flickerstreak@47 63 until self.layoutOpts.args[key] == nil
flickerstreak@47 64 self.barOptMap[name] = key
flickerstreak@47 65 self.layoutOpts.args[key] = {
flickerstreak@47 66 type = "group",
flickerstreak@47 67 name = name,
flickerstreak@47 68 childGroups = "tab",
flickerstreak@47 69 args = {
flickerstreak@47 70 general = {
flickerstreak@47 71 type = "group",
flickerstreak@47 72 name = L["General"],
flickerstreak@47 73 args = {
flickerstreak@47 74 name = {
flickerstreak@47 75 type = "input",
flickerstreak@47 76 name = L["Rename Bar"],
flickerstreak@47 77 get = function() return bar:GetName() end,
flickerstreak@47 78 set = function(info, value) return ReAction:RenameBar(bar, value) end,
flickerstreak@47 79 order = 1,
flickerstreak@47 80 },
flickerstreak@47 81 delete = {
flickerstreak@47 82 type = "execute",
flickerstreak@47 83 name = L["Delete Bar"],
flickerstreak@47 84 desc = function() return bar:GetName() end,
flickerstreak@47 85 confirm = true,
flickerstreak@47 86 func = function() ReAction:EraseBar(bar) end,
flickerstreak@47 87 order = -1
flickerstreak@47 88 },
flickerstreak@47 89
flickerstreak@47 90 }
flickerstreak@47 91 },
flickerstreak@47 92 },
flickerstreak@47 93
flickerstreak@47 94 }
flickerstreak@47 95 end
flickerstreak@47 96
flickerstreak@47 97 function module:OnEraseBar(evt, name)
flickerstreak@47 98 local key = self.barOptMap[name]
flickerstreak@47 99 self.barOptMap[name] = nil
flickerstreak@47 100 if key then
flickerstreak@47 101 self.layoutOpts.args[key] = nil
flickerstreak@47 102 self:RefreshLayoutEditor()
flickerstreak@25 103 end
flickerstreak@25 104 end
flickerstreak@44 105
flickerstreak@47 106 function module:OnRenameBar(evt, oldname, newname)
flickerstreak@47 107 local key = self.barOptMap[oldname]
flickerstreak@47 108 self.barOptMap[oldname], self.barOptMap[newname] = nil, key
flickerstreak@47 109 if key then
flickerstreak@47 110 self.layoutOpts.args[key].name = newname
flickerstreak@47 111 self:RefreshLayoutEditor()
flickerstreak@47 112 end
flickerstreak@47 113 end
flickerstreak@47 114
flickerstreak@47 115 function module:PLAYER_REGEN_DISABLED()
flickerstreak@47 116 if self.editor then
flickerstreak@47 117 self.editor:Hide()
flickerstreak@47 118 end
flickerstreak@47 119 end
flickerstreak@47 120
flickerstreak@47 121 function module:UserError(msg)
flickerstreak@47 122 -- any user errors should be flashed to the UIErrorsFrame
flickerstreak@47 123 UIErrorsFrame:AddMessage(msg)
flickerstreak@47 124 end
flickerstreak@47 125
flickerstreak@47 126 function module:OpenConfig()
flickerstreak@47 127 InterfaceOptionsFrame_OpenToFrame("ReAction")
flickerstreak@47 128 end
flickerstreak@47 129
flickerstreak@47 130 function module:LaunchLayoutEditor(bar)
flickerstreak@47 131 if InCombatLockdown() then
flickerstreak@47 132 self:UserError(L["ReAction config mode disabled during combat."])
flickerstreak@47 133 else
flickerstreak@47 134 if not self.editor then
flickerstreak@47 135 -- use a local container to work around AceConfigDialog closing
flickerstreak@47 136 -- both the layout editor and the global options when interface options is closed
flickerstreak@47 137 local ed = LibStub("AceGUI-3.0"):Create("Frame")
flickerstreak@47 138 ed.frame:SetClampedToScreen(true)
flickerstreak@47 139 local old_OnUpdate = ed.frame:GetScript("OnUpdate")
flickerstreak@47 140 ed.frame:SetScript("OnUpdate", function(dt)
flickerstreak@47 141 if old_OnUpdate then
flickerstreak@47 142 old_OnUpdate(dt)
flickerstreak@47 143 end
flickerstreak@47 144 if ed.closePending then
flickerstreak@47 145 InterfaceOptionsFrame:Hide()
flickerstreak@47 146 ed.closePending = false
flickerstreak@47 147 end
flickerstreak@47 148 if ed.selfClosePending then
flickerstreak@47 149 ed:Hide()
flickerstreak@47 150 AceConfigReg:NotifyChange("ReAction")
flickerstreak@47 151 ed.selfClosePending = false
flickerstreak@47 152 end
flickerstreak@47 153 end )
flickerstreak@47 154 ed:SetCallback("OnClose",
flickerstreak@47 155 function()
flickerstreak@47 156 ReAction:SetConfigMode(false)
flickerstreak@47 157 end )
flickerstreak@47 158 self.editor = ed
flickerstreak@47 159 AceConfigDialog:SetDefaultSize("ReAction-Layout", 600, 450)
flickerstreak@47 160 end
flickerstreak@47 161
flickerstreak@47 162 AceConfigDialog:Open("ReAction-Layout", self.editor)
flickerstreak@47 163 ReAction:SetConfigMode(true)
flickerstreak@47 164 end
flickerstreak@47 165 end
flickerstreak@47 166
flickerstreak@47 167 function module:RefreshLayoutEditor()
flickerstreak@47 168 AceConfigReg:NotifyChange("ReAction-Layout")
flickerstreak@47 169 if self.editor and self.editor.frame:IsShown() then
flickerstreak@47 170 AceConfigDialog:Open("ReAction-Layout", self.editor)
flickerstreak@47 171 end
flickerstreak@47 172 end
flickerstreak@47 173
flickerstreak@47 174 function module:GetBarTypes()
flickerstreak@47 175 local opts = self.optBarTypes or { }
flickerstreak@47 176 self.optBarTypes = opts
flickerstreak@47 177
flickerstreak@47 178 -- TODO: get these from module registration somehow
flickerstreak@47 179 opts[1] = "foo"
flickerstreak@47 180
flickerstreak@47 181 return opts
flickerstreak@47 182 end
flickerstreak@47 183
flickerstreak@47 184 function module:CreateBar()
flickerstreak@47 185 local name = self.tmpBarName
flickerstreak@47 186 local type = self.tmpBarType
flickerstreak@47 187
flickerstreak@47 188 self.tmpBarName = nil
flickerstreak@47 189 self.tmpBarType = nil
flickerstreak@47 190
flickerstreak@47 191 -- TODO: get from module registration
flickerstreak@47 192 -- TODO: use rows/cols info
flickerstreak@47 193 ReAction:CreateBar(name)
flickerstreak@47 194 end
flickerstreak@47 195
flickerstreak@46 196 function module:InitializeOptions()
flickerstreak@47 197 -- general config options
flickerstreak@47 198 local opts = {
flickerstreak@46 199 type = "group",
flickerstreak@47 200 name = "ReAction",
flickerstreak@46 201 childGroups = "tab",
flickerstreak@46 202 args = {
flickerstreak@47 203 _desc = {
flickerstreak@47 204 type = "description",
flickerstreak@47 205 name = L["Customizable replacement for Blizzard's Action Bars"],
flickerstreak@47 206 order = 1,
flickerstreak@47 207 },
flickerstreak@47 208 _launchLayout = {
flickerstreak@47 209 type = "execute",
flickerstreak@47 210 handler = self,
flickerstreak@47 211 name = L["Layout Editor..."],
flickerstreak@47 212 desc = L["Show the ReAction Layout Editor to edit your bars"],
flickerstreak@47 213 func = function()
flickerstreak@47 214 self:LaunchLayoutEditor()
flickerstreak@47 215 -- you can't close a dialog in response to an options click, because the end of the
flickerstreak@47 216 -- handler for all the button events calls lib:Open()
flickerstreak@47 217 -- So, schedule a close on the next OnUpdate
flickerstreak@47 218 if self.db.profile.closeOnLaunch then
flickerstreak@47 219 self.editor.closePending = true
flickerstreak@47 220 end
flickerstreak@47 221 end,
flickerstreak@47 222 order = 2,
flickerstreak@47 223 },
flickerstreak@47 224 _closeThis = {
flickerstreak@47 225 type = "toggle",
flickerstreak@47 226 name = L["Close on Launch"],
flickerstreak@47 227 desc = L["Close the Interface Options window when launching the ReAction Layout Editor"],
flickerstreak@47 228 get = function() return self.db.profile.closeOnLaunch end,
flickerstreak@47 229 set = function(info, val) self.db.profile.closeOnLaunch = val end,
flickerstreak@47 230 order = 3,
flickerstreak@47 231 },
flickerstreak@46 232 global = {
flickerstreak@46 233 type = "group",
flickerstreak@46 234 name = L["Global Settings"],
flickerstreak@46 235 desc = L["Global configuration settings"],
flickerstreak@46 236 args = { },
flickerstreak@47 237 order = 3,
flickerstreak@46 238 },
flickerstreak@47 239 _profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(ReAction.db),
flickerstreak@46 240 module = {
flickerstreak@46 241 type = "group",
flickerstreak@46 242 childGroups = "select",
flickerstreak@46 243 name = L["Module Settings"],
flickerstreak@46 244 desc = L["Configuration settings for each module"],
flickerstreak@46 245 args = { },
flickerstreak@46 246 order = -1,
flickerstreak@46 247 },
flickerstreak@46 248 },
flickerstreak@46 249 plugins = { }
flickerstreak@46 250 }
flickerstreak@47 251 self.configOptions = opts
flickerstreak@47 252 opts.args._profile.order = -2
flickerstreak@47 253 AceConfigReg:RegisterOptionsTable("ReAction",opts)
flickerstreak@47 254 self.frame = AceConfigDialog:AddToBlizOptions("ReAction", "ReAction")
flickerstreak@47 255 self.frame.obj:SetCallback("default",
flickerstreak@47 256 function()
flickerstreak@47 257 ReAction.db:ResetProfile()
flickerstreak@47 258 module:OpenConfig()
flickerstreak@47 259 end )
flickerstreak@46 260
flickerstreak@47 261 -- import options from registered modules
flickerstreak@47 262 for c, tbl in pairs(opts.args) do
flickerstreak@46 263 for _, m in pairs(ReAction:GetOptions(c)) do
flickerstreak@46 264 for k, v in pairs(m) do
flickerstreak@46 265 tbl.args[k] = v
flickerstreak@46 266 end
flickerstreak@46 267 end
flickerstreak@46 268 end
flickerstreak@46 269
flickerstreak@46 270 ReAction:RegisterOptions("module",self, {
flickerstreak@46 271 configUI = {
flickerstreak@46 272 type = "group",
flickerstreak@46 273 name = "Config UI",
flickerstreak@46 274 desc = "description",
flickerstreak@46 275 args = {
flickerstreak@46 276 foo = {
flickerstreak@46 277 type = "toggle",
flickerstreak@46 278 handler = self,
flickerstreak@46 279 name = "foo",
flickerstreak@46 280 desc = "description",
flickerstreak@46 281 get = function() return true end,
flickerstreak@46 282 set = function() end,
flickerstreak@46 283 }
flickerstreak@46 284 }
flickerstreak@46 285 },
flickerstreak@46 286 })
flickerstreak@46 287
flickerstreak@47 288 -- layout editor options
flickerstreak@47 289 local layoutOpts = {
flickerstreak@47 290 type = "group",
flickerstreak@47 291 name = ("ReAction - %s"):format(L["Layout"]),
flickerstreak@47 292 handler = self,
flickerstreak@47 293 childGroups = "tree",
flickerstreak@47 294 args = {
flickerstreak@47 295 desc = {
flickerstreak@47 296 type = "description",
flickerstreak@47 297 name = L["Use the mouse to arrange and resize the bars on screen. Tooltips on bars indicate additional functionality."],
flickerstreak@47 298 order = 1
flickerstreak@47 299 },
flickerstreak@47 300 launchConfig = {
flickerstreak@47 301 type = "execute",
flickerstreak@47 302 name = L["Global Config"],
flickerstreak@47 303 desc = L["Opens ReAction global configuration settings panel"],
flickerstreak@47 304 func = function()
flickerstreak@47 305 self:OpenConfig()
flickerstreak@47 306 -- you can't close a dialog in response to an options click, because the end of the
flickerstreak@47 307 -- handler for all the button events calls lib:Open()
flickerstreak@47 308 -- So, schedule a close on the next appropriate event
flickerstreak@47 309 if self.db.profile.editorCloseOnLaunch then
flickerstreak@47 310 self.editor.selfClosePending = true
flickerstreak@47 311 end
flickerstreak@47 312 end,
flickerstreak@47 313 order = 2
flickerstreak@47 314 },
flickerstreak@47 315 closThis = {
flickerstreak@47 316 type = "toggle",
flickerstreak@47 317 name = L["Close on Launch"],
flickerstreak@47 318 desc = L["Close the Layout Editor when opening the ReAction global Interface Options"],
flickerstreak@47 319 get = function() return self.db.profile.editorCloseOnLaunch end,
flickerstreak@47 320 set = function(info, val) self.db.profile.editorCloseOnLaunch = val end,
flickerstreak@47 321 order = 3,
flickerstreak@47 322 },
flickerstreak@47 323 new = {
flickerstreak@47 324 type = "group",
flickerstreak@47 325 name = L["New Bar..."],
flickerstreak@47 326 order = 4,
flickerstreak@47 327 args = {
flickerstreak@47 328 desc = {
flickerstreak@47 329 type = "description",
flickerstreak@47 330 name = L["Choose a name, type, and initial grid for your new action bar:"],
flickerstreak@47 331 order = 1,
flickerstreak@47 332 },
flickerstreak@47 333 name = {
flickerstreak@47 334 type = "input",
flickerstreak@47 335 name = L["Bar Name"],
flickerstreak@47 336 desc = L["Enter a name for your new action bar"],
flickerstreak@47 337 get = function() return self.tmpBarName or "" end,
flickerstreak@47 338 set = function(info, val) self.tmpBarName = val end,
flickerstreak@47 339 order = 2,
flickerstreak@47 340 },
flickerstreak@47 341 type = {
flickerstreak@47 342 type = "select",
flickerstreak@47 343 name = L["Button Type"],
flickerstreak@47 344 get = function() return self.tmpBarType or "" end,
flickerstreak@47 345 set = function(info, val) self.tmpBarType = val end,
flickerstreak@47 346 values = "GetBarTypes",
flickerstreak@47 347 order = 3,
flickerstreak@47 348 },
flickerstreak@47 349 grid = {
flickerstreak@47 350 type = "group",
flickerstreak@47 351 name = L["Button Grid"],
flickerstreak@47 352 inline = true,
flickerstreak@47 353 args = {
flickerstreak@47 354 hdr = {
flickerstreak@47 355 type = "header",
flickerstreak@47 356 name = L["Button Grid"],
flickerstreak@47 357 order = 1,
flickerstreak@47 358 },
flickerstreak@47 359 rows = {
flickerstreak@47 360 type = "range",
flickerstreak@47 361 name = L["Rows"],
flickerstreak@47 362 get = function() return self.tmpBarRows or 1 end,
flickerstreak@47 363 set = function(info, val) self.tmpBarRows = val end,
flickerstreak@47 364 width = "half",
flickerstreak@47 365 min = 1,
flickerstreak@47 366 max = 32,
flickerstreak@47 367 step = 1,
flickerstreak@47 368 order = 2,
flickerstreak@47 369 },
flickerstreak@47 370 cols = {
flickerstreak@47 371 type = "range",
flickerstreak@47 372 name = L["Columns"],
flickerstreak@47 373 get = function() return self.tmpBarCols or 12 end,
flickerstreak@47 374 set = function(info, val) self.tmpBarCols = val end,
flickerstreak@47 375 width = "half",
flickerstreak@47 376 min = 1,
flickerstreak@47 377 max = 32,
flickerstreak@47 378 step = 1,
flickerstreak@47 379 order = 3,
flickerstreak@47 380 },
flickerstreak@47 381 sz = {
flickerstreak@47 382 type = "range",
flickerstreak@47 383 name = L["Size"],
flickerstreak@47 384 get = function() return self.tmpBarSize or 36 end,
flickerstreak@47 385 set = function(info, val) self.tmpBarSize = val end,
flickerstreak@47 386 width = "half",
flickerstreak@47 387 min = 10,
flickerstreak@47 388 max = 72,
flickerstreak@47 389 step = 1,
flickerstreak@47 390 order = 4,
flickerstreak@47 391 },
flickerstreak@47 392 spacing = {
flickerstreak@47 393 type = "range",
flickerstreak@47 394 name = L["Spacing"],
flickerstreak@47 395 get = function() return self.tmpBarSpacing or 3 end,
flickerstreak@47 396 set = function(info, val) self.tmpBarSpacing = val end,
flickerstreak@47 397 width = "half",
flickerstreak@47 398 min = 0,
flickerstreak@47 399 max = 24,
flickerstreak@47 400 step = 1,
flickerstreak@47 401 order = 5,
flickerstreak@47 402 }
flickerstreak@47 403 },
flickerstreak@47 404 order = 4
flickerstreak@47 405 },
flickerstreak@47 406 spacer = {
flickerstreak@47 407 type = "header",
flickerstreak@47 408 name = "",
flickerstreak@47 409 width = "full",
flickerstreak@47 410 order = -2
flickerstreak@47 411 },
flickerstreak@47 412 go = {
flickerstreak@47 413 type = "execute",
flickerstreak@47 414 name = L["Create Bar"],
flickerstreak@47 415 func = "CreateBar",
flickerstreak@47 416 order = -1,
flickerstreak@47 417 }
flickerstreak@47 418 }
flickerstreak@47 419 }
flickerstreak@47 420 }
flickerstreak@47 421 }
flickerstreak@47 422 self.layoutOpts = layoutOpts
flickerstreak@47 423 self.barOptMap = { }
flickerstreak@47 424 AceConfigReg:RegisterOptionsTable("ReAction-Layout",layoutOpts)
flickerstreak@44 425 end
flickerstreak@44 426