annotate State.lua @ 77:da8ba8783924

- added revision updater to each code file - Changed button/bar class mechanic to metatable-based - Changed buttons to live within a sub-frame, to play nicely between show-empty-buttons and hidestates - bar frame is now available only via accessor - Changed some semantics with AddButton/PlaceButton - Cleaned up action buttons options, fixed hide-when-empty option - moved show-action-ID-label as a button method - converted drag overlay from nested-frame to :Raise() - fixed ReAction:SetConfigMode() to not call event when mode doesn't change - Fixed ordering for dynamic state tab (always last)
author Flick <flickerstreak@gmail.com>
date Mon, 23 Jun 2008 22:27:50 +0000
parents 06cd74bdc7da
children a45255f5d0c2
rev   line source
flickerstreak@25 1 --[[
flickerstreak@62 2 ReAction bar state driver interface
flickerstreak@25 3
flickerstreak@25 4 --]]
flickerstreak@25 5
flickerstreak@25 6 -- local imports
flickerstreak@25 7 local ReAction = ReAction
flickerstreak@25 8 local L = ReAction.L
flickerstreak@25 9 local _G = _G
flickerstreak@25 10 local InCombatLockdown = InCombatLockdown
flickerstreak@75 11 local format = string.format
flickerstreak@25 12
flickerstreak@77 13 ReAction:UpdateRevision("$Revision: 103 $")
flickerstreak@77 14
flickerstreak@25 15 -- module declaration
flickerstreak@25 16 local moduleID = "State"
flickerstreak@65 17 local module = ReAction:NewModule( moduleID, "AceEvent-3.0" )
flickerstreak@62 18
flickerstreak@64 19 -- Utility --
flickerstreak@62 20
flickerstreak@62 21 -- traverse a table tree by key list and fetch the result or first nil
flickerstreak@62 22 local function tfetch(t, ...)
flickerstreak@62 23 for i = 1, select('#', ...) do
flickerstreak@62 24 t = t and t[select(i, ...)]
flickerstreak@62 25 end
flickerstreak@62 26 return t
flickerstreak@62 27 end
flickerstreak@62 28
flickerstreak@62 29 -- traverse a table tree by key list and build tree as necessary
flickerstreak@62 30 local function tbuild(t, ...)
flickerstreak@62 31 for i = 1, select('#', ...) do
flickerstreak@62 32 local key = select(i, ...)
flickerstreak@62 33 if not t[key] then t[key] = { } end
flickerstreak@62 34 t = t[key]
flickerstreak@62 35 end
flickerstreak@62 36 return t
flickerstreak@62 37 end
flickerstreak@62 38
flickerstreak@75 39 -- return a new array of keys of table 't', sorted by comparing
flickerstreak@75 40 -- sub-fields (obtained via tfetch) of the table values
flickerstreak@75 41 local function fieldsort( t, ... )
flickerstreak@75 42 local r = { }
flickerstreak@75 43 for k in pairs(t) do
flickerstreak@75 44 table.insert(r,k)
flickerstreak@75 45 end
flickerstreak@75 46 local path = { ... }
flickerstreak@75 47 table.sort(r, function(lhs, rhs)
flickerstreak@75 48 local olhs = tfetch(t[lhs], unpack(path)) or 0
flickerstreak@75 49 local orhs = tfetch(t[rhs], unpack(path)) or 0
flickerstreak@75 50 return olhs < orhs
flickerstreak@75 51 end)
flickerstreak@75 52 return r
flickerstreak@75 53 end
flickerstreak@75 54
flickerstreak@68 55
flickerstreak@68 56 local InitRules, ApplyStates, SetProperty, GetProperty
flickerstreak@75 57
flickerstreak@75 58 -- PRIVATE --
flickerstreak@64 59 do
flickerstreak@67 60 -- As far as I can tell the macro clauses are NOT locale-specific.
flickerstreak@67 61 local ruleformats = {
flickerstreak@67 62 stealth = "stealth",
flickerstreak@67 63 nostealth = "nostealth",
flickerstreak@67 64 shadowform = "form:1",
flickerstreak@67 65 noshadowform = "noform",
flickerstreak@67 66 pet = "pet",
flickerstreak@67 67 nopet = "nopet",
flickerstreak@67 68 harm = "target=target,harm",
flickerstreak@67 69 help = "target=target,help",
flickerstreak@67 70 notarget = "target=target,noexists",
flickerstreak@67 71 focusharm = "target=focus,harm",
flickerstreak@67 72 focushelp = "target=focus,help",
flickerstreak@67 73 nofocus = "target=focus,noexists",
flickerstreak@67 74 raid = "group:raid",
flickerstreak@67 75 party = "group:party",
flickerstreak@67 76 solo = "nogroup",
flickerstreak@67 77 combat = "combat",
flickerstreak@67 78 nocombat = "nocombat",
flickerstreak@75 79 possess = "bonusbar:5",
flickerstreak@67 80 }
flickerstreak@65 81
flickerstreak@67 82 -- Have to do these shenanigans instead of hardcoding the stances/forms because
flickerstreak@67 83 -- the ordering varies if the character is missing a form. For warriors
flickerstreak@67 84 -- this is rarely a problem (c'mon, who actually skips the level 10 def stance quest?)
flickerstreak@67 85 -- but for druids it can be. Some people never bother to do the aquatic form quest
flickerstreak@75 86 -- until well past when they get cat form, and stance 5/6 can be flight, tree, or moonkin
flickerstreak@67 87 -- depending on talents.
flickerstreak@65 88 function InitRules()
flickerstreak@65 89 local forms = { }
flickerstreak@67 90 -- sort by icon since it's locale-independent
flickerstreak@65 91 for i = 1, GetNumShapeshiftForms() do
flickerstreak@65 92 local icon = GetShapeshiftFormInfo(i)
flickerstreak@65 93 forms[icon] = i;
flickerstreak@65 94 end
flickerstreak@65 95 -- use 9 if not found since 9 is never a valid stance/form
flickerstreak@65 96 local defensive = forms["Interface\\Icons\\Ability_Warrior_DefensiveStance"] or 9
flickerstreak@65 97 local berserker = forms["Interface\\Icons\\Ability_Racial_Avatar"] or 9
flickerstreak@65 98 local bear = forms["Interface\\Icons\\Ability_Racial_BearForm"] or 9 -- bear and dire bear share the same icon
flickerstreak@65 99 local aquatic = forms["Interface\\Icons\\Ability_Druid_AquaticForm"] or 9
flickerstreak@65 100 local cat = forms["Interface\\Icons\\Ability_Druid_CatForm"] or 9
flickerstreak@65 101 local travel = forms["Interface\\Icons\\Ability_Druid_TravelForm"] or 9
flickerstreak@75 102 local tree = forms["Interface\\Icons\\Ability_Druid_TreeofLife"] or 9
flickerstreak@75 103 local moonkin = forms["Interface\\Icons\\Spell_Nature_ForceOfNature"] or 9
flickerstreak@67 104 local flight = forms["Interface\\Icons\\Ability_Druid_FlightForm"] or 9 -- flight and swift flight share the same icon
flickerstreak@65 105
flickerstreak@75 106 ruleformats.battle = "stance:1"
flickerstreak@75 107 ruleformats.defensive = format("stance:%d",defensive)
flickerstreak@75 108 ruleformats.berserker = format("stance:%d",berserker)
flickerstreak@75 109 ruleformats.caster = format("form:0/%d/%d/%d",aquatic, travel, flight)
flickerstreak@75 110 ruleformats.bear = format("form:%d",bear)
flickerstreak@75 111 ruleformats.cat = format("form:%d",cat)
flickerstreak@75 112 ruleformats.tree = format("form:%d",tree)
flickerstreak@75 113 ruleformats.moonkin = format("form:%d",moonkin)
flickerstreak@64 114 end
flickerstreak@62 115
flickerstreak@75 116
flickerstreak@75 117 -- state property functions
flickerstreak@75 118 local ofskeys = {
flickerstreak@75 119 anchorPoint = "point",
flickerstreak@75 120 anchorRelPoint = "relpoint",
flickerstreak@75 121 anchorX = "x",
flickerstreak@75 122 anchorY = "y"
flickerstreak@75 123 }
flickerstreak@75 124
flickerstreak@75 125 local barofsidx = {
flickerstreak@75 126 anchorPoint = 1,
flickerstreak@75 127 anchorRelPoint = 3,
flickerstreak@75 128 anchorX = 4,
flickerstreak@75 129 anchorY = 5
flickerstreak@75 130 }
flickerstreak@75 131
flickerstreak@75 132 local function UpdatePartialAnchor(bar, states, ckey)
flickerstreak@75 133 local map = { }
flickerstreak@75 134 local bc = bar.config
flickerstreak@75 135 for state, c in pairs(states) do
flickerstreak@75 136 if c.enableAnchor then
flickerstreak@75 137 map[state] = c[ckey]
flickerstreak@75 138 end
flickerstreak@68 139 end
flickerstreak@75 140 local ofskey = ofskeys[ckey]
flickerstreak@75 141 local default = select(barofsidx[ckey], bar:GetAnchor())
flickerstreak@75 142 bar:SetStateAttribute(format("headofs%s",ofskeys[ckey]), map, default)
flickerstreak@75 143 end
flickerstreak@75 144
flickerstreak@75 145 -- the name of the function maps to the name of the config element
flickerstreak@75 146 local propertyFuncs = {
flickerstreak@75 147 hide = function( bar, states )
flickerstreak@75 148 local hs = { }
flickerstreak@75 149 for state, config in pairs(states) do
flickerstreak@75 150 if config.hide then
flickerstreak@75 151 table.insert(hs, state)
flickerstreak@75 152 end
flickerstreak@75 153 end
flickerstreak@75 154 bar:SetStateAttribute("hidestates", nil, table.concat(hs,","), true) -- pass to buttons
flickerstreak@75 155 end,
flickerstreak@75 156
flickerstreak@75 157 page = function( bar, states )
flickerstreak@75 158 local map = { }
flickerstreak@75 159 for state, config in pairs(states) do
flickerstreak@75 160 if config.page then
flickerstreak@75 161 map[state] = format("page%d",config.page)
flickerstreak@75 162 end
flickerstreak@75 163 end
flickerstreak@75 164 bar:SetStateAttribute("statebutton", map)
flickerstreak@75 165 end,
flickerstreak@75 166
flickerstreak@75 167 keybindstate = function( bar, states )
flickerstreak@75 168 local map = { }
flickerstreak@75 169 for state, config in pairs(states) do
flickerstreak@75 170 local kbset = config.keybindstate and state
flickerstreak@75 171 map[state] = kbset
flickerstreak@75 172 for button in bar:IterateButtons() do
flickerstreak@75 173 -- TODO: inform children they should maintain multiple binding sets
flickerstreak@75 174 -- ?? button:UpdateBindingSet(kbset)
flickerstreak@75 175 end
flickerstreak@75 176 end
flickerstreak@77 177 bar:SetStateAttribute("statebindings", map, true) -- apply to button frame, bindings only work for direct children
flickerstreak@75 178 end,
flickerstreak@75 179
flickerstreak@75 180 enableAnchor = function( bar, states )
flickerstreak@75 181 for ckey in pairs(ofskeys) do
flickerstreak@75 182 UpdatePartialAnchor(bar, states, ckey)
flickerstreak@75 183 end
flickerstreak@75 184 end,
flickerstreak@75 185
flickerstreak@75 186 enableScale = function( bar, states )
flickerstreak@75 187 local map = { }
flickerstreak@75 188 for state, c in pairs(states) do
flickerstreak@75 189 if c.enableScale then
flickerstreak@75 190 map[state] = c.scale
flickerstreak@75 191 end
flickerstreak@75 192 end
flickerstreak@75 193 bar:SetStateAttribute("headscale", map, 1.0)
flickerstreak@75 194 end,
flickerstreak@75 195 }
flickerstreak@75 196
flickerstreak@75 197 -- generate some table entries
flickerstreak@75 198 propertyFuncs.scale = propertyFuncs.enableScale
flickerstreak@75 199 for ckey in pairs(ofskeys) do
flickerstreak@75 200 propertyFuncs[ckey] = function( bar, states )
flickerstreak@75 201 UpdatePartialAnchor(bar, states, ckey)
flickerstreak@75 202 end
flickerstreak@68 203 end
flickerstreak@68 204
flickerstreak@68 205
flickerstreak@68 206 function GetProperty( bar, state, propname )
flickerstreak@68 207 return tfetch(module.db.profile.bars, bar:GetName(), "states", state, propname)
flickerstreak@68 208 end
flickerstreak@68 209
flickerstreak@68 210 function SetProperty( bar, state, propname, value )
flickerstreak@68 211 local states = tbuild(module.db.profile.bars, bar:GetName(), "states")
flickerstreak@68 212 tbuild(states, state)[propname] = value
flickerstreak@68 213 local f = propertyFuncs[propname]
flickerstreak@68 214 if f then
flickerstreak@68 215 f(bar, states)
flickerstreak@68 216 end
flickerstreak@68 217 end
flickerstreak@68 218
flickerstreak@75 219
flickerstreak@75 220
flickerstreak@75 221 --
flickerstreak@75 222 -- Build a state-transition spec string and statemap to be passed to
flickerstreak@75 223 -- Bar:SetStateDriver().
flickerstreak@75 224 --
flickerstreak@75 225 -- The statemap building is complex: keybound states override all
flickerstreak@75 226 -- other transitions, so must remain in their current state, but must
flickerstreak@75 227 -- also remember other transitions that happen while they're stuck there
flickerstreak@75 228 -- so that when the binding is toggled off it can return to the proper state
flickerstreak@75 229 --
flickerstreak@75 230 local function BuildStateMap(states)
flickerstreak@75 231 local rules = { }
flickerstreak@75 232 local statemap = { }
flickerstreak@75 233 local keybinds = { }
flickerstreak@75 234 local default
flickerstreak@75 235
flickerstreak@75 236 -- first grab all the keybind override states
flickerstreak@75 237 -- and construct an override template
flickerstreak@75 238 local override
flickerstreak@75 239 do
flickerstreak@75 240 local overrides = { }
flickerstreak@75 241 for name, state in pairs(states) do
flickerstreak@75 242 local type = tfetch(state, "rule", "type")
flickerstreak@75 243 if type == "keybind" then
flickerstreak@75 244 -- use the state-stack to remember the current transition
flickerstreak@75 245 -- use $s as a marker for a later call to gsub()
flickerstreak@75 246 table.insert(overrides, format("%s:$s set() %s", name, name))
flickerstreak@75 247 end
flickerstreak@75 248 end
flickerstreak@75 249 if #overrides > 0 then
flickerstreak@75 250 table.insert(overrides, "") -- for a trailing ';'
flickerstreak@75 251 end
flickerstreak@75 252 override = table.concat(overrides, ";") or ""
flickerstreak@75 253 end
flickerstreak@75 254
flickerstreak@75 255 -- now iterate the rules in order
flickerstreak@75 256 for idx, state in ipairs(fieldsort(states, "rule", "order")) do
flickerstreak@75 257 local c = states[state].rule
flickerstreak@75 258 local type = c.type
flickerstreak@75 259 if type == "default" then
flickerstreak@75 260 default = default or state
flickerstreak@75 261 elseif type == "custom" then
flickerstreak@75 262 if c.custom then
flickerstreak@75 263 -- strip out all spaces from the custom rule
flickerstreak@75 264 table.insert(rules, format("%s %s", c.custom:gsub("%s",""), state))
flickerstreak@75 265 end
flickerstreak@75 266 elseif type == "any" then
flickerstreak@75 267 if c.values then
flickerstreak@75 268 local clauses = { }
flickerstreak@75 269 for key, value in pairs(c.values) do
flickerstreak@75 270 table.insert(clauses, format("[%s]", ruleformats[key]))
flickerstreak@75 271 end
flickerstreak@75 272 if #clauses > 0 then
flickerstreak@75 273 table.insert(rules, format("%s %s", table.concat(clauses), state))
flickerstreak@75 274 end
flickerstreak@75 275 end
flickerstreak@75 276 elseif type == "all" then
flickerstreak@75 277 if c.values then
flickerstreak@75 278 local clauses = { }
flickerstreak@75 279 for key, value in pairs(c.values) do
flickerstreak@75 280 table.insert(clauses, ruleformats[key])
flickerstreak@75 281 end
flickerstreak@75 282 if #clauses > 0 then
flickerstreak@75 283 table.insert(rules, format("%s %s", format("[%s]", table.concat(clauses, ",")), state))
flickerstreak@75 284 end
flickerstreak@75 285 end
flickerstreak@75 286 end
flickerstreak@75 287
flickerstreak@75 288 -- use a different virtual button for the actual keybind transition,
flickerstreak@75 289 -- to implement a toggle. You have to clear it regardless of the type
flickerstreak@75 290 -- (which is usually a no-op) to unbind state transitions when switching
flickerstreak@75 291 -- transition types.
flickerstreak@75 292 local bindbutton = format("%s_binding",state)
flickerstreak@75 293 if type == "keybind" then
flickerstreak@75 294 keybinds[bindbutton] = c.keybind or false
flickerstreak@75 295 statemap[bindbutton] = format("%s:pop();*:set(%s)", state, state)
flickerstreak@75 296 else
flickerstreak@75 297 keybinds[bindbutton] = false
flickerstreak@75 298 end
flickerstreak@75 299
flickerstreak@75 300 -- construct the statemap. gsub() the state name into the override template.
flickerstreak@75 301 statemap[state] = format("%s%s", override:gsub("%$s",state), state)
flickerstreak@75 302 end
flickerstreak@75 303 -- make sure that the default, if any, is last
flickerstreak@75 304 if default then
flickerstreak@75 305 table.insert(rules, default)
flickerstreak@75 306 end
flickerstreak@75 307 return table.concat(rules,";"), statemap, keybinds
flickerstreak@75 308 end
flickerstreak@75 309
flickerstreak@75 310 function ApplyStates( bar )
flickerstreak@75 311 local states = tfetch(module.db.profile.bars, bar:GetName(), "states")
flickerstreak@75 312 if states then
flickerstreak@75 313 local rule, statemap, keybinds = BuildStateMap(states)
flickerstreak@75 314 bar:SetStateDriver("reaction", rule, statemap)
flickerstreak@75 315 for state, key in pairs(keybinds) do
flickerstreak@75 316 bar:SetAttributeBinding(state, key, "state-reaction", state)
flickerstreak@75 317 end
flickerstreak@75 318 for k, f in pairs(propertyFuncs) do
flickerstreak@75 319 f(bar, states)
flickerstreak@68 320 end
flickerstreak@68 321 end
flickerstreak@68 322 end
flickerstreak@68 323
flickerstreak@64 324 end
flickerstreak@64 325
flickerstreak@64 326
flickerstreak@68 327
flickerstreak@68 328 -- module event handlers --
flickerstreak@68 329
flickerstreak@65 330 function module:OnInitialize()
flickerstreak@65 331 self.db = ReAction.db:RegisterNamespace( moduleID,
flickerstreak@65 332 {
flickerstreak@65 333 profile = {
flickerstreak@65 334 bars = { },
flickerstreak@65 335 }
flickerstreak@65 336 }
flickerstreak@65 337 )
flickerstreak@65 338
flickerstreak@65 339 InitRules()
flickerstreak@65 340 self:RegisterEvent("PLAYER_AURAS_CHANGED")
flickerstreak@65 341
flickerstreak@65 342 ReAction:RegisterBarOptionGenerator(self, "GetBarOptions")
flickerstreak@65 343
flickerstreak@65 344 ReAction.RegisterCallback(self, "OnCreateBar","OnRefreshBar")
flickerstreak@65 345 ReAction.RegisterCallback(self, "OnRefreshBar")
flickerstreak@65 346 ReAction.RegisterCallback(self, "OnEraseBar")
flickerstreak@65 347 ReAction.RegisterCallback(self, "OnRenameBar")
flickerstreak@65 348 ReAction.RegisterCallback(self, "OnConfigModeChanged")
flickerstreak@65 349 end
flickerstreak@65 350
flickerstreak@65 351 function module:PLAYER_AURAS_CHANGED()
flickerstreak@65 352 self:UnregisterEvent("PLAYER_AURAS_CHANGED")
flickerstreak@66 353 -- on login the number of stances is 0 until this event fires during the init sequence.
flickerstreak@66 354 -- however if you reload just the UI the number of stances is correct immediately
flickerstreak@66 355 -- and this event won't fire until you gain/lose buffs/debuffs, at which point you might
flickerstreak@66 356 -- be in combat.
flickerstreak@66 357 if not InCombatLockdown() then
flickerstreak@66 358 InitRules()
flickerstreak@66 359 for name, bar in ReAction:IterateBars() do
flickerstreak@67 360 self:OnRefreshBar(nil,bar,name)
flickerstreak@66 361 end
flickerstreak@66 362 end
flickerstreak@65 363 end
flickerstreak@65 364
flickerstreak@65 365 function module:OnRefreshBar(event, bar, name)
flickerstreak@65 366 local c = self.db.profile.bars[name]
flickerstreak@65 367 if c then
flickerstreak@68 368 ApplyStates(bar)
flickerstreak@65 369 end
flickerstreak@65 370 end
flickerstreak@65 371
flickerstreak@65 372 function module:OnEraseBar(event, bar, name)
flickerstreak@65 373 self.db.profile.bars[name] = nil
flickerstreak@65 374 end
flickerstreak@65 375
flickerstreak@65 376 function module:OnRenameBar(event, bar, oldname, newname)
flickerstreak@75 377 local bars = self.db.profile.bars
flickerstreak@65 378 bars[newname], bars[oldname] = bars[oldname], nil
flickerstreak@65 379 end
flickerstreak@65 380
flickerstreak@65 381 function module:OnConfigModeChanged(event, mode)
flickerstreak@65 382 -- TODO: unregister all state drivers (temporarily) and hidestates
flickerstreak@65 383 end
flickerstreak@65 384
flickerstreak@64 385
flickerstreak@64 386
flickerstreak@64 387 -- Options --
flickerstreak@64 388
flickerstreak@64 389 local CreateBarOptions
flickerstreak@62 390 do
flickerstreak@62 391 local function ClassCheck(...)
flickerstreak@62 392 for i = 1, select('#',...) do
flickerstreak@62 393 local _, c = UnitClass("player")
flickerstreak@62 394 if c == select(i,...) then
flickerstreak@62 395 return false
flickerstreak@62 396 end
flickerstreak@62 397 end
flickerstreak@62 398 return true
flickerstreak@62 399 end
flickerstreak@62 400
flickerstreak@64 401 -- pre-sorted by the order they should appear in
flickerstreak@64 402 local rules = {
flickerstreak@64 403 -- rule hidden fields
flickerstreak@64 404 { "stance", ClassCheck("WARRIOR"), { {battle = L["Battle Stance"]}, {defensive = L["Defensive Stance"]}, {berserker = L["Berserker Stance"]} } },
flickerstreak@75 405 { "form", ClassCheck("DRUID"), { {caster = L["Caster Form"]}, {bear = L["Bear Form"]}, {cat = L["Cat Form"]}, {tree = L["Tree of Life"]}, {moonkin = L["Moonkin Form"]} } },
flickerstreak@64 406 { "stealth", ClassCheck("ROGUE","DRUID"), { {stealth = L["Stealth"]}, {nostealth = L["No Stealth"]} } },
flickerstreak@64 407 { "shadow", ClassCheck("PRIEST"), { {shadowform = L["Shadowform"]}, {noshadowform = L["No Shadowform"]} } },
flickerstreak@64 408 { "pet", ClassCheck("HUNTER","WARLOCK"), { {pet = L["With Pet"]}, {nopet = L["Without Pet"]} } },
flickerstreak@64 409 { "target", false, { {harm = L["Hostile Target"]}, {help = L["Friendly Target"]}, {notarget = L["No Target"]} } },
flickerstreak@64 410 { "focus", false, { {focusharm = L["Hostile Focus"]}, {focushelp = L["Friendly Focus"]}, {nofocus = L["No Focus"]} } },
flickerstreak@75 411 { "possess", false, { {possess = L["Mind Control"]} } },
flickerstreak@64 412 { "group", false, { {raid = L["Raid"]}, {party = L["Party"]}, {solo = L["Solo"]} } },
flickerstreak@64 413 { "combat", false, { {combat = L["In Combat"]}, {nocombat = L["Out of Combat"]} } },
flickerstreak@62 414 }
flickerstreak@62 415
flickerstreak@64 416 local ruleSelect = { }
flickerstreak@64 417 local ruleMap = { }
flickerstreak@64 418 local optionMap = setmetatable({},{__mode="k"})
flickerstreak@62 419
flickerstreak@68 420 local pointTable = {
flickerstreak@68 421 NONE = " ",
flickerstreak@68 422 CENTER = L["Center"],
flickerstreak@68 423 LEFT = L["Left"],
flickerstreak@68 424 RIGHT = L["Right"],
flickerstreak@68 425 TOP = L["Top"],
flickerstreak@68 426 BOTTOM = L["Bottom"],
flickerstreak@68 427 TOPLEFT = L["Top Left"],
flickerstreak@68 428 TOPRIGHT = L["Top Right"],
flickerstreak@68 429 BOTTOMLEFT = L["Bottom Left"],
flickerstreak@68 430 BOTTOMRIGHT = L["Bottom Right"],
flickerstreak@68 431 }
flickerstreak@68 432
flickerstreak@64 433 -- unpack rules table into ruleSelect and ruleMap
flickerstreak@64 434 for _, c in ipairs(rules) do
flickerstreak@64 435 local rule, hidden, fields = unpack(c)
flickerstreak@64 436 if not hidden then
flickerstreak@64 437 for _, field in ipairs(fields) do
flickerstreak@64 438 local key, label = next(field)
flickerstreak@64 439 table.insert(ruleSelect, label)
flickerstreak@64 440 table.insert(ruleMap, key)
flickerstreak@62 441 end
flickerstreak@62 442 end
flickerstreak@62 443 end
flickerstreak@62 444
flickerstreak@62 445 local function CreateStateOptions(bar, name)
flickerstreak@62 446 local opts = {
flickerstreak@62 447 type = "group",
flickerstreak@62 448 name = name,
flickerstreak@64 449 childGroups = "tab",
flickerstreak@25 450 }
flickerstreak@62 451
flickerstreak@64 452 local states = tbuild(module.db.profile.bars, bar:GetName(), "states")
flickerstreak@64 453
flickerstreak@68 454 local function update()
flickerstreak@68 455 ApplyStates(bar)
flickerstreak@68 456 end
flickerstreak@68 457
flickerstreak@68 458 local function setrule( key, value, ... )
flickerstreak@64 459 tbuild(states, opts.name, "rule", ...)[key] = value
flickerstreak@64 460 end
flickerstreak@64 461
flickerstreak@68 462 local function getrule( ... )
flickerstreak@64 463 return tfetch(states, opts.name, "rule", ...)
flickerstreak@64 464 end
flickerstreak@64 465
flickerstreak@68 466 local function setprop(info, value)
flickerstreak@68 467 SetProperty(bar, opts.name, info[#info], value)
flickerstreak@68 468 end
flickerstreak@68 469
flickerstreak@68 470 local function getprop(info)
flickerstreak@68 471 return GetProperty(bar, opts.name, info[#info])
flickerstreak@68 472 end
flickerstreak@68 473
flickerstreak@64 474 local function fixall(setkey)
flickerstreak@64 475 -- if multiple selections in the same group are chosen when 'all' is selected,
flickerstreak@64 476 -- keep only one of them. If changing the mode, the first in the fields list will
flickerstreak@64 477 -- be chosen arbitrarily. Otherwise, if selecting a new checkbox from the field-set,
flickerstreak@64 478 -- it will be retained.
flickerstreak@64 479 local notified = false
flickerstreak@64 480 for _, c in ipairs(rules) do
flickerstreak@64 481 local rule, hidden, fields = unpack(c)
flickerstreak@64 482 local found = false
flickerstreak@64 483 for key in ipairs(fields) do
flickerstreak@68 484 if getrule("values",key) then
flickerstreak@64 485 if (found or setkey) and key ~= setkey then
flickerstreak@68 486 setrule(key,false,"values")
flickerstreak@64 487 if not setkey and not notified then
flickerstreak@64 488 ReAction:UserError(L["Warning: one or more incompatible rules were turned off"])
flickerstreak@64 489 notified = true
flickerstreak@64 490 end
flickerstreak@64 491 end
flickerstreak@64 492 found = true
flickerstreak@64 493 end
flickerstreak@62 494 end
flickerstreak@62 495 end
flickerstreak@62 496 end
flickerstreak@62 497
flickerstreak@64 498 local function getNeighbors()
flickerstreak@64 499 local before, after
flickerstreak@64 500 for k, v in pairs(states) do
flickerstreak@64 501 local o = tonumber(tfetch(v, "rule", "order"))
flickerstreak@64 502 if o and k ~= opts.name then
flickerstreak@64 503 local obefore = tfetch(states,before,"rule","order")
flickerstreak@64 504 local oafter = tfetch(states,after,"rule","order")
flickerstreak@64 505 if o < opts.order and (not obefore or obefore < o) then
flickerstreak@64 506 before = k
flickerstreak@64 507 end
flickerstreak@64 508 if o > opts.order and (not oafter or oafter > o) then
flickerstreak@64 509 after = k
flickerstreak@64 510 end
flickerstreak@64 511 end
flickerstreak@64 512 end
flickerstreak@64 513 return before, after
flickerstreak@64 514 end
flickerstreak@64 515
flickerstreak@64 516 local function swapOrder( a, b )
flickerstreak@64 517 -- do options table
flickerstreak@64 518 local args = optionMap[bar].args
flickerstreak@64 519 args[a].order, args[b].order = args[b].order, args[a].order
flickerstreak@64 520 -- do profile
flickerstreak@64 521 a = tbuild(states, a, "rule")
flickerstreak@64 522 b = tbuild(states, b, "rule")
flickerstreak@64 523 a.order, b.order = b.order, a.order
flickerstreak@64 524 end
flickerstreak@64 525
flickerstreak@68 526 local function anchordisable()
flickerstreak@71 527 return not GetProperty(bar, opts.name, "enableAnchor")
flickerstreak@64 528 end
flickerstreak@64 529
flickerstreak@68 530 tbuild(states, name)
flickerstreak@64 531
flickerstreak@68 532 opts.order = getrule("order")
flickerstreak@64 533 if opts.order == nil then
flickerstreak@64 534 -- add after the highest
flickerstreak@64 535 opts.order = 100
flickerstreak@64 536 for _, state in pairs(states) do
flickerstreak@64 537 local x = tonumber(tfetch(state, "rule", "order"))
flickerstreak@64 538 if x and x >= opts.order then
flickerstreak@64 539 opts.order = x + 1
flickerstreak@64 540 end
flickerstreak@64 541 end
flickerstreak@68 542 setrule("order",opts.order)
flickerstreak@64 543 end
flickerstreak@64 544
flickerstreak@64 545 opts.args = {
flickerstreak@68 546 ordering = {
flickerstreak@68 547 name = L["Info"],
flickerstreak@68 548 order = 1,
flickerstreak@64 549 type = "group",
flickerstreak@64 550 args = {
flickerstreak@64 551 delete = {
flickerstreak@68 552 name = L["Delete this State"],
flickerstreak@68 553 order = -1,
flickerstreak@64 554 type = "execute",
flickerstreak@64 555 func = function(info)
flickerstreak@68 556 if states[opts.name] then
flickerstreak@68 557 states[opts.name] = nil
flickerstreak@68 558 ApplyStates(bar)
flickerstreak@68 559 end
flickerstreak@64 560 optionMap[bar].args[opts.name] = nil
flickerstreak@64 561 end,
flickerstreak@64 562 },
flickerstreak@64 563 rename = {
flickerstreak@64 564 name = L["Name"],
flickerstreak@64 565 order = 1,
flickerstreak@68 566 type = "input",
flickerstreak@64 567 get = function() return opts.name end,
flickerstreak@64 568 set = function(info, value)
flickerstreak@64 569 -- check for existing state name
flickerstreak@64 570 if states[value] then
flickerstreak@75 571 format(L["State named '%s' already exists"],value)
flickerstreak@64 572 end
flickerstreak@64 573 local args = optionMap[bar].args
flickerstreak@64 574 states[value], args[value], states[opts.name], args[opts.name] = states[opts.name], args[opts.name], nil, nil
flickerstreak@64 575 opts.name = value
flickerstreak@64 576 update()
flickerstreak@64 577 end,
flickerstreak@64 578 pattern = "^%w*$",
flickerstreak@64 579 usage = L["State names must be alphanumeric without spaces"],
flickerstreak@64 580 },
flickerstreak@64 581 ordering = {
flickerstreak@64 582 name = L["Evaluation Order"],
flickerstreak@64 583 desc = L["State transitions are evaluated in the order listed:\nMove a state up or down to change the order"],
flickerstreak@64 584 order = 2,
flickerstreak@68 585 type = "group",
flickerstreak@68 586 inline = true,
flickerstreak@64 587 args = {
flickerstreak@64 588 up = {
flickerstreak@68 589 name = L["Up"],
flickerstreak@68 590 order = 1,
flickerstreak@64 591 type = "execute",
flickerstreak@64 592 width = "half",
flickerstreak@64 593 func = function()
flickerstreak@64 594 local before, after = getNeighbors()
flickerstreak@64 595 if before then
flickerstreak@64 596 swapOrder(before, opts.name)
flickerstreak@64 597 update()
flickerstreak@64 598 end
flickerstreak@64 599 end,
flickerstreak@64 600 },
flickerstreak@64 601 down = {
flickerstreak@68 602 name = L["Down"],
flickerstreak@68 603 order = 2,
flickerstreak@64 604 type = "execute",
flickerstreak@64 605 width = "half",
flickerstreak@64 606 func = function()
flickerstreak@64 607 local before, after = getNeighbors()
flickerstreak@64 608 if after then
flickerstreak@64 609 swapOrder(opts.name, after)
flickerstreak@64 610 update()
flickerstreak@64 611 end
flickerstreak@64 612 end,
flickerstreak@64 613 }
flickerstreak@64 614 }
flickerstreak@68 615 }
flickerstreak@64 616 }
flickerstreak@64 617 },
flickerstreak@68 618 properties = {
flickerstreak@68 619 name = L["Properties"],
flickerstreak@68 620 order = 2,
flickerstreak@68 621 type = "group",
flickerstreak@68 622 args = {
flickerstreak@68 623 desc = {
flickerstreak@68 624 name = L["Set the properties for the bar when in this state"],
flickerstreak@68 625 order = 1,
flickerstreak@68 626 type = "description"
flickerstreak@68 627 },
flickerstreak@68 628 hide = {
flickerstreak@68 629 name = L["Hide Bar"],
flickerstreak@68 630 order = 2,
flickerstreak@68 631 type = "toggle",
flickerstreak@68 632 set = setprop,
flickerstreak@68 633 get = getprop,
flickerstreak@68 634 },
flickerstreak@68 635 page = {
flickerstreak@68 636 name = L["Show Page #"],
flickerstreak@68 637 order = 3,
flickerstreak@68 638 type = "select",
flickerstreak@68 639 disabled = function()
flickerstreak@75 640 --return bar:GetNumPages() < 2
flickerstreak@75 641 return true
flickerstreak@68 642 end,
flickerstreak@68 643 hidden = function()
flickerstreak@75 644 --return bar:GetNumPages() < 2
flickerstreak@75 645 return true
flickerstreak@68 646 end,
flickerstreak@68 647 values = function()
flickerstreak@75 648 -- use off-by-one ordering to put (none) first in the list
flickerstreak@75 649 local pages = { [1] = L["(none)"] }
flickerstreak@75 650 --for i = 1, bar:GetNumPages() do
flickerstreak@75 651 -- pages[i+1] = i
flickerstreak@75 652 --end
flickerstreak@68 653 return pages
flickerstreak@68 654 end,
flickerstreak@68 655 set = function(info, value)
flickerstreak@75 656 value = value - 1
flickerstreak@75 657 setprop(info, value > 0 and value or nil)
flickerstreak@68 658 end,
flickerstreak@68 659 get = function(info)
flickerstreak@75 660 return getprop(info) or L["(none)"]
flickerstreak@68 661 end,
flickerstreak@68 662 },
flickerstreak@68 663 keybindstate = {
flickerstreak@68 664 name = L["Override Keybinds"],
flickerstreak@68 665 desc = L["Set this state to maintain its own set of keybinds which override the defaults when active"],
flickerstreak@68 666 order = 4,
flickerstreak@68 667 type = "toggle",
flickerstreak@68 668 set = setprop,
flickerstreak@68 669 get = getprop,
flickerstreak@68 670 },
flickerstreak@68 671 position = {
flickerstreak@68 672 name = L["Position"],
flickerstreak@68 673 order = 5,
flickerstreak@68 674 type = "group",
flickerstreak@68 675 inline = true,
flickerstreak@68 676 args = {
flickerstreak@71 677 enableAnchor = {
flickerstreak@68 678 name = L["Set New Position"],
flickerstreak@68 679 order = 1,
flickerstreak@68 680 type = "toggle",
flickerstreak@68 681 set = setprop,
flickerstreak@68 682 get = getprop,
flickerstreak@68 683 },
flickerstreak@68 684 anchorPoint = {
flickerstreak@68 685 name = L["Point"],
flickerstreak@68 686 order = 2,
flickerstreak@68 687 type = "select",
flickerstreak@68 688 values = pointTable,
flickerstreak@68 689 set = function(info, value) setprop(info, value ~= "NONE" and value or nil) end,
flickerstreak@68 690 get = function(info) return getprop(info) or "NONE" end,
flickerstreak@68 691 disabled = anchordisable,
flickerstreak@68 692 hidden = anchordisable,
flickerstreak@68 693 },
flickerstreak@68 694 anchorRelPoint = {
flickerstreak@68 695 name = L["Relative Point"],
flickerstreak@68 696 order = 3,
flickerstreak@68 697 type = "select",
flickerstreak@68 698 values = pointTable,
flickerstreak@68 699 set = function(info, value) setprop(info, value ~= "NONE" and value or nil) end,
flickerstreak@68 700 get = function(info) return getprop(info) or "NONE" end,
flickerstreak@68 701 disabled = anchordisable,
flickerstreak@68 702 hidden = anchordisable,
flickerstreak@68 703 },
flickerstreak@68 704 anchorX = {
flickerstreak@68 705 name = L["X Offset"],
flickerstreak@68 706 order = 4,
flickerstreak@68 707 type = "range",
flickerstreak@68 708 min = -100,
flickerstreak@68 709 max = 100,
flickerstreak@68 710 step = 1,
flickerstreak@68 711 set = setprop,
flickerstreak@68 712 get = getprop,
flickerstreak@68 713 disabled = anchordisable,
flickerstreak@68 714 hidden = anchordisable,
flickerstreak@68 715 },
flickerstreak@68 716 anchorY = {
flickerstreak@68 717 name = L["Y Offset"],
flickerstreak@68 718 order = 5,
flickerstreak@68 719 type = "range",
flickerstreak@68 720 min = -100,
flickerstreak@68 721 max = 100,
flickerstreak@68 722 step = 1,
flickerstreak@68 723 set = setprop,
flickerstreak@68 724 get = getprop,
flickerstreak@68 725 disabled = anchordisable,
flickerstreak@68 726 hidden = anchordisable,
flickerstreak@68 727 },
flickerstreak@68 728 },
flickerstreak@68 729 },
flickerstreak@68 730 scale = {
flickerstreak@68 731 name = L["Scale"],
flickerstreak@68 732 order = 6,
flickerstreak@68 733 type = "group",
flickerstreak@68 734 inline = true,
flickerstreak@68 735 args = {
flickerstreak@75 736 enableScale = {
flickerstreak@68 737 name = L["Set New Scale"],
flickerstreak@68 738 order = 1,
flickerstreak@68 739 type = "toggle",
flickerstreak@68 740 set = setprop,
flickerstreak@68 741 get = getprop,
flickerstreak@68 742 },
flickerstreak@68 743 scale = {
flickerstreak@68 744 name = L["Scale"],
flickerstreak@68 745 order = 2,
flickerstreak@68 746 type = "range",
flickerstreak@68 747 min = 0.1,
flickerstreak@68 748 max = 2.5,
flickerstreak@68 749 step = 0.05,
flickerstreak@68 750 isPercent = true,
flickerstreak@68 751 set = setprop,
flickerstreak@68 752 get = function(info) return getprop(info) or 1 end,
flickerstreak@75 753 disabled = function() return not GetProperty(bar, opts.name, "enableScale") end,
flickerstreak@75 754 hidden = function() return not GetProperty(bar, opts.name, "enableScale") end,
flickerstreak@68 755 },
flickerstreak@68 756 },
flickerstreak@68 757 },
flickerstreak@68 758 },
flickerstreak@68 759 },
flickerstreak@64 760 rules = {
flickerstreak@70 761 name = L["Rule"],
flickerstreak@68 762 order = 3,
flickerstreak@64 763 type = "group",
flickerstreak@64 764 args = {
flickerstreak@64 765 mode = {
flickerstreak@68 766 name = L["Select this state"],
flickerstreak@68 767 order = 2,
flickerstreak@64 768 type = "select",
flickerstreak@64 769 style = "radio",
flickerstreak@64 770 values = {
flickerstreak@64 771 default = L["by default"],
flickerstreak@64 772 any = L["when ANY of these"],
flickerstreak@64 773 all = L["when ALL of these"],
flickerstreak@68 774 custom = L["via custom rule"],
flickerstreak@68 775 keybind = L["via keybinding"],
flickerstreak@64 776 },
flickerstreak@64 777 set = function( info, value )
flickerstreak@68 778 setrule("type", value)
flickerstreak@64 779 fixall()
flickerstreak@64 780 update()
flickerstreak@64 781 end,
flickerstreak@64 782 get = function( info )
flickerstreak@68 783 return getrule("type")
flickerstreak@64 784 end,
flickerstreak@64 785 },
flickerstreak@64 786 clear = {
flickerstreak@68 787 name = L["Clear All"],
flickerstreak@68 788 order = 3,
flickerstreak@64 789 type = "execute",
flickerstreak@68 790 hidden = function()
flickerstreak@68 791 local t = getrule("type")
flickerstreak@68 792 return t ~= "any" and t ~= "all"
flickerstreak@68 793 end,
flickerstreak@68 794 disabled = function()
flickerstreak@68 795 local t = getrule("type")
flickerstreak@68 796 return t ~= "any" and t ~= "all"
flickerstreak@68 797 end,
flickerstreak@64 798 func = function()
flickerstreak@68 799 local type = getrule("type")
flickerstreak@64 800 if type == "custom" then
flickerstreak@68 801 setrule("custom","")
flickerstreak@64 802 elseif type == "any" or type == "all" then
flickerstreak@68 803 setrule("values", {})
flickerstreak@64 804 end
flickerstreak@64 805 update()
flickerstreak@64 806 end,
flickerstreak@64 807 },
flickerstreak@64 808 inputs = {
flickerstreak@68 809 name = L["Conditions"],
flickerstreak@68 810 order = 4,
flickerstreak@64 811 type = "multiselect",
flickerstreak@64 812 hidden = function()
flickerstreak@68 813 local t = getrule("type")
flickerstreak@68 814 return t ~= "any" and t ~= "all"
flickerstreak@64 815 end,
flickerstreak@64 816 disabled = function()
flickerstreak@68 817 local t = getrule("type")
flickerstreak@68 818 return t ~= "any" and t ~= "all"
flickerstreak@64 819 end,
flickerstreak@64 820 values = ruleSelect,
flickerstreak@64 821 set = function(info, key, value )
flickerstreak@68 822 setrule(ruleMap[key], value or nil, "values")
flickerstreak@64 823 if value then
flickerstreak@64 824 fixall(ruleMap[key])
flickerstreak@64 825 end
flickerstreak@64 826 update()
flickerstreak@64 827 end,
flickerstreak@64 828 get = function(info, key)
flickerstreak@68 829 return getrule("values", ruleMap[key]) or false
flickerstreak@64 830 end,
flickerstreak@64 831 },
flickerstreak@64 832 custom = {
flickerstreak@68 833 name = L["Custom Rule"],
flickerstreak@68 834 order = 5,
flickerstreak@64 835 type = "input",
flickerstreak@64 836 multiline = true,
flickerstreak@64 837 hidden = function()
flickerstreak@68 838 return getrule("type") ~= "custom"
flickerstreak@64 839 end,
flickerstreak@64 840 disabled = function()
flickerstreak@68 841 return getrule("type") ~= "custom"
flickerstreak@64 842 end,
flickerstreak@64 843 desc = L["Syntax like macro rules: see preset rules for examples"],
flickerstreak@64 844 set = function(info, value)
flickerstreak@68 845 setrule("custom",value)
flickerstreak@64 846 update()
flickerstreak@64 847 end,
flickerstreak@64 848 get = function(info)
flickerstreak@68 849 return getrule("custom") or ""
flickerstreak@64 850 end,
flickerstreak@64 851 validate = function (info, rule)
flickerstreak@64 852 local s = rule:gsub("%s","") -- remove all spaces
flickerstreak@64 853 -- unfortunately %b and captures don't support the '+' notation, or this would be considerably simpler
flickerstreak@64 854 repeat
flickerstreak@64 855 if s == "" then
flickerstreak@64 856 return true
flickerstreak@64 857 end
flickerstreak@64 858 local c, r = s:match("(%b[])(.*)")
flickerstreak@64 859 if c == nil and s and #s > 0 then
flickerstreak@75 860 return format(L["Invalid custom rule '%s': each clause must appear within [brackets]"],rule)
flickerstreak@64 861 end
flickerstreak@64 862 s = r
flickerstreak@64 863 until c == nil
flickerstreak@64 864 return true
flickerstreak@64 865 end,
flickerstreak@68 866 },
flickerstreak@68 867 keybind = {
flickerstreak@68 868 name = L["Keybinding"],
flickerstreak@68 869 order = 6,
flickerstreak@68 870 inline = true,
flickerstreak@68 871 hidden = function() return getrule("type") ~= "keybind" end,
flickerstreak@68 872 disabled = function() return getrule("type") ~= "keybind" end,
flickerstreak@68 873 type = "group",
flickerstreak@68 874 args = {
flickerstreak@68 875 desc = {
flickerstreak@72 876 name = L["Invoking a state keybind toggles an override of all other transition rules."],
flickerstreak@68 877 order = 1,
flickerstreak@68 878 type = "description",
flickerstreak@68 879 },
flickerstreak@68 880 keybind = {
flickerstreak@68 881 name = L["State Hotkey"],
flickerstreak@68 882 desc = L["Define an override toggle keybind"],
flickerstreak@68 883 order = 2,
flickerstreak@68 884 type = "keybinding",
flickerstreak@68 885 set = function(info, value)
flickerstreak@70 886 if value and #value == 0 then
flickerstreak@70 887 value = nil
flickerstreak@70 888 end
flickerstreak@68 889 setrule("keybind",value)
flickerstreak@68 890 update()
flickerstreak@68 891 end,
flickerstreak@68 892 get = function() return getrule("keybind") end,
flickerstreak@68 893 },
flickerstreak@68 894 },
flickerstreak@68 895 },
flickerstreak@68 896 },
flickerstreak@68 897 },
flickerstreak@62 898 }
flickerstreak@62 899 return opts
flickerstreak@25 900 end
flickerstreak@62 901
flickerstreak@64 902
flickerstreak@62 903 CreateBarOptions = function(bar)
flickerstreak@62 904 local private = { }
flickerstreak@75 905 local states = tbuild(module.db.profile.bars, bar:GetName(), "states")
flickerstreak@62 906 local options = {
flickerstreak@77 907 name = L["Dynamic State"],
flickerstreak@62 908 type = "group",
flickerstreak@77 909 order = -1,
flickerstreak@64 910 childGroups = "tree",
flickerstreak@62 911 disabled = InCombatLockdown,
flickerstreak@62 912 args = {
flickerstreak@64 913 __desc__ = {
flickerstreak@68 914 name = L["States are evaluated in the order they are listed"],
flickerstreak@68 915 order = 1,
flickerstreak@64 916 type = "description",
flickerstreak@64 917 },
flickerstreak@64 918 __new__ = {
flickerstreak@64 919 name = L["New State..."],
flickerstreak@64 920 order = 2,
flickerstreak@68 921 type = "group",
flickerstreak@62 922 args = {
flickerstreak@64 923 name = {
flickerstreak@64 924 name = L["State Name"],
flickerstreak@64 925 desc = L["Set a name for the new state"],
flickerstreak@68 926 order = 1,
flickerstreak@68 927 type = "input",
flickerstreak@64 928 get = function() return private.newstatename or "" end,
flickerstreak@64 929 set = function(info,value) private.newstatename = value end,
flickerstreak@64 930 pattern = "^%w*$",
flickerstreak@64 931 usage = L["State names must be alphanumeric without spaces"],
flickerstreak@64 932 },
flickerstreak@64 933 create = {
flickerstreak@68 934 name = L["Create State"],
flickerstreak@68 935 order = 2,
flickerstreak@64 936 type = "execute",
flickerstreak@64 937 func = function ()
flickerstreak@64 938 local name = private.newstatename
flickerstreak@68 939 if states[name] then
flickerstreak@75 940 ReAction:UserError(format(L["State named '%s' already exists"],name))
flickerstreak@68 941 else
flickerstreak@68 942 -- TODO: select default state options and pass as final argument
flickerstreak@68 943 states[name] = { }
flickerstreak@68 944 optionMap[bar].args[name] = CreateStateOptions(bar,name)
flickerstreak@68 945 private.newstatename = ""
flickerstreak@68 946 end
flickerstreak@64 947 end,
flickerstreak@64 948 disabled = function()
flickerstreak@64 949 local name = private.newstatename or ""
flickerstreak@64 950 return #name == 0 or name:find("%W")
flickerstreak@64 951 end,
flickerstreak@62 952 }
flickerstreak@62 953 }
flickerstreak@64 954 }
flickerstreak@62 955 }
flickerstreak@62 956 }
flickerstreak@62 957 local states = tfetch(module.db.profile.bars, bar:GetName(), "states")
flickerstreak@62 958 if states then
flickerstreak@62 959 for name, config in pairs(states) do
flickerstreak@64 960 options.args[name] = CreateStateOptions(bar,name)
flickerstreak@62 961 end
flickerstreak@62 962 end
flickerstreak@64 963 optionMap[bar] = options
flickerstreak@62 964 return options
flickerstreak@62 965 end
flickerstreak@25 966 end
flickerstreak@25 967
flickerstreak@62 968 function module:GetBarOptions(bar)
flickerstreak@64 969 return CreateBarOptions(bar)
flickerstreak@25 970 end