annotate ReAction.lua @ 184:1ee86bbb05a0

more options rearranging
author Flick <flickerstreak@gmail.com>
date Fri, 22 Oct 2010 16:03:04 +0000
parents 55c2fc0c8d55
children 2e7a322e0195
rev   line source
flickerstreak@63 1 --[[
flickerstreak@63 2 ReAction.lua
flickerstreak@63 3
flickerstreak@182 4 The ReAction core manages several collections:
flickerstreak@63 5 - modules (via AceAddon)
flickerstreak@63 6 - bars
flickerstreak@182 7 - bar options
flickerstreak@63 8 - bar-type constructors
flickerstreak@63 9
flickerstreak@90 10 and publishes events when those collections change. It also implements a couple properties
flickerstreak@63 11 and has a couple convenience methods which drill down to particular modules.
flickerstreak@63 12
flickerstreak@90 13 Most of the "real work" of the addon happens in Bar.lua, Overlay.lua, State.lua, and the various modules.
flickerstreak@63 14
flickerstreak@63 15 Events (with handler arguments):
flickerstreak@63 16 --------------------------------
flickerstreak@63 17 "OnCreateBar" (bar, name) : after a bar object is created
flickerstreak@63 18 "OnDestroyBar" (bar, name) : before a bar object is destroyed
flickerstreak@63 19 "OnEraseBar" (bar, name) : before a bar config is removed from the profile db
flickerstreak@63 20 "OnRenameBar" (bar, oldname, newname) : after a bar is renamed
flickerstreak@63 21 "OnRefreshBar" (bar, name) : after a bar's state has been updated
flickerstreak@63 22 "OnOptionsRefreshed" () : after the global options tree is refreshed
flickerstreak@63 23 "OnConfigModeChanged" (mode) : after the config mode is changed
flickerstreak@63 24 "OnBarOptionGeneratorRegistered" (module, function) : after an options generator function is registered
flickerstreak@63 25
flickerstreak@63 26 ReAction is also an AceAddon-3.0 and contains an AceDB-3.0, which in turn publish more events.
flickerstreak@63 27 ]]--
flickerstreak@182 28 local addonName, addonTable = ...
flickerstreak@182 29 local ReAction = LibStub("AceAddon-3.0"):NewAddon( addonName,
flickerstreak@33 30 "AceEvent-3.0"
flickerstreak@30 31 )
flickerstreak@184 32 ReAction.version = GetAddOnMetadata(addonName,"Version")
flickerstreak@175 33 addonTable.ReAction = ReAction
flickerstreak@27 34
flickerstreak@33 35 ------ LIBRARIES ------
flickerstreak@63 36 local callbacks = LibStub("CallbackHandler-1.0"):New(ReAction)
flickerstreak@184 37 local LKB = LibStub("LibKeyBound-1.0")
flickerstreak@33 38 local L = LibStub("AceLocale-3.0"):GetLocale("ReAction")
flickerstreak@33 39 ReAction.L = L
flickerstreak@184 40 ReAction.LKB = LKB
flickerstreak@182 41 ReAction.callbacks = callbacks
flickerstreak@33 42
flickerstreak@28 43 ------ PRIVATE ------
flickerstreak@116 44 local private = { }
flickerstreak@63 45 local bars = {}
flickerstreak@63 46 local defaultBarConfig = {}
flickerstreak@63 47 local barOptionGenerators = { }
flickerstreak@63 48
flickerstreak@116 49
flickerstreak@182 50 local SelectBar, DestroyBar, InitializeBars, TearDownBars, DeepCopy, CallModuleMethod
flickerstreak@28 51 do
flickerstreak@28 52 local pcall = pcall
flickerstreak@28 53 local geterrorhandler = geterrorhandler
flickerstreak@63 54 local self = ReAction
flickerstreak@63 55 local inited = false
flickerstreak@28 56
flickerstreak@63 57 function SelectBar(x)
flickerstreak@28 58 local bar, name
flickerstreak@28 59 if type(x) == "string" then
flickerstreak@28 60 name = x
flickerstreak@63 61 bar = self:GetBar(name)
flickerstreak@50 62 else
flickerstreak@63 63 for k,v in pairs(bars) do
flickerstreak@50 64 if v == x then
flickerstreak@28 65 name = k
flickerstreak@50 66 bar = x
flickerstreak@28 67 end
flickerstreak@28 68 end
flickerstreak@28 69 end
flickerstreak@28 70 return bar, name
flickerstreak@28 71 end
flickerstreak@28 72
flickerstreak@63 73 function DestroyBar(x)
flickerstreak@28 74 local bar, name = SelectBar(x)
flickerstreak@63 75 if bar and name then
flickerstreak@63 76 bars[name] = nil
flickerstreak@63 77 callbacks:Fire("OnDestroyBar", bar, name)
flickerstreak@28 78 bar:Destroy()
flickerstreak@28 79 end
flickerstreak@28 80 end
flickerstreak@28 81
flickerstreak@63 82 function InitializeBars()
flickerstreak@63 83 if not inited then
flickerstreak@63 84 for name, config in pairs(self.db.profile.bars) do
flickerstreak@28 85 if config then
flickerstreak@63 86 self:CreateBar(name, config)
flickerstreak@28 87 end
flickerstreak@28 88 end
flickerstreak@101 89 -- re-anchor and refresh in case anchor order does not match init order
flickerstreak@63 90 for name, bar in pairs(bars) do
flickerstreak@63 91 bar:ApplyAnchor()
flickerstreak@101 92 callbacks:Fire("OnRefreshBar", bar, name)
flickerstreak@63 93 end
flickerstreak@63 94 inited = true
flickerstreak@28 95 end
flickerstreak@28 96 end
flickerstreak@28 97
flickerstreak@63 98 function TearDownBars()
flickerstreak@63 99 for name, bar in pairs(bars) do
flickerstreak@28 100 if bar then
flickerstreak@63 101 bars[name] = DestroyBar(bar)
flickerstreak@28 102 end
flickerstreak@28 103 end
flickerstreak@63 104 inited = false
flickerstreak@28 105 end
flickerstreak@28 106
flickerstreak@63 107 function DeepCopy(x)
flickerstreak@28 108 if type(x) ~= "table" then
flickerstreak@28 109 return x
flickerstreak@28 110 end
flickerstreak@28 111 local r = {}
flickerstreak@28 112 for k,v in pairs(x) do
flickerstreak@28 113 r[k] = DeepCopy(v)
flickerstreak@28 114 end
flickerstreak@28 115 return r
flickerstreak@28 116 end
flickerstreak@28 117
flickerstreak@63 118 function CallModuleMethod(modulename, method, ...)
flickerstreak@63 119 local m = self:GetModule(modulename,true)
flickerstreak@63 120 if m then
flickerstreak@63 121 if type(m) == "table" and type(m[method]) == "function" then
flickerstreak@63 122 m[method](m,...)
flickerstreak@63 123 end
flickerstreak@30 124 end
flickerstreak@30 125 end
flickerstreak@92 126
flickerstreak@28 127 end
flickerstreak@28 128
flickerstreak@28 129
flickerstreak@28 130 ------ HANDLERS ------
flickerstreak@28 131 function ReAction:OnInitialize()
flickerstreak@28 132 self.db = LibStub("AceDB-3.0"):New("ReAction_DB",
flickerstreak@28 133 {
flickerstreak@28 134 profile = {
flickerstreak@28 135 bars = { },
flickerstreak@184 136 defaultBar = { },
flickerstreak@184 137 closeOptionsOnEditorLaunch = true,
flickerstreak@28 138 }
flickerstreak@111 139 },
flickerstreak@182 140 true -- use global 'Default' (locale-specific)
flickerstreak@28 141 )
flickerstreak@184 142 LKB.RegisterCallback(self,"LIBKEYBOUND_ENABLED")
flickerstreak@184 143 LKB.RegisterCallback(self,"LIBKEYBOUND_DISABLED")
flickerstreak@88 144
flickerstreak@182 145 self:RegisterEvent("PLAYER_REGEN_DISABLED")
flickerstreak@63 146
flickerstreak@182 147 self:InitializeOptions()
flickerstreak@28 148 end
flickerstreak@28 149
flickerstreak@28 150 function ReAction:OnEnable()
flickerstreak@28 151 InitializeBars()
flickerstreak@28 152 end
flickerstreak@28 153
flickerstreak@28 154 function ReAction:OnDisable()
flickerstreak@28 155 TearDownBars()
flickerstreak@28 156 end
flickerstreak@28 157
flickerstreak@33 158 function ReAction:PLAYER_REGEN_DISABLED()
flickerstreak@63 159 if private.configMode == true then
flickerstreak@63 160 self:UserError(L["ReAction config mode disabled during combat."])
flickerstreak@33 161 self:SetConfigMode(false)
flickerstreak@88 162 self:SetKeybindMode(false)
flickerstreak@33 163 end
flickerstreak@33 164 end
flickerstreak@33 165
flickerstreak@88 166 function ReAction:LIBKEYBOUND_ENABLED( evt )
flickerstreak@88 167 self:SetKeybindMode(true)
flickerstreak@88 168 end
flickerstreak@88 169
flickerstreak@88 170 function ReAction:LIBKEYBOUND_DISABLED( evt )
flickerstreak@88 171 return self:SetKeybindMode(false)
flickerstreak@88 172 end
flickerstreak@88 173
flickerstreak@33 174
flickerstreak@28 175
flickerstreak@28 176 ------ API ------
flickerstreak@77 177
flickerstreak@61 178 function ReAction:UserError(msg)
flickerstreak@61 179 -- any user errors should be flashed to the UIErrorsFrame
flickerstreak@61 180 UIErrorsFrame:AddMessage(msg)
flickerstreak@61 181 end
flickerstreak@61 182
flickerstreak@184 183 function ReAction:RebuildAll()
flickerstreak@184 184 TearDownBars()
flickerstreak@184 185 InitializeBars()
flickerstreak@184 186 end
flickerstreak@184 187
flickerstreak@184 188
flickerstreak@63 189 -- usage:
flickerstreak@91 190 -- (1) ReAction:CreateBar(name, [cfgTable])
flickerstreak@63 191 -- (2) ReAction:CreateBar(name, "barType", [nRows], [nCols], [btnSize], [btnSpacing])
flickerstreak@91 192 function ReAction:CreateBar(name, config, ...)
flickerstreak@91 193 local profile = self.db.profile
flickerstreak@91 194
flickerstreak@127 195 if name then
flickerstreak@127 196 if bars[name] then
flickerstreak@127 197 self:UserError(format(L["ReAction: name '%s' already in use"],name))
flickerstreak@127 198 return nil
flickerstreak@127 199 end
flickerstreak@127 200 else
flickerstreak@91 201 local prefix = L["Bar "]
flickerstreak@91 202 local i = 1
flickerstreak@91 203 repeat
flickerstreak@91 204 name = prefix..i
flickerstreak@91 205 i = i + 1
flickerstreak@91 206 until bars[name] == nil
flickerstreak@91 207 end
flickerstreak@91 208
flickerstreak@91 209 if type(config) == "string" then
flickerstreak@91 210 config = defaultBarConfig[config]
flickerstreak@48 211 if not config then
flickerstreak@91 212 error(("ReAction:CreateBar() - unknown bar type '%s'"):format(tostring(select(1,...))))
flickerstreak@48 213 end
flickerstreak@48 214 config = DeepCopy(config)
flickerstreak@91 215 config.btnRows = select(1,...) or config.btnRows or 1
flickerstreak@91 216 config.btnColumns = select(2,...) or config.btnColumns or 12
flickerstreak@91 217 config.btnWidth = select(3,...) or config.btnWidth or 36
flickerstreak@91 218 config.btnHeight = select(3,...) or config.btnHeight or 36
flickerstreak@91 219 config.spacing = select(4,...) or config.spacing or 3
flickerstreak@48 220 config.width = config.width or config.btnColumns*(config.btnWidth + config.spacing) + 1
flickerstreak@48 221 config.height = config.height or config.btnRows*(config.btnHeight + config.spacing) + 1
flickerstreak@81 222 config.anchor = config.anchor or "UIParent"
flickerstreak@81 223 config.point = config.point or "BOTTOM"
flickerstreak@81 224 config.relpoint = config.relpoint or "BOTTOM"
flickerstreak@48 225 config.y = config.y or 200
flickerstreak@48 226 config.x = config.x or 0
flickerstreak@48 227 end
flickerstreak@91 228 config = config or profile.bars[name] or DeepCopy(profile.defaultBar)
flickerstreak@91 229
flickerstreak@91 230 profile.bars[name] = config
flickerstreak@91 231 local bar = self.Bar:New( name, config ) -- ReAction.Bar defined in Bar.lua
flickerstreak@63 232 bars[name] = bar
flickerstreak@63 233 callbacks:Fire("OnCreateBar", bar, name)
flickerstreak@63 234 if private.configMode then
flickerstreak@33 235 bar:ShowControls(true)
flickerstreak@33 236 end
flickerstreak@33 237
flickerstreak@28 238 return bar
flickerstreak@28 239 end
flickerstreak@28 240
flickerstreak@28 241 function ReAction:EraseBar(x)
flickerstreak@28 242 local bar, name = SelectBar(x)
flickerstreak@63 243 if bar and name then
flickerstreak@63 244 callbacks:Fire("OnEraseBar", bar, name)
flickerstreak@28 245 DestroyBar(bar)
flickerstreak@28 246 self.db.profile.bars[name] = nil
flickerstreak@28 247 end
flickerstreak@28 248 end
flickerstreak@28 249
flickerstreak@28 250 function ReAction:GetBar(name)
flickerstreak@63 251 return bars[name]
flickerstreak@63 252 end
flickerstreak@63 253
flickerstreak@90 254 -- returns pairs of name, bar
flickerstreak@63 255 function ReAction:IterateBars()
flickerstreak@63 256 return pairs(bars)
flickerstreak@28 257 end
flickerstreak@28 258
flickerstreak@28 259 function ReAction:RenameBar(x, newname)
flickerstreak@28 260 local bar, name = SelectBar(x)
flickerstreak@63 261 if type(newname) ~= "string" then
flickerstreak@63 262 error("ReAction:RenameBar() - second argument must be a string")
flickerstreak@63 263 end
flickerstreak@63 264 if bar and name and #newname > 0 then
flickerstreak@127 265 if newname == name then
flickerstreak@127 266 return
flickerstreak@127 267 end
flickerstreak@63 268 if bars[newname] then
flickerstreak@127 269 self:UserError(format(L["ReAction: name '%s' already in use"],newname))
flickerstreak@47 270 else
flickerstreak@63 271 bars[newname], bars[name] = bars[name], nil
flickerstreak@47 272 bar:SetName(newname or "")
flickerstreak@47 273 local cfg = self.db.profile.bars
flickerstreak@47 274 cfg[newname], cfg[name] = cfg[name], nil
flickerstreak@63 275 callbacks:Fire("OnRenameBar", bar, name, newname)
flickerstreak@28 276 end
flickerstreak@28 277 end
flickerstreak@28 278 end
flickerstreak@28 279
flickerstreak@63 280 function ReAction:RefreshBar(x)
flickerstreak@63 281 local bar, name = SelectBar(x)
flickerstreak@63 282 if bar and name then
flickerstreak@63 283 callbacks:Fire("OnRefreshBar", bar, name)
flickerstreak@63 284 end
flickerstreak@63 285 end
flickerstreak@63 286
flickerstreak@53 287 function ReAction:RegisterBarType( name, config, isDefaultChoice )
flickerstreak@63 288 defaultBarConfig[name] = config
flickerstreak@48 289 if isDefaultChoice then
flickerstreak@81 290 private.defaultBarConfigChoice = name
flickerstreak@48 291 end
flickerstreak@48 292 self:RefreshOptions()
flickerstreak@48 293 end
flickerstreak@48 294
flickerstreak@53 295 function ReAction:UnregisterBarType( name )
flickerstreak@63 296 defaultBarConfig[name] = nil
flickerstreak@63 297 if private.defaultBarConfigChoice == name then
flickerstreak@63 298 private.defaultBarConfigChoice = nil
flickerstreak@48 299 end
flickerstreak@48 300 self:RefreshOptions()
flickerstreak@48 301 end
flickerstreak@48 302
flickerstreak@63 303 function ReAction:IterateBarTypes()
flickerstreak@63 304 return pairs(defaultBarConfig)
flickerstreak@63 305 end
flickerstreak@63 306
flickerstreak@63 307 function ReAction:GetBarTypeConfig(name)
flickerstreak@63 308 if name then
flickerstreak@63 309 return defaultBarConfig[name]
flickerstreak@63 310 end
flickerstreak@63 311 end
flickerstreak@63 312
flickerstreak@63 313 function ReAction:GetBarTypeOptions( fill )
flickerstreak@63 314 fill = fill or { }
flickerstreak@63 315 for k in self:IterateBarTypes() do
flickerstreak@63 316 fill[k] = k
flickerstreak@63 317 end
flickerstreak@63 318 return fill
flickerstreak@63 319 end
flickerstreak@63 320
flickerstreak@63 321 function ReAction:GetDefaultBarType()
flickerstreak@63 322 return private.defaultBarConfigChoice
flickerstreak@63 323 end
flickerstreak@63 324
flickerstreak@30 325 function ReAction:RefreshOptions()
flickerstreak@63 326 callbacks:Fire("OnOptionsRefreshed")
flickerstreak@63 327 end
flickerstreak@63 328
flickerstreak@63 329 --
flickerstreak@182 330 -- In addition to global options, options tables
flickerstreak@63 331 -- must be generated dynamically for each bar.
flickerstreak@63 332 --
flickerstreak@63 333 -- 'func' should be a function or a method string.
flickerstreak@63 334 -- The function or method will be passed the bar as its parameter.
flickerstreak@63 335 -- (methods will of course get the module as the first 'self' parameter)
flickerstreak@63 336 --
flickerstreak@63 337 -- A generator can be unregistered by passing a nil func.
flickerstreak@63 338 --
flickerstreak@63 339 function ReAction:RegisterBarOptionGenerator( module, func )
flickerstreak@63 340 if not module or type(module) ~= "table" then -- doesn't need to be a proper module, strictly
flickerstreak@63 341 error("ReAction:RegisterBarOptionGenerator() : Invalid module")
flickerstreak@63 342 end
flickerstreak@63 343 if type(func) == "string" then
flickerstreak@63 344 if not module[func] then
flickerstreak@63 345 error(("ReAction:RegisterBarOptionGenerator() : Invalid method '%s'"):format(func))
flickerstreak@63 346 end
flickerstreak@63 347 elseif func and type(func) ~= "function" then
flickerstreak@63 348 error("ReAction:RegisterBarOptionGenerator() : Invalid function")
flickerstreak@63 349 end
flickerstreak@63 350 barOptionGenerators[module] = func
flickerstreak@63 351 callbacks:Fire("OnBarOptionGeneratorRegistered", module, func)
flickerstreak@63 352 end
flickerstreak@63 353
flickerstreak@63 354 -- builds a table suitable for use as an AceConfig3 group 'plugins' sub-table
flickerstreak@63 355 function ReAction:GenerateBarOptionsTable( bar )
flickerstreak@63 356 local opts = { }
flickerstreak@63 357 for module, func in pairs(barOptionGenerators) do
flickerstreak@63 358 local success, r
flickerstreak@63 359 if type(func) == "string" then
flickerstreak@63 360 success, r = pcall(module[func], module, bar)
flickerstreak@63 361 else
flickerstreak@63 362 success, r = pcall(func, bar)
flickerstreak@63 363 end
flickerstreak@63 364 if success then
flickerstreak@90 365 if r then
flickerstreak@90 366 opts[module:GetName()] = { [module:GetName()] = r }
flickerstreak@90 367 end
flickerstreak@63 368 else
flickerstreak@63 369 geterrorhandler()(r)
flickerstreak@63 370 end
flickerstreak@63 371 end
flickerstreak@63 372 return opts
flickerstreak@30 373 end
flickerstreak@33 374
flickerstreak@33 375 function ReAction:SetConfigMode( mode )
flickerstreak@77 376 if mode ~= private.configMode then
flickerstreak@77 377 private.configMode = mode
flickerstreak@77 378 callbacks:Fire("OnConfigModeChanged", mode)
flickerstreak@77 379 end
flickerstreak@63 380 end
flickerstreak@63 381
flickerstreak@63 382 function ReAction:GetConfigMode()
flickerstreak@63 383 return private.configMode
flickerstreak@33 384 end
flickerstreak@38 385
flickerstreak@81 386 function ReAction:ShowEditor(bar, ...)
flickerstreak@81 387 CallModuleMethod("ConfigUI","LaunchBarEditor",bar, ...)
flickerstreak@47 388 end
flickerstreak@88 389
flickerstreak@88 390 function ReAction:SetKeybindMode( mode )
flickerstreak@88 391 if mode ~= private.kbMode then
flickerstreak@88 392 if mode then
flickerstreak@184 393 LKB:Activate()
flickerstreak@88 394 else
flickerstreak@184 395 LKB:Deactivate()
flickerstreak@88 396 end
flickerstreak@184 397 private.kbMode = LKB:IsShown() or false
flickerstreak@88 398 end
flickerstreak@88 399 end
flickerstreak@88 400
flickerstreak@88 401 function ReAction:GetKeybindMode( mode )
flickerstreak@88 402 return private.kbMode
flickerstreak@88 403 end