annotate ReAction.lua @ 127:29dacbecdb52

Fixed handling for making new bars with the same name
author Flick <flickerstreak@gmail.com>
date Wed, 04 Mar 2009 21:19:32 +0000
parents a2d2f23137c8
children 8cc187143acd
rev   line source
flickerstreak@63 1 --[[
flickerstreak@63 2 ReAction.lua
flickerstreak@63 3
flickerstreak@63 4 The ReAction core manages 4 collections:
flickerstreak@63 5 - modules (via AceAddon)
flickerstreak@63 6 - bars
flickerstreak@63 7 - 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@63 28 local version = GetAddOnMetadata("ReAction","Version")
flickerstreak@27 29
flickerstreak@27 30 ------ CORE ------
flickerstreak@30 31 local ReAction = LibStub("AceAddon-3.0"):NewAddon( "ReAction",
flickerstreak@33 32 "AceConsole-3.0",
flickerstreak@33 33 "AceEvent-3.0"
flickerstreak@30 34 )
flickerstreak@33 35 ReAction.revision = tonumber(("$Revision$"):match("%d+"))
flickerstreak@27 36
flickerstreak@28 37 ------ GLOBALS ------
flickerstreak@28 38 _G["ReAction"] = ReAction
flickerstreak@27 39
flickerstreak@28 40 ------ DEBUGGING ------
flickerstreak@25 41 ReAction.debug = true
flickerstreak@36 42 local dbprint
flickerstreak@25 43 if ReAction.debug then
flickerstreak@36 44 dbprint = function(msg)
flickerstreak@25 45 DEFAULT_CHAT_FRAME:AddMessage(msg)
flickerstreak@25 46 end
flickerstreak@25 47 else
flickerstreak@36 48 dbprint = function() end
flickerstreak@25 49 end
flickerstreak@36 50 ReAction.dbprint = dbprint
flickerstreak@25 51
flickerstreak@33 52 ------ LIBRARIES ------
flickerstreak@63 53 local callbacks = LibStub("CallbackHandler-1.0"):New(ReAction)
flickerstreak@88 54 local KB = LibStub("LibKeyBound-1.0")
flickerstreak@33 55 local L = LibStub("AceLocale-3.0"):GetLocale("ReAction")
flickerstreak@33 56 ReAction.L = L
flickerstreak@33 57
flickerstreak@28 58 ------ PRIVATE ------
flickerstreak@88 59 local weak = {__mode="k"}
flickerstreak@116 60 local private = { }
flickerstreak@63 61 local bars = {}
flickerstreak@63 62 local defaultBarConfig = {}
flickerstreak@63 63 local barOptionGenerators = { }
flickerstreak@63 64 local options = {
flickerstreak@63 65 type = "group",
flickerstreak@63 66 name = "ReAction",
flickerstreak@63 67 childGroups = "tab",
flickerstreak@63 68 args = {
flickerstreak@63 69 _desc = {
flickerstreak@63 70 type = "description",
flickerstreak@63 71 name = L["Customizable replacement for Blizzard's Action Bars"],
flickerstreak@63 72 order = 1,
flickerstreak@63 73 },
flickerstreak@63 74 global = {
flickerstreak@63 75 type = "group",
flickerstreak@63 76 name = L["Global Settings"],
flickerstreak@63 77 desc = L["Global configuration settings"],
flickerstreak@63 78 args = {
flickerstreak@63 79 unlock = {
flickerstreak@63 80 type = "toggle",
flickerstreak@63 81 name = L["Unlock Bars"],
flickerstreak@63 82 desc = L["Unlock bars for dragging and resizing with the mouse"],
flickerstreak@63 83 handler = ReAction,
flickerstreak@63 84 get = "GetConfigMode",
flickerstreak@63 85 set = function(info, value) ReAction:SetConfigMode(value) end,
flickerstreak@116 86 width = "double",
flickerstreak@63 87 disabled = InCombatLockdown,
flickerstreak@63 88 order = 1
flickerstreak@63 89 },
flickerstreak@116 90 skipProfileWarning = {
flickerstreak@116 91 type = "toggle",
flickerstreak@116 92 name = L["Skip profile keybind warning"],
flickerstreak@116 93 desc = L["Don't show a warning about updating keybinds when switching profiles"],
flickerstreak@116 94 get = function() return ReAction.db.global.skipKeybindWarning end,
flickerstreak@116 95 set = function(info, value) ReAction.db.global.skipKeybindWarning = value end,
flickerstreak@116 96 width = "double",
flickerstreak@116 97 order = 2,
flickerstreak@116 98 },
flickerstreak@63 99 },
flickerstreak@63 100 plugins = { },
flickerstreak@63 101 order = 2,
flickerstreak@63 102 },
flickerstreak@63 103 module = {
flickerstreak@63 104 type = "group",
flickerstreak@63 105 childGroups = "select",
flickerstreak@63 106 name = L["Module Settings"],
flickerstreak@63 107 desc = L["Configuration settings for each module"],
flickerstreak@63 108 args = { },
flickerstreak@63 109 plugins = { },
flickerstreak@63 110 order = 3,
flickerstreak@63 111 },
flickerstreak@63 112 },
flickerstreak@63 113 plugins = { }
flickerstreak@63 114 }
flickerstreak@63 115 ReAction.options = options
flickerstreak@63 116
flickerstreak@116 117 -- insert an entry into the WoW static popup dialogs list
flickerstreak@116 118 StaticPopupDialogs["REACTION_KB_WARN"] = {
flickerstreak@116 119 text = L["ReAction profile changed: check your keybinds, they may need to be updated."],
flickerstreak@116 120 button1 = L["OK"],
flickerstreak@116 121 hideOnEscape = true,
flickerstreak@116 122 enterClicksFirstButton = true,
flickerstreak@116 123 timeout = 0,
flickerstreak@116 124 showAlert = true,
flickerstreak@116 125 whileDead = true,
flickerstreak@116 126 }
flickerstreak@116 127
flickerstreak@116 128 local SelectBar, DestroyBar, InitializeBars, TearDownBars, DeepCopy, CallModuleMethod, SlashHandler
flickerstreak@28 129 do
flickerstreak@28 130 local pcall = pcall
flickerstreak@28 131 local geterrorhandler = geterrorhandler
flickerstreak@63 132 local self = ReAction
flickerstreak@63 133 local inited = false
flickerstreak@28 134
flickerstreak@63 135 function SelectBar(x)
flickerstreak@28 136 local bar, name
flickerstreak@28 137 if type(x) == "string" then
flickerstreak@28 138 name = x
flickerstreak@63 139 bar = self:GetBar(name)
flickerstreak@50 140 else
flickerstreak@63 141 for k,v in pairs(bars) do
flickerstreak@50 142 if v == x then
flickerstreak@28 143 name = k
flickerstreak@50 144 bar = x
flickerstreak@28 145 end
flickerstreak@28 146 end
flickerstreak@28 147 end
flickerstreak@28 148 return bar, name
flickerstreak@28 149 end
flickerstreak@28 150
flickerstreak@63 151 function DestroyBar(x)
flickerstreak@28 152 local bar, name = SelectBar(x)
flickerstreak@63 153 if bar and name then
flickerstreak@63 154 bars[name] = nil
flickerstreak@63 155 callbacks:Fire("OnDestroyBar", bar, name)
flickerstreak@28 156 bar:Destroy()
flickerstreak@28 157 end
flickerstreak@28 158 end
flickerstreak@28 159
flickerstreak@63 160 function InitializeBars()
flickerstreak@63 161 if not inited then
flickerstreak@63 162 for name, config in pairs(self.db.profile.bars) do
flickerstreak@28 163 if config then
flickerstreak@63 164 self:CreateBar(name, config)
flickerstreak@28 165 end
flickerstreak@28 166 end
flickerstreak@101 167 -- re-anchor and refresh in case anchor order does not match init order
flickerstreak@63 168 for name, bar in pairs(bars) do
flickerstreak@63 169 bar:ApplyAnchor()
flickerstreak@101 170 callbacks:Fire("OnRefreshBar", bar, name)
flickerstreak@63 171 end
flickerstreak@63 172 inited = true
flickerstreak@28 173 end
flickerstreak@28 174 end
flickerstreak@28 175
flickerstreak@63 176 function TearDownBars()
flickerstreak@63 177 for name, bar in pairs(bars) do
flickerstreak@28 178 if bar then
flickerstreak@63 179 bars[name] = DestroyBar(bar)
flickerstreak@28 180 end
flickerstreak@28 181 end
flickerstreak@63 182 inited = false
flickerstreak@28 183 end
flickerstreak@28 184
flickerstreak@63 185 function DeepCopy(x)
flickerstreak@28 186 if type(x) ~= "table" then
flickerstreak@28 187 return x
flickerstreak@28 188 end
flickerstreak@28 189 local r = {}
flickerstreak@28 190 for k,v in pairs(x) do
flickerstreak@28 191 r[k] = DeepCopy(v)
flickerstreak@28 192 end
flickerstreak@28 193 return r
flickerstreak@28 194 end
flickerstreak@28 195
flickerstreak@63 196 function CallModuleMethod(modulename, method, ...)
flickerstreak@63 197 local m = self:GetModule(modulename,true)
flickerstreak@63 198 if m then
flickerstreak@63 199 if type(m) == "table" and type(m[method]) == "function" then
flickerstreak@63 200 m[method](m,...)
flickerstreak@63 201 else
flickerstreak@63 202 dbprint(("Bad call '%s' to %s module"):format(tostring(method),modulename));
flickerstreak@63 203 end
flickerstreak@63 204 else
flickerstreak@63 205 self:Print(("Module '%s' not found"):format(tostring(modulename)))
flickerstreak@63 206 end
flickerstreak@28 207 end
flickerstreak@28 208
flickerstreak@63 209 function SlashHandler(option)
flickerstreak@30 210 if option == "config" then
flickerstreak@63 211 self:ShowConfig()
flickerstreak@58 212 elseif option == "edit" then
flickerstreak@63 213 self:ShowEditor()
flickerstreak@50 214 elseif option == "unlock" then
flickerstreak@63 215 self:SetConfigMode(true)
flickerstreak@50 216 elseif option == "lock" then
flickerstreak@63 217 self:SetConfigMode(false)
flickerstreak@88 218 elseif option == "kb" then
flickerstreak@88 219 self:SetKeybindMode(true)
flickerstreak@30 220 else
flickerstreak@63 221 self:Print(("%3.1f.%d"):format(version,self.revision))
flickerstreak@63 222 self:Print("/rxn config")
flickerstreak@63 223 self:Print("/rxn edit")
flickerstreak@63 224 self:Print("/rxn lock")
flickerstreak@63 225 self:Print("/rxn unlock")
flickerstreak@88 226 self:Print("/rxn kb")
flickerstreak@30 227 end
flickerstreak@30 228 end
flickerstreak@92 229
flickerstreak@28 230 end
flickerstreak@28 231
flickerstreak@28 232
flickerstreak@28 233 ------ HANDLERS ------
flickerstreak@28 234 function ReAction:OnInitialize()
flickerstreak@28 235 self.db = LibStub("AceDB-3.0"):New("ReAction_DB",
flickerstreak@28 236 {
flickerstreak@28 237 profile = {
flickerstreak@28 238 bars = { },
flickerstreak@28 239 defaultBar = { }
flickerstreak@28 240 }
flickerstreak@111 241 },
flickerstreak@114 242 L["Default"]
flickerstreak@28 243 )
flickerstreak@28 244 self.db.RegisterCallback(self,"OnProfileChanged")
flickerstreak@95 245 self.db.RegisterCallback(self,"OnProfileReset", "OnProfileChanged")
flickerstreak@95 246 self.db.RegisterCallback(self,"OnProfileCopied","OnProfileChanged")
flickerstreak@63 247
flickerstreak@88 248 KB.RegisterCallback(self,"LIBKEYBOUND_ENABLED")
flickerstreak@88 249 KB.RegisterCallback(self,"LIBKEYBOUND_DISABLED")
flickerstreak@88 250
flickerstreak@63 251 options.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db)
flickerstreak@63 252
flickerstreak@30 253 self:RegisterChatCommand("reaction", SlashHandler)
flickerstreak@30 254 self:RegisterChatCommand("rxn", SlashHandler)
flickerstreak@33 255 self:RegisterEvent("PLAYER_REGEN_DISABLED")
flickerstreak@28 256 end
flickerstreak@28 257
flickerstreak@28 258 function ReAction:OnEnable()
flickerstreak@28 259 InitializeBars()
flickerstreak@28 260 end
flickerstreak@28 261
flickerstreak@28 262 function ReAction:OnDisable()
flickerstreak@28 263 TearDownBars()
flickerstreak@28 264 end
flickerstreak@28 265
flickerstreak@28 266 function ReAction:OnProfileChanged()
flickerstreak@33 267 TearDownBars()
flickerstreak@33 268 InitializeBars()
flickerstreak@116 269 self:PopKeybindWarning()
flickerstreak@28 270 end
flickerstreak@28 271
flickerstreak@33 272 function ReAction:PLAYER_REGEN_DISABLED()
flickerstreak@63 273 if private.configMode == true then
flickerstreak@63 274 self:UserError(L["ReAction config mode disabled during combat."])
flickerstreak@33 275 self:SetConfigMode(false)
flickerstreak@88 276 self:SetKeybindMode(false)
flickerstreak@33 277 end
flickerstreak@33 278 end
flickerstreak@33 279
flickerstreak@88 280 function ReAction:LIBKEYBOUND_ENABLED( evt )
flickerstreak@88 281 self:SetKeybindMode(true)
flickerstreak@88 282 end
flickerstreak@88 283
flickerstreak@88 284 function ReAction:LIBKEYBOUND_DISABLED( evt )
flickerstreak@88 285 return self:SetKeybindMode(false)
flickerstreak@88 286 end
flickerstreak@88 287
flickerstreak@33 288
flickerstreak@28 289
flickerstreak@28 290 ------ API ------
flickerstreak@77 291 function ReAction:UpdateRevision(str)
flickerstreak@77 292 local revision = tonumber(str:match("%d+"))
flickerstreak@77 293 if revision and revision > ReAction.revision then
flickerstreak@77 294 ReAction.revision = revision
flickerstreak@77 295 end
flickerstreak@77 296 end
flickerstreak@77 297
flickerstreak@61 298 function ReAction:UserError(msg)
flickerstreak@61 299 -- any user errors should be flashed to the UIErrorsFrame
flickerstreak@61 300 UIErrorsFrame:AddMessage(msg)
flickerstreak@61 301 end
flickerstreak@61 302
flickerstreak@63 303 -- usage:
flickerstreak@91 304 -- (1) ReAction:CreateBar(name, [cfgTable])
flickerstreak@63 305 -- (2) ReAction:CreateBar(name, "barType", [nRows], [nCols], [btnSize], [btnSpacing])
flickerstreak@91 306 function ReAction:CreateBar(name, config, ...)
flickerstreak@91 307 local profile = self.db.profile
flickerstreak@91 308
flickerstreak@127 309 if name then
flickerstreak@127 310 if bars[name] then
flickerstreak@127 311 self:UserError(format(L["ReAction: name '%s' already in use"],name))
flickerstreak@127 312 return nil
flickerstreak@127 313 end
flickerstreak@127 314 else
flickerstreak@91 315 local prefix = L["Bar "]
flickerstreak@91 316 local i = 1
flickerstreak@91 317 repeat
flickerstreak@91 318 name = prefix..i
flickerstreak@91 319 i = i + 1
flickerstreak@91 320 until bars[name] == nil
flickerstreak@91 321 end
flickerstreak@91 322
flickerstreak@91 323 if type(config) == "string" then
flickerstreak@91 324 config = defaultBarConfig[config]
flickerstreak@48 325 if not config then
flickerstreak@91 326 error(("ReAction:CreateBar() - unknown bar type '%s'"):format(tostring(select(1,...))))
flickerstreak@48 327 end
flickerstreak@48 328 config = DeepCopy(config)
flickerstreak@91 329 config.btnRows = select(1,...) or config.btnRows or 1
flickerstreak@91 330 config.btnColumns = select(2,...) or config.btnColumns or 12
flickerstreak@91 331 config.btnWidth = select(3,...) or config.btnWidth or 36
flickerstreak@91 332 config.btnHeight = select(3,...) or config.btnHeight or 36
flickerstreak@91 333 config.spacing = select(4,...) or config.spacing or 3
flickerstreak@48 334 config.width = config.width or config.btnColumns*(config.btnWidth + config.spacing) + 1
flickerstreak@48 335 config.height = config.height or config.btnRows*(config.btnHeight + config.spacing) + 1
flickerstreak@81 336 config.anchor = config.anchor or "UIParent"
flickerstreak@81 337 config.point = config.point or "BOTTOM"
flickerstreak@81 338 config.relpoint = config.relpoint or "BOTTOM"
flickerstreak@48 339 config.y = config.y or 200
flickerstreak@48 340 config.x = config.x or 0
flickerstreak@48 341 end
flickerstreak@91 342 config = config or profile.bars[name] or DeepCopy(profile.defaultBar)
flickerstreak@91 343
flickerstreak@91 344 profile.bars[name] = config
flickerstreak@91 345 local bar = self.Bar:New( name, config ) -- ReAction.Bar defined in Bar.lua
flickerstreak@63 346 bars[name] = bar
flickerstreak@63 347 callbacks:Fire("OnCreateBar", bar, name)
flickerstreak@63 348 if private.configMode then
flickerstreak@33 349 bar:ShowControls(true)
flickerstreak@33 350 end
flickerstreak@33 351
flickerstreak@28 352 return bar
flickerstreak@28 353 end
flickerstreak@28 354
flickerstreak@28 355 function ReAction:EraseBar(x)
flickerstreak@28 356 local bar, name = SelectBar(x)
flickerstreak@63 357 if bar and name then
flickerstreak@63 358 callbacks:Fire("OnEraseBar", bar, name)
flickerstreak@28 359 DestroyBar(bar)
flickerstreak@28 360 self.db.profile.bars[name] = nil
flickerstreak@28 361 end
flickerstreak@28 362 end
flickerstreak@28 363
flickerstreak@28 364 function ReAction:GetBar(name)
flickerstreak@63 365 return bars[name]
flickerstreak@63 366 end
flickerstreak@63 367
flickerstreak@90 368 -- returns pairs of name, bar
flickerstreak@63 369 function ReAction:IterateBars()
flickerstreak@63 370 return pairs(bars)
flickerstreak@28 371 end
flickerstreak@28 372
flickerstreak@28 373 function ReAction:RenameBar(x, newname)
flickerstreak@28 374 local bar, name = SelectBar(x)
flickerstreak@63 375 if type(newname) ~= "string" then
flickerstreak@63 376 error("ReAction:RenameBar() - second argument must be a string")
flickerstreak@63 377 end
flickerstreak@63 378 if bar and name and #newname > 0 then
flickerstreak@127 379 if newname == name then
flickerstreak@127 380 return
flickerstreak@127 381 end
flickerstreak@63 382 if bars[newname] then
flickerstreak@127 383 self:UserError(format(L["ReAction: name '%s' already in use"],newname))
flickerstreak@47 384 else
flickerstreak@63 385 bars[newname], bars[name] = bars[name], nil
flickerstreak@47 386 bar:SetName(newname or "")
flickerstreak@47 387 local cfg = self.db.profile.bars
flickerstreak@47 388 cfg[newname], cfg[name] = cfg[name], nil
flickerstreak@63 389 callbacks:Fire("OnRenameBar", bar, name, newname)
flickerstreak@28 390 end
flickerstreak@28 391 end
flickerstreak@28 392 end
flickerstreak@28 393
flickerstreak@63 394 function ReAction:RefreshBar(x)
flickerstreak@63 395 local bar, name = SelectBar(x)
flickerstreak@63 396 if bar and name then
flickerstreak@63 397 callbacks:Fire("OnRefreshBar", bar, name)
flickerstreak@63 398 end
flickerstreak@63 399 end
flickerstreak@63 400
flickerstreak@53 401 function ReAction:RegisterBarType( name, config, isDefaultChoice )
flickerstreak@63 402 defaultBarConfig[name] = config
flickerstreak@48 403 if isDefaultChoice then
flickerstreak@81 404 private.defaultBarConfigChoice = name
flickerstreak@48 405 end
flickerstreak@48 406 self:RefreshOptions()
flickerstreak@48 407 end
flickerstreak@48 408
flickerstreak@53 409 function ReAction:UnregisterBarType( name )
flickerstreak@63 410 defaultBarConfig[name] = nil
flickerstreak@63 411 if private.defaultBarConfigChoice == name then
flickerstreak@63 412 private.defaultBarConfigChoice = nil
flickerstreak@48 413 end
flickerstreak@48 414 self:RefreshOptions()
flickerstreak@48 415 end
flickerstreak@48 416
flickerstreak@63 417 function ReAction:IterateBarTypes()
flickerstreak@63 418 return pairs(defaultBarConfig)
flickerstreak@63 419 end
flickerstreak@63 420
flickerstreak@63 421 function ReAction:GetBarTypeConfig(name)
flickerstreak@63 422 if name then
flickerstreak@63 423 return defaultBarConfig[name]
flickerstreak@63 424 end
flickerstreak@63 425 end
flickerstreak@63 426
flickerstreak@63 427 function ReAction:GetBarTypeOptions( fill )
flickerstreak@63 428 fill = fill or { }
flickerstreak@63 429 for k in self:IterateBarTypes() do
flickerstreak@63 430 fill[k] = k
flickerstreak@63 431 end
flickerstreak@63 432 return fill
flickerstreak@63 433 end
flickerstreak@63 434
flickerstreak@63 435 function ReAction:GetDefaultBarType()
flickerstreak@63 436 return private.defaultBarConfigChoice
flickerstreak@63 437 end
flickerstreak@63 438
flickerstreak@63 439 function ReAction:RegisterOptions(module, opts, global)
flickerstreak@63 440 options.args[global and "global" or "module"].plugins[module:GetName()] = opts
flickerstreak@63 441 self:RefreshOptions()
flickerstreak@30 442 end
flickerstreak@30 443
flickerstreak@30 444 function ReAction:RefreshOptions()
flickerstreak@63 445 callbacks:Fire("OnOptionsRefreshed")
flickerstreak@63 446 end
flickerstreak@63 447
flickerstreak@63 448 --
flickerstreak@63 449 -- In addition to global and general module options, options tables
flickerstreak@63 450 -- must be generated dynamically for each bar.
flickerstreak@63 451 --
flickerstreak@63 452 -- 'func' should be a function or a method string.
flickerstreak@63 453 -- The function or method will be passed the bar as its parameter.
flickerstreak@63 454 -- (methods will of course get the module as the first 'self' parameter)
flickerstreak@63 455 --
flickerstreak@63 456 -- A generator can be unregistered by passing a nil func.
flickerstreak@63 457 --
flickerstreak@63 458 function ReAction:RegisterBarOptionGenerator( module, func )
flickerstreak@63 459 if not module or type(module) ~= "table" then -- doesn't need to be a proper module, strictly
flickerstreak@63 460 error("ReAction:RegisterBarOptionGenerator() : Invalid module")
flickerstreak@63 461 end
flickerstreak@63 462 if type(func) == "string" then
flickerstreak@63 463 if not module[func] then
flickerstreak@63 464 error(("ReAction:RegisterBarOptionGenerator() : Invalid method '%s'"):format(func))
flickerstreak@63 465 end
flickerstreak@63 466 elseif func and type(func) ~= "function" then
flickerstreak@63 467 error("ReAction:RegisterBarOptionGenerator() : Invalid function")
flickerstreak@63 468 end
flickerstreak@63 469 barOptionGenerators[module] = func
flickerstreak@63 470 callbacks:Fire("OnBarOptionGeneratorRegistered", module, func)
flickerstreak@63 471 end
flickerstreak@63 472
flickerstreak@63 473 -- builds a table suitable for use as an AceConfig3 group 'plugins' sub-table
flickerstreak@63 474 function ReAction:GenerateBarOptionsTable( bar )
flickerstreak@63 475 local opts = { }
flickerstreak@63 476 for module, func in pairs(barOptionGenerators) do
flickerstreak@63 477 local success, r
flickerstreak@63 478 if type(func) == "string" then
flickerstreak@63 479 success, r = pcall(module[func], module, bar)
flickerstreak@63 480 else
flickerstreak@63 481 success, r = pcall(func, bar)
flickerstreak@63 482 end
flickerstreak@63 483 if success then
flickerstreak@90 484 if r then
flickerstreak@90 485 opts[module:GetName()] = { [module:GetName()] = r }
flickerstreak@90 486 end
flickerstreak@63 487 else
flickerstreak@63 488 geterrorhandler()(r)
flickerstreak@63 489 end
flickerstreak@63 490 end
flickerstreak@63 491 return opts
flickerstreak@30 492 end
flickerstreak@33 493
flickerstreak@33 494 function ReAction:SetConfigMode( mode )
flickerstreak@77 495 if mode ~= private.configMode then
flickerstreak@77 496 private.configMode = mode
flickerstreak@77 497 callbacks:Fire("OnConfigModeChanged", mode)
flickerstreak@77 498 end
flickerstreak@63 499 end
flickerstreak@63 500
flickerstreak@63 501 function ReAction:GetConfigMode()
flickerstreak@63 502 return private.configMode
flickerstreak@33 503 end
flickerstreak@38 504
flickerstreak@38 505 function ReAction:ShowConfig()
flickerstreak@63 506 CallModuleMethod("ConfigUI","OpenConfig")
flickerstreak@38 507 end
flickerstreak@38 508
flickerstreak@81 509 function ReAction:ShowEditor(bar, ...)
flickerstreak@81 510 CallModuleMethod("ConfigUI","LaunchBarEditor",bar, ...)
flickerstreak@47 511 end
flickerstreak@88 512
flickerstreak@88 513 function ReAction:SetKeybindMode( mode )
flickerstreak@88 514 if mode ~= private.kbMode then
flickerstreak@88 515 if mode then
flickerstreak@88 516 KB:Activate()
flickerstreak@88 517 else
flickerstreak@88 518 KB:Deactivate()
flickerstreak@88 519 end
flickerstreak@88 520 private.kbMode = KB:IsShown() or false
flickerstreak@88 521 end
flickerstreak@88 522 end
flickerstreak@88 523
flickerstreak@88 524 function ReAction:GetKeybindMode( mode )
flickerstreak@88 525 return private.kbMode
flickerstreak@88 526 end
flickerstreak@88 527
flickerstreak@116 528 function ReAction:PopKeybindWarning()
flickerstreak@116 529 if not self.db.global.skipKeybindWarning then
flickerstreak@116 530 StaticPopup_Show("REACTION_KB_WARN")
flickerstreak@92 531 end
flickerstreak@88 532 end
flickerstreak@122 533
flickerstreak@122 534 -- Export ReAction launcher to LibDataBroker-aware displays
flickerstreak@122 535 LibStub:GetLibrary("LibDataBroker-1.1"):NewDataObject( "ReAction",
flickerstreak@122 536 {
flickerstreak@122 537 type = "launcher",
flickerstreak@122 538 icon = "Interface\\Icons\\INV_Qiraj_JewelEncased",
flickerstreak@122 539
flickerstreak@122 540 OnClick = function( frame, button )
flickerstreak@122 541 if not InCombatLockdown() then
flickerstreak@122 542 if IsAltKeyDown() then
flickerstreak@122 543 ReAction:SetKeybindMode( not ReAction:GetKeybindMode() )
flickerstreak@122 544 elseif IsShiftKeyDown() then
flickerstreak@122 545 ReAction:SetConfigMode( not ReAction:GetConfigMode() )
flickerstreak@122 546 elseif button == "RightButton" then
flickerstreak@122 547 ReAction:ShowEditor()
flickerstreak@122 548 else
flickerstreak@122 549 ReAction:ShowConfig()
flickerstreak@122 550 end
flickerstreak@122 551 else
flickerstreak@122 552 ReAction:UserError(L["ReAction: can't configure in combat"])
flickerstreak@122 553 end
flickerstreak@122 554 end,
flickerstreak@122 555
flickerstreak@122 556 -- this isn't included in the 'launcher' type LDB spec but it seems all launcher displays use it
flickerstreak@122 557 OnTooltipShow = function( tooltip )
flickerstreak@122 558 tooltip:AddLine(format("|cffffffff%s|r %s",L["Click"],L["for global configuration"]))
flickerstreak@122 559 tooltip:AddLine(format("|cffffd200%s|r %s",L["Right-click"],L["for bar editor dialog"]))
flickerstreak@122 560 tooltip:AddLine(format("|cff00ff00%s|r %s",L["Shift-click"],L["to unlock bars"]))
flickerstreak@122 561 tooltip:AddLine(format("|cff00cccc%s|r %s",L["Alt-click"],L["for keybind mode"]))
flickerstreak@122 562 end,
flickerstreak@122 563
flickerstreak@122 564 }
flickerstreak@122 565 )