| 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 |