annotate modules/State.lua @ 169:8cc187143acd

Strip out obsolete revision tracking
author Flick <flickerstreak@gmail.com>
date Tue, 19 Oct 2010 17:20:16 +0000
parents e77f716af1b7
children df68b5a40490
rev   line source
flickerstreak@109 1 --[[
flickerstreak@109 2 ReAction bar state driver interface
flickerstreak@109 3
flickerstreak@109 4 --]]
flickerstreak@109 5
flickerstreak@109 6 -- local imports
flickerstreak@109 7 local ReAction = ReAction
flickerstreak@109 8 local L = ReAction.L
flickerstreak@109 9 local _G = _G
flickerstreak@109 10 local format = string.format
flickerstreak@109 11 local InCombatLockdown = InCombatLockdown
flickerstreak@109 12 local RegisterStateDriver = RegisterStateDriver
flickerstreak@109 13
flickerstreak@109 14 -- module declaration
flickerstreak@109 15 local moduleID = "State"
flickerstreak@109 16 local module = ReAction:NewModule( moduleID, "AceEvent-3.0" )
flickerstreak@109 17
flickerstreak@109 18 -- Utility --
flickerstreak@109 19
flickerstreak@109 20 -- traverse a table tree by key list and fetch the result or first nil
flickerstreak@109 21 local function tfetch(t, ...)
flickerstreak@109 22 for i = 1, select('#', ...) do
flickerstreak@109 23 t = t and t[select(i, ...)]
flickerstreak@109 24 end
flickerstreak@109 25 return t
flickerstreak@109 26 end
flickerstreak@109 27
flickerstreak@109 28 -- traverse a table tree by key list and build tree as necessary
flickerstreak@109 29 local function tbuild(t, ...)
flickerstreak@109 30 for i = 1, select('#', ...) do
flickerstreak@109 31 local key = select(i, ...)
flickerstreak@109 32 if not t[key] then t[key] = { } end
flickerstreak@109 33 t = t[key]
flickerstreak@109 34 end
flickerstreak@109 35 return t
flickerstreak@109 36 end
flickerstreak@109 37
flickerstreak@109 38 -- return a new array of keys of table 't', sorted by comparing
flickerstreak@109 39 -- sub-fields (obtained via tfetch) of the table values
flickerstreak@109 40 local function fieldsort( t, ... )
flickerstreak@109 41 local r = { }
flickerstreak@109 42 for k in pairs(t) do
flickerstreak@109 43 table.insert(r,k)
flickerstreak@109 44 end
flickerstreak@109 45 local path = { ... }
flickerstreak@109 46 table.sort(r, function(lhs, rhs)
flickerstreak@109 47 local olhs = tfetch(t[lhs], unpack(path)) or 0
flickerstreak@109 48 local orhs = tfetch(t[rhs], unpack(path)) or 0
flickerstreak@109 49 return olhs < orhs
flickerstreak@109 50 end)
flickerstreak@109 51 return r
flickerstreak@109 52 end
flickerstreak@109 53
flickerstreak@109 54
flickerstreak@157 55 local ApplyStates, CleanupStates, SetProperty, GetProperty, RegisterProperty
flickerstreak@109 56
flickerstreak@109 57 -- PRIVATE --
flickerstreak@109 58 do
flickerstreak@109 59 function GetProperty( bar, state, propname )
flickerstreak@109 60 return tfetch(module.db.profile.bars, bar:GetName(), "states", state, propname)
flickerstreak@109 61 end
flickerstreak@109 62
flickerstreak@109 63 function SetProperty( bar, state, propname, value )
flickerstreak@109 64 local s = tbuild(module.db.profile.bars, bar:GetName(), "states", state)
flickerstreak@109 65 s[propname] = value
flickerstreak@155 66 bar:SetSecureStateData(state, propname, value)
flickerstreak@109 67 end
flickerstreak@109 68
flickerstreak@109 69 function RegisterProperty( propname, snippet )
flickerstreak@109 70 for _, bar in ReAction:IterateBars() do
flickerstreak@155 71 if type(snippet) == "string" then
flickerstreak@155 72 bar:SetSecureStateExtension(propname,snippet)
flickerstreak@109 73 end
flickerstreak@157 74 ApplyStates(bar)
flickerstreak@109 75 end
flickerstreak@109 76 end
flickerstreak@109 77
flickerstreak@109 78 function UnregisterProperty( propname )
flickerstreak@109 79 for _, bar in ReAction:IterateBars() do
flickerstreak@155 80 bar:SetSecureStateExtension(propname,nil)
flickerstreak@157 81 ApplyStates(bar)
flickerstreak@109 82 end
flickerstreak@109 83 end
flickerstreak@109 84
flickerstreak@109 85 function ApplyStates( bar )
flickerstreak@109 86 local states = tfetch(module.db.profile.bars, bar:GetName(), "states")
flickerstreak@109 87 if states then
flickerstreak@157 88 bar:SetStateDriver(states)
flickerstreak@109 89 end
flickerstreak@109 90 end
flickerstreak@109 91
flickerstreak@109 92 function CleanupStates( bar )
flickerstreak@155 93 bar:SetStateDriver(nil)
flickerstreak@109 94 end
flickerstreak@109 95 end
flickerstreak@109 96
flickerstreak@109 97
flickerstreak@109 98
flickerstreak@109 99 -- module event handlers --
flickerstreak@109 100
flickerstreak@109 101 function module:OnInitialize()
flickerstreak@109 102 self.db = ReAction.db:RegisterNamespace( moduleID,
flickerstreak@109 103 {
flickerstreak@109 104 profile = {
flickerstreak@109 105 bars = { },
flickerstreak@109 106 }
flickerstreak@109 107 }
flickerstreak@109 108 )
flickerstreak@109 109
flickerstreak@109 110 self:RegisterEvent("UPDATE_SHAPESHIFT_FORMS")
flickerstreak@109 111
flickerstreak@109 112 ReAction:RegisterBarOptionGenerator(self, "GetBarOptions")
flickerstreak@109 113
flickerstreak@109 114 ReAction.RegisterCallback(self, "OnCreateBar","OnRefreshBar")
flickerstreak@109 115 ReAction.RegisterCallback(self, "OnDestroyBar")
flickerstreak@109 116 ReAction.RegisterCallback(self, "OnRefreshBar")
flickerstreak@109 117 ReAction.RegisterCallback(self, "OnEraseBar")
flickerstreak@109 118 ReAction.RegisterCallback(self, "OnRenameBar")
flickerstreak@109 119 end
flickerstreak@109 120
flickerstreak@109 121 function module:OnEnable()
flickerstreak@109 122 self:UPDATE_SHAPESHIFT_FORMS() -- it doesn't fire on a /reloadui
flickerstreak@109 123 end
flickerstreak@109 124
flickerstreak@109 125 function module:UPDATE_SHAPESHIFT_FORMS()
flickerstreak@109 126 -- Re-parse the rules table according to the new form list.
flickerstreak@109 127 -- This happens both at initial login (after PLAYER_ENTERING_WORLD)
flickerstreak@109 128 -- as well as when gaining new abilities.
flickerstreak@157 129 ReAction.Bar.InitRuleFormats()
flickerstreak@155 130 for _, bar in ReAction:IterateBars() do
flickerstreak@155 131 ApplyStates(bar)
flickerstreak@109 132 end
flickerstreak@109 133 end
flickerstreak@109 134
flickerstreak@109 135 function module:OnRefreshBar(event, bar, name)
flickerstreak@109 136 local c = self.db.profile.bars[name]
flickerstreak@109 137 if c then
flickerstreak@109 138 ApplyStates(bar)
flickerstreak@109 139 end
flickerstreak@109 140 end
flickerstreak@109 141
flickerstreak@109 142 function module:OnDestroyBar(event, bar, name)
flickerstreak@109 143 CleanupStates(bar)
flickerstreak@109 144 end
flickerstreak@109 145
flickerstreak@109 146 function module:OnEraseBar(event, bar, name)
flickerstreak@109 147 self.db.profile.bars[name] = nil
flickerstreak@109 148 end
flickerstreak@109 149
flickerstreak@109 150 function module:OnRenameBar(event, bar, oldname, newname)
flickerstreak@109 151 local bars = self.db.profile.bars
flickerstreak@109 152 bars[newname], bars[oldname] = bars[oldname], nil
flickerstreak@109 153 end
flickerstreak@109 154
flickerstreak@109 155
flickerstreak@109 156
flickerstreak@109 157 -- Options --
flickerstreak@109 158
flickerstreak@109 159 local CreateBarOptions, RegisterPropertyOptions
flickerstreak@109 160 do
flickerstreak@109 161 -- pre-sorted by the order they should appear in
flickerstreak@109 162 local rules = {
flickerstreak@118 163 -- rule fields
flickerstreak@118 164 { "stance", { {battle = L["Battle Stance"]}, {defensive = L["Defensive Stance"]}, {berserker = L["Berserker Stance"]} } },
flickerstreak@118 165 { "form", { {caster = L["Caster Form"]}, {bear = L["Bear Form"]}, {cat = L["Cat Form"]}, {tree = L["Tree of Life"]}, {moonkin = L["Moonkin Form"]} } },
flickerstreak@118 166 { "stealth", { {stealth = L["Stealth"]}, {nostealth = L["No Stealth"]} } },
flickerstreak@118 167 { "shadow", { {shadowform = L["Shadowform"]}, {noshadowform = L["No Shadowform"]} } },
flickerstreak@118 168 { "pet", { {pet = L["With Pet"]}, {nopet = L["Without Pet"]} } },
flickerstreak@118 169 { "target", { {harm = L["Hostile Target"]}, {help = L["Friendly Target"]}, {notarget = L["No Target"]} } },
flickerstreak@118 170 { "focus", { {focusharm = L["Hostile Focus"]}, {focushelp = L["Friendly Focus"]}, {nofocus = L["No Focus"]} } },
flickerstreak@118 171 { "possess", { {possess = L["Mind Control"]} } },
flickerstreak@118 172 { "vehicle", { {vehicle = L["In a Vehicle"]} } },
flickerstreak@118 173 { "group", { {raid = L["Raid"]}, {party = L["Party"]}, {solo = L["Solo"]} } },
flickerstreak@118 174 { "combat", { {combat = L["In Combat"]}, {nocombat = L["Out of Combat"]} } },
flickerstreak@109 175 }
flickerstreak@109 176
flickerstreak@109 177 local ruleSelect = { }
flickerstreak@109 178 local ruleMap = { }
flickerstreak@109 179 local optionMap = setmetatable({},{__mode="k"})
flickerstreak@109 180
flickerstreak@109 181 local pointTable = {
flickerstreak@109 182 NONE = " ",
flickerstreak@109 183 CENTER = L["Center"],
flickerstreak@109 184 LEFT = L["Left"],
flickerstreak@109 185 RIGHT = L["Right"],
flickerstreak@109 186 TOP = L["Top"],
flickerstreak@109 187 BOTTOM = L["Bottom"],
flickerstreak@109 188 TOPLEFT = L["Top Left"],
flickerstreak@109 189 TOPRIGHT = L["Top Right"],
flickerstreak@109 190 BOTTOMLEFT = L["Bottom Left"],
flickerstreak@109 191 BOTTOMRIGHT = L["Bottom Right"],
flickerstreak@109 192 }
flickerstreak@109 193
flickerstreak@109 194 -- unpack rules table into ruleSelect and ruleMap
flickerstreak@109 195 for _, c in ipairs(rules) do
flickerstreak@118 196 local rule, fields = unpack(c)
flickerstreak@118 197 for _, field in ipairs(fields) do
flickerstreak@118 198 local key, label = next(field)
flickerstreak@118 199 table.insert(ruleSelect, label)
flickerstreak@118 200 table.insert(ruleMap, key)
flickerstreak@109 201 end
flickerstreak@109 202 end
flickerstreak@109 203
flickerstreak@109 204 local stateOptions = {
flickerstreak@109 205 ordering = {
flickerstreak@109 206 name = L["Info"],
flickerstreak@109 207 order = 1,
flickerstreak@109 208 type = "group",
flickerstreak@109 209 args = {
flickerstreak@109 210 delete = {
flickerstreak@109 211 name = L["Delete this State"],
flickerstreak@109 212 order = -1,
flickerstreak@109 213 type = "execute",
flickerstreak@109 214 func = "DeleteState",
flickerstreak@109 215 },
flickerstreak@109 216 rename = {
flickerstreak@109 217 name = L["Name"],
flickerstreak@109 218 order = 1,
flickerstreak@109 219 type = "input",
flickerstreak@109 220 get = "GetName",
flickerstreak@109 221 set = "SetStateName",
flickerstreak@109 222 pattern = "^%w*$",
flickerstreak@109 223 usage = L["State names must be alphanumeric without spaces"],
flickerstreak@109 224 },
flickerstreak@109 225 ordering = {
flickerstreak@109 226 name = L["Evaluation Order"],
flickerstreak@109 227 desc = L["State transitions are evaluated in the order listed:\nMove a state up or down to change the order"],
flickerstreak@109 228 order = 2,
flickerstreak@109 229 type = "group",
flickerstreak@109 230 inline = true,
flickerstreak@109 231 args = {
flickerstreak@109 232 up = {
flickerstreak@109 233 name = L["Up"],
flickerstreak@109 234 order = 1,
flickerstreak@109 235 type = "execute",
flickerstreak@109 236 width = "half",
flickerstreak@109 237 func = "MoveStateUp",
flickerstreak@109 238 },
flickerstreak@109 239 down = {
flickerstreak@109 240 name = L["Down"],
flickerstreak@109 241 order = 2,
flickerstreak@109 242 type = "execute",
flickerstreak@109 243 width = "half",
flickerstreak@109 244 func = "MoveStateDown",
flickerstreak@109 245 }
flickerstreak@109 246 }
flickerstreak@109 247 }
flickerstreak@109 248 }
flickerstreak@109 249 },
flickerstreak@109 250 properties = {
flickerstreak@109 251 name = L["Properties"],
flickerstreak@109 252 order = 2,
flickerstreak@109 253 type = "group",
flickerstreak@109 254 args = {
flickerstreak@109 255 desc = {
flickerstreak@109 256 name = L["Set the properties for the bar when in this state"],
flickerstreak@109 257 order = 1,
flickerstreak@109 258 type = "description"
flickerstreak@109 259 },
flickerstreak@109 260 hide = {
flickerstreak@109 261 name = L["Hide Bar"],
flickerstreak@109 262 order = 90,
flickerstreak@109 263 type = "toggle",
flickerstreak@109 264 set = "SetProp",
flickerstreak@109 265 get = "GetProp",
flickerstreak@109 266 },
flickerstreak@109 267 --[[ BROKEN
flickerstreak@109 268 keybindState = {
flickerstreak@109 269 name = L["Override Keybinds"],
flickerstreak@109 270 desc = L["Set this state to maintain its own set of keybinds which override the defaults when active"],
flickerstreak@109 271 order = 91,
flickerstreak@109 272 type = "toggle",
flickerstreak@109 273 set = "SetProp",
flickerstreak@109 274 get = "GetProp",
flickerstreak@109 275 }, ]]
flickerstreak@109 276 position = {
flickerstreak@109 277 name = L["Position"],
flickerstreak@109 278 order = 92,
flickerstreak@109 279 type = "group",
flickerstreak@109 280 inline = true,
flickerstreak@109 281 args = {
flickerstreak@109 282 anchorEnable = {
flickerstreak@109 283 name = L["Reposition"],
flickerstreak@109 284 order = 1,
flickerstreak@109 285 type = "toggle",
flickerstreak@109 286 set = "SetProp",
flickerstreak@109 287 get = "GetProp",
flickerstreak@109 288 },
flickerstreak@109 289 anchorFrame = {
flickerstreak@109 290 name = L["Anchor Frame"],
flickerstreak@109 291 order = 2,
flickerstreak@109 292 type = "select",
flickerstreak@109 293 values = "GetAnchorFrames",
flickerstreak@109 294 set = "SetAnchorFrame",
flickerstreak@109 295 get = "GetAnchorFrame",
flickerstreak@109 296 disabled = "GetAnchorDisabled",
flickerstreak@109 297 hidden = "GetAnchorDisabled",
flickerstreak@109 298 },
flickerstreak@109 299 anchorPoint = {
flickerstreak@109 300 name = L["Point"],
flickerstreak@109 301 order = 3,
flickerstreak@109 302 type = "select",
flickerstreak@109 303 values = pointTable,
flickerstreak@109 304 set = "SetAnchorPointProp",
flickerstreak@109 305 get = "GetAnchorPointProp",
flickerstreak@109 306 disabled = "GetAnchorDisabled",
flickerstreak@109 307 hidden = "GetAnchorDisabled",
flickerstreak@109 308 },
flickerstreak@109 309 anchorRelPoint = {
flickerstreak@109 310 name = L["Relative Point"],
flickerstreak@109 311 order = 4,
flickerstreak@109 312 type = "select",
flickerstreak@109 313 values = pointTable,
flickerstreak@109 314 set = "SetAnchorPointProp",
flickerstreak@109 315 get = "GetAnchorPointProp",
flickerstreak@109 316 disabled = "GetAnchorDisabled",
flickerstreak@109 317 hidden = "GetAnchorDisabled",
flickerstreak@109 318 },
flickerstreak@109 319 anchorX = {
flickerstreak@109 320 name = L["X Offset"],
flickerstreak@109 321 order = 5,
flickerstreak@109 322 type = "range",
flickerstreak@109 323 min = -100,
flickerstreak@109 324 max = 100,
flickerstreak@109 325 step = 1,
flickerstreak@109 326 set = "SetProp",
flickerstreak@109 327 get = "GetProp",
flickerstreak@109 328 disabled = "GetAnchorDisabled",
flickerstreak@109 329 hidden = "GetAnchorDisabled",
flickerstreak@109 330 },
flickerstreak@109 331 anchorY = {
flickerstreak@109 332 name = L["Y Offset"],
flickerstreak@109 333 order = 6,
flickerstreak@109 334 type = "range",
flickerstreak@109 335 min = -100,
flickerstreak@109 336 max = 100,
flickerstreak@109 337 step = 1,
flickerstreak@109 338 set = "SetProp",
flickerstreak@109 339 get = "GetProp",
flickerstreak@109 340 disabled = "GetAnchorDisabled",
flickerstreak@109 341 hidden = "GetAnchorDisabled",
flickerstreak@109 342 },
flickerstreak@109 343 },
flickerstreak@109 344 },
flickerstreak@109 345 scale = {
flickerstreak@109 346 name = L["Scale"],
flickerstreak@109 347 order = 93,
flickerstreak@109 348 type = "group",
flickerstreak@109 349 inline = true,
flickerstreak@109 350 args = {
flickerstreak@109 351 enableScale = {
flickerstreak@109 352 name = L["Set New Scale"],
flickerstreak@109 353 order = 1,
flickerstreak@109 354 type = "toggle",
flickerstreak@109 355 set = "SetProp",
flickerstreak@109 356 get = "GetProp",
flickerstreak@109 357 },
flickerstreak@109 358 scale = {
flickerstreak@109 359 name = L["Scale"],
flickerstreak@109 360 order = 2,
flickerstreak@109 361 type = "range",
flickerstreak@109 362 min = 0.25,
flickerstreak@109 363 max = 2.5,
flickerstreak@109 364 step = 0.05,
flickerstreak@109 365 isPercent = true,
flickerstreak@109 366 set = "SetProp",
flickerstreak@109 367 get = "GetScale",
flickerstreak@109 368 disabled = "GetScaleDisabled",
flickerstreak@109 369 hidden = "GetScaleDisabled",
flickerstreak@109 370 },
flickerstreak@109 371 },
flickerstreak@109 372 },
flickerstreak@109 373 alpha = {
flickerstreak@109 374 name = L["Transparency"],
flickerstreak@109 375 order = 94,
flickerstreak@109 376 type = "group",
flickerstreak@109 377 inline = true,
flickerstreak@109 378 args = {
flickerstreak@109 379 enableAlpha = {
flickerstreak@109 380 name = L["Set Transparency"],
flickerstreak@109 381 order = 1,
flickerstreak@109 382 type = "toggle",
flickerstreak@109 383 set = "SetProp",
flickerstreak@109 384 get = "GetProp",
flickerstreak@109 385 },
flickerstreak@109 386 alpha = {
flickerstreak@109 387 name = L["Transparency"],
flickerstreak@109 388 order = 2,
flickerstreak@109 389 type = "range",
flickerstreak@109 390 min = 0,
flickerstreak@109 391 max = 1,
flickerstreak@109 392 step = 0.01,
flickerstreak@109 393 bigStep = 0.05,
flickerstreak@109 394 isPercent = true,
flickerstreak@109 395 set = "SetProp",
flickerstreak@109 396 get = "GetAlpha",
flickerstreak@109 397 disabled = "GetAlphaDisabled",
flickerstreak@109 398 hidden = "GetAlphaDisabled",
flickerstreak@109 399 },
flickerstreak@109 400 },
flickerstreak@109 401 },
flickerstreak@109 402 },
flickerstreak@109 403 plugins = { }
flickerstreak@109 404 },
flickerstreak@109 405 rules = {
flickerstreak@109 406 name = L["Rule"],
flickerstreak@109 407 order = 3,
flickerstreak@109 408 type = "group",
flickerstreak@109 409 args = {
flickerstreak@109 410 mode = {
flickerstreak@109 411 name = L["Select this state"],
flickerstreak@109 412 order = 2,
flickerstreak@109 413 type = "select",
flickerstreak@109 414 style = "radio",
flickerstreak@109 415 values = {
flickerstreak@109 416 default = L["by default"],
flickerstreak@109 417 any = L["when ANY of these"],
flickerstreak@109 418 all = L["when ALL of these"],
flickerstreak@109 419 custom = L["via custom rule"],
flickerstreak@109 420 keybind = L["via keybinding"],
flickerstreak@109 421 },
flickerstreak@109 422 set = "SetType",
flickerstreak@109 423 get = "GetType",
flickerstreak@109 424 },
flickerstreak@109 425 clear = {
flickerstreak@109 426 name = L["Clear All"],
flickerstreak@109 427 order = 3,
flickerstreak@109 428 type = "execute",
flickerstreak@109 429 hidden = "GetClearAllDisabled",
flickerstreak@109 430 disabled = "GetClearAllDisabled",
flickerstreak@109 431 func = "ClearAllConditions",
flickerstreak@109 432 },
flickerstreak@109 433 inputs = {
flickerstreak@109 434 name = L["Conditions"],
flickerstreak@109 435 order = 4,
flickerstreak@109 436 type = "multiselect",
flickerstreak@109 437 hidden = "GetConditionsDisabled",
flickerstreak@109 438 disabled = "GetConditionsDisabled",
flickerstreak@109 439 values = ruleSelect,
flickerstreak@109 440 set = "SetCondition",
flickerstreak@109 441 get = "GetCondition",
flickerstreak@109 442 },
flickerstreak@109 443 custom = {
flickerstreak@109 444 name = L["Custom Rule"],
flickerstreak@109 445 order = 5,
flickerstreak@109 446 type = "input",
flickerstreak@109 447 multiline = true,
flickerstreak@109 448 hidden = "GetCustomDisabled",
flickerstreak@109 449 disabled = "GetCustomDisabled",
flickerstreak@109 450 desc = L["Syntax like macro rules: see preset rules for examples"],
flickerstreak@109 451 set = "SetCustomRule",
flickerstreak@109 452 get = "GetCustomRule",
flickerstreak@109 453 validate = "ValidateCustomRule",
flickerstreak@109 454 },
flickerstreak@109 455 keybind = {
flickerstreak@109 456 name = L["Keybinding"],
flickerstreak@109 457 order = 6,
flickerstreak@109 458 inline = true,
flickerstreak@109 459 hidden = "GetKeybindDisabled",
flickerstreak@109 460 disabled = "GetKeybindDisabled",
flickerstreak@109 461 type = "group",
flickerstreak@109 462 args = {
flickerstreak@109 463 desc = {
flickerstreak@109 464 name = L["Invoking a state keybind toggles an override of all other transition rules."],
flickerstreak@109 465 order = 1,
flickerstreak@109 466 type = "description",
flickerstreak@109 467 },
flickerstreak@109 468 keybind = {
flickerstreak@109 469 name = L["State Hotkey"],
flickerstreak@109 470 desc = L["Define an override toggle keybind"],
flickerstreak@109 471 order = 2,
flickerstreak@109 472 type = "keybinding",
flickerstreak@109 473 set = "SetKeybind",
flickerstreak@109 474 get = "GetKeybind",
flickerstreak@109 475 },
flickerstreak@109 476 },
flickerstreak@109 477 },
flickerstreak@109 478 },
flickerstreak@109 479 },
flickerstreak@109 480 }
flickerstreak@109 481
flickerstreak@109 482 local handlers = { }
flickerstreak@109 483 local meta = {
flickerstreak@109 484 __index = function(self, key)
flickerstreak@109 485 for _, h in pairs(handlers) do
flickerstreak@109 486 if h[key] then
flickerstreak@109 487 return h[key]
flickerstreak@109 488 end
flickerstreak@109 489 end
flickerstreak@109 490 end,
flickerstreak@109 491 }
flickerstreak@109 492 local StateHandler = setmetatable({ }, meta)
flickerstreak@109 493 local proto = { __index = StateHandler }
flickerstreak@109 494
flickerstreak@109 495 function RegisterPropertyOptions( field, options, handler )
flickerstreak@109 496 stateOptions.properties.plugins[field] = options
flickerstreak@109 497 handlers[field] = handler
flickerstreak@109 498 end
flickerstreak@109 499
flickerstreak@109 500 function UnregisterPropertyOptions( field )
flickerstreak@109 501 stateOptions.properties.plugins[field] = nil
flickerstreak@109 502 handlers[field] = nil
flickerstreak@109 503 end
flickerstreak@109 504
flickerstreak@109 505 function StateHandler:New( bar, opts )
flickerstreak@109 506 local self = setmetatable(
flickerstreak@109 507 {
flickerstreak@109 508 bar = bar
flickerstreak@109 509 },
flickerstreak@109 510 proto )
flickerstreak@109 511
flickerstreak@109 512 function self:GetName()
flickerstreak@109 513 return opts.name
flickerstreak@109 514 end
flickerstreak@109 515
flickerstreak@109 516 function self:SetName(name)
flickerstreak@109 517 opts.name = name
flickerstreak@109 518 end
flickerstreak@109 519
flickerstreak@109 520 function self:GetOrder()
flickerstreak@109 521 return opts.order
flickerstreak@109 522 end
flickerstreak@109 523
flickerstreak@109 524 -- get reference to states table: even if the bar
flickerstreak@109 525 -- name changes the states table ref won't
flickerstreak@109 526 self.states = tbuild(module.db.profile.bars, bar:GetName(), "states")
flickerstreak@109 527 self.state = tbuild(self.states, opts.name)
flickerstreak@109 528
flickerstreak@109 529 opts.order = self:GetRuleField("order")
flickerstreak@109 530 if opts.order == nil then
flickerstreak@109 531 -- add after the highest
flickerstreak@109 532 opts.order = 100
flickerstreak@109 533 for _, state in pairs(self.states) do
flickerstreak@109 534 local x = tonumber(tfetch(state, "rule", "order"))
flickerstreak@109 535 if x and x >= opts.order then
flickerstreak@109 536 opts.order = x + 1
flickerstreak@109 537 end
flickerstreak@109 538 end
flickerstreak@109 539 self:SetRuleField("order",opts.order)
flickerstreak@109 540 end
flickerstreak@109 541
flickerstreak@109 542 return self
flickerstreak@109 543 end
flickerstreak@109 544
flickerstreak@109 545 -- helper methods
flickerstreak@109 546
flickerstreak@109 547 function StateHandler:SetRuleField( key, value, ... )
flickerstreak@109 548 tbuild(self.state, "rule", ...)[key] = value
flickerstreak@109 549 end
flickerstreak@109 550
flickerstreak@109 551 function StateHandler:GetRuleField( ... )
flickerstreak@109 552 return tfetch(self.state, "rule", ...)
flickerstreak@109 553 end
flickerstreak@109 554
flickerstreak@109 555 function StateHandler:FixAll( setkey )
flickerstreak@109 556 -- if multiple selections in the same group are chosen when 'all' is selected,
flickerstreak@109 557 -- keep only one of them. If changing the mode, the first in the fields list will
flickerstreak@109 558 -- be chosen arbitrarily. Otherwise, if selecting a new checkbox from the field-set,
flickerstreak@109 559 -- it will be retained.
flickerstreak@109 560 local notified = false
flickerstreak@109 561 if self:GetRuleField("type") == "all" then
flickerstreak@109 562 for _, c in ipairs(rules) do
flickerstreak@118 563 local rule, fields = unpack(c)
flickerstreak@109 564 local once = false
flickerstreak@109 565 if setkey then
flickerstreak@109 566 for idx, field in ipairs(fields) do
flickerstreak@109 567 if next(field) == setkey then
flickerstreak@109 568 once = true
flickerstreak@109 569 end
flickerstreak@109 570 end
flickerstreak@109 571 end
flickerstreak@109 572 for idx, field in ipairs(fields) do
flickerstreak@109 573 local key = next(field)
flickerstreak@109 574 if self:GetRuleField("values",key) then
flickerstreak@109 575 if once and key ~= setkey then
flickerstreak@109 576 self:SetRuleField(key,false,"values")
flickerstreak@109 577 if not setkey and not notified then
flickerstreak@109 578 ReAction:UserError(L["Warning: one or more incompatible rules were turned off"])
flickerstreak@109 579 notified = true
flickerstreak@109 580 end
flickerstreak@109 581 end
flickerstreak@109 582 once = true
flickerstreak@109 583 end
flickerstreak@109 584 end
flickerstreak@109 585 end
flickerstreak@109 586 end
flickerstreak@109 587 end
flickerstreak@109 588
flickerstreak@109 589 function StateHandler:GetNeighbors()
flickerstreak@109 590 local before, after
flickerstreak@109 591 for k, v in pairs(self.states) do
flickerstreak@109 592 local o = tonumber(tfetch(v, "rule", "order"))
flickerstreak@109 593 if o and k ~= self:GetName() then
flickerstreak@109 594 local obefore = tfetch(self.states,before,"rule","order")
flickerstreak@109 595 local oafter = tfetch(self.states,after,"rule","order")
flickerstreak@109 596 if o < self:GetOrder() and (not obefore or obefore < o) then
flickerstreak@109 597 before = k
flickerstreak@109 598 end
flickerstreak@109 599 if o > self:GetOrder() and (not oafter or oafter > o) then
flickerstreak@109 600 after = k
flickerstreak@109 601 end
flickerstreak@109 602 end
flickerstreak@109 603 end
flickerstreak@109 604 return before, after
flickerstreak@109 605 end
flickerstreak@109 606
flickerstreak@109 607 function StateHandler:SwapOrder( a, b )
flickerstreak@109 608 -- do options table
flickerstreak@109 609 local args = optionMap[self.bar].args
flickerstreak@109 610 args[a].order, args[b].order = args[b].order, args[a].order
flickerstreak@109 611 -- do profile
flickerstreak@109 612 a = tbuild(self.states, a, "rule")
flickerstreak@109 613 b = tbuild(self.states, b, "rule")
flickerstreak@109 614 a.order, b.order = b.order, a.order
flickerstreak@109 615 end
flickerstreak@109 616
flickerstreak@109 617 -- handler methods
flickerstreak@109 618
flickerstreak@109 619 function StateHandler:GetProp( info )
flickerstreak@109 620 -- gets property of the same name as the options arg
flickerstreak@109 621 return GetProperty(self.bar, self:GetName(), info[#info])
flickerstreak@109 622 end
flickerstreak@109 623
flickerstreak@109 624 function StateHandler:SetProp( info, value )
flickerstreak@109 625 -- sets property of the same name as the options arg
flickerstreak@109 626 SetProperty(self.bar, self:GetName(), info[#info], value)
flickerstreak@109 627 end
flickerstreak@109 628
flickerstreak@109 629 function StateHandler:DeleteState()
flickerstreak@109 630 if self.states[self:GetName()] then
flickerstreak@109 631 self.states[self:GetName()] = nil
flickerstreak@109 632 ApplyStates(self.bar)
flickerstreak@109 633 end
flickerstreak@109 634 optionMap[self.bar].args[self:GetName()] = nil
flickerstreak@109 635 end
flickerstreak@109 636
flickerstreak@109 637 function StateHandler:SetStateName(info, value)
flickerstreak@109 638 -- check for existing state name
flickerstreak@109 639 if self.states[value] then
flickerstreak@109 640 ReAction:UserError(format(L["State named '%s' already exists"],value))
flickerstreak@109 641 return
flickerstreak@109 642 end
flickerstreak@109 643 local args = optionMap[self.bar].args
flickerstreak@109 644 local name = self:GetName()
flickerstreak@109 645 self.states[value], args[value], self.states[name], args[name] = self.states[name], args[name], nil, nil
flickerstreak@109 646 self:SetName(value)
flickerstreak@109 647 ApplyStates(self.bar)
flickerstreak@109 648 ReAction:ShowEditor(self.bar, moduleID, value)
flickerstreak@109 649 end
flickerstreak@109 650
flickerstreak@109 651 function StateHandler:MoveStateUp()
flickerstreak@109 652 local before, after = self:GetNeighbors()
flickerstreak@109 653 if before then
flickerstreak@109 654 self:SwapOrder(before, self:GetName())
flickerstreak@109 655 ApplyStates(self.bar)
flickerstreak@109 656 end
flickerstreak@109 657 end
flickerstreak@109 658
flickerstreak@109 659 function StateHandler:MoveStateDown()
flickerstreak@109 660 local before, after = self:GetNeighbors()
flickerstreak@109 661 if after then
flickerstreak@109 662 self:SwapOrder(self:GetName(), after)
flickerstreak@109 663 ApplyStates(self.bar)
flickerstreak@109 664 end
flickerstreak@109 665 end
flickerstreak@109 666
flickerstreak@109 667 function StateHandler:GetAnchorDisabled()
flickerstreak@109 668 return not GetProperty(self.bar, self:GetName(), "anchorEnable")
flickerstreak@109 669 end
flickerstreak@109 670
flickerstreak@109 671 function StateHandler:GetAnchorFrames(info)
flickerstreak@109 672 self._anchorframes = self._anchorframes or { }
flickerstreak@109 673 table.wipe(self._anchorframes)
flickerstreak@109 674
flickerstreak@109 675 table.insert(self._anchorframes, "UIParent")
flickerstreak@109 676 for name, bar in ReAction:IterateBars() do
flickerstreak@109 677 table.insert(self._anchorframes, bar:GetFrame():GetName())
flickerstreak@109 678 end
flickerstreak@109 679 return self._anchorframes
flickerstreak@109 680 end
flickerstreak@109 681
flickerstreak@109 682 function StateHandler:GetAnchorFrame(info)
flickerstreak@109 683 local value = self:GetProp(info)
flickerstreak@109 684 for k,v in pairs(self._anchorframes) do
flickerstreak@109 685 if v == value then
flickerstreak@109 686 return k
flickerstreak@109 687 end
flickerstreak@109 688 end
flickerstreak@109 689 end
flickerstreak@109 690
flickerstreak@109 691 function StateHandler:SetAnchorFrame(info, value)
flickerstreak@109 692 local f = _G[self._anchorframes[value]]
flickerstreak@109 693 if f then
flickerstreak@157 694 self.bar:SetFrameRef("anchor-"..self:GetName(), f)
flickerstreak@109 695 self:SetProp(info, f:GetName())
flickerstreak@109 696 end
flickerstreak@109 697 end
flickerstreak@109 698
flickerstreak@109 699 function StateHandler:SetAnchorPointProp(info, value)
flickerstreak@109 700 self:SetProp(info, value ~= "NONE" and value or nil)
flickerstreak@109 701 end
flickerstreak@109 702
flickerstreak@109 703 function StateHandler:GetAnchorPointProp(info)
flickerstreak@109 704 return self:GetProp(info) or "NONE"
flickerstreak@109 705 end
flickerstreak@109 706
flickerstreak@109 707 function StateHandler:GetScale(info)
flickerstreak@109 708 return self:GetProp(info) or 1.0
flickerstreak@109 709 end
flickerstreak@109 710
flickerstreak@109 711 function StateHandler:GetScaleDisabled()
flickerstreak@109 712 return not GetProperty(self.bar, self:GetName(), "enableScale")
flickerstreak@109 713 end
flickerstreak@109 714
flickerstreak@109 715 function StateHandler:GetAlpha(info)
flickerstreak@109 716 return self:GetProp(info) or 1.0
flickerstreak@109 717 end
flickerstreak@109 718
flickerstreak@109 719 function StateHandler:GetAlphaDisabled()
flickerstreak@109 720 return not GetProperty(self.bar, self:GetName(), "enableAlpha")
flickerstreak@109 721 end
flickerstreak@109 722
flickerstreak@109 723 function StateHandler:SetType(info, value)
flickerstreak@109 724 self:SetRuleField("type", value)
flickerstreak@109 725 self:FixAll()
flickerstreak@109 726 ApplyStates(self.bar)
flickerstreak@109 727 end
flickerstreak@109 728
flickerstreak@109 729 function StateHandler:GetType()
flickerstreak@109 730 return self:GetRuleField("type")
flickerstreak@109 731 end
flickerstreak@109 732
flickerstreak@109 733 function StateHandler:GetClearAllDisabled()
flickerstreak@109 734 local t = self:GetRuleField("type")
flickerstreak@109 735 return not( t == "any" or t == "all" or t == "custom")
flickerstreak@109 736 end
flickerstreak@109 737
flickerstreak@109 738 function StateHandler:ClearAllConditions()
flickerstreak@109 739 local t = self:GetRuleField("type")
flickerstreak@109 740 if t == "custom" then
flickerstreak@109 741 self:SetRuleField("custom","")
flickerstreak@109 742 elseif t == "any" or t == "all" then
flickerstreak@109 743 self:SetRuleField("values", {})
flickerstreak@109 744 end
flickerstreak@109 745 ApplyStates(self.bar)
flickerstreak@109 746 end
flickerstreak@109 747
flickerstreak@109 748 function StateHandler:GetConditionsDisabled()
flickerstreak@109 749 local t = self:GetRuleField("type")
flickerstreak@109 750 return not( t == "any" or t == "all")
flickerstreak@109 751 end
flickerstreak@109 752
flickerstreak@109 753 function StateHandler:SetCondition(info, key, value)
flickerstreak@109 754 self:SetRuleField(ruleMap[key], value or nil, "values")
flickerstreak@109 755 if value then
flickerstreak@109 756 self:FixAll(ruleMap[key])
flickerstreak@109 757 end
flickerstreak@109 758 ApplyStates(self.bar)
flickerstreak@109 759 end
flickerstreak@109 760
flickerstreak@109 761 function StateHandler:GetCondition(info, key)
flickerstreak@109 762 return self:GetRuleField("values", ruleMap[key]) or false
flickerstreak@109 763 end
flickerstreak@109 764
flickerstreak@109 765 function StateHandler:GetCustomDisabled()
flickerstreak@109 766 return self:GetRuleField("type") ~= "custom"
flickerstreak@109 767 end
flickerstreak@109 768
flickerstreak@109 769 function StateHandler:SetCustomRule(info, value)
flickerstreak@109 770 self:SetRuleField("custom",value)
flickerstreak@109 771 ApplyStates(self.bar)
flickerstreak@109 772 end
flickerstreak@109 773
flickerstreak@109 774 function StateHandler:GetCustomRule()
flickerstreak@109 775 return self:GetRuleField("custom") or ""
flickerstreak@109 776 end
flickerstreak@109 777
flickerstreak@109 778 function StateHandler:ValidateCustomRule(info, value)
flickerstreak@109 779 local s = value:gsub("%s","") -- remove all spaces
flickerstreak@109 780 -- unfortunately %b and captures don't support the '+' notation, or this would be considerably simpler
flickerstreak@109 781 repeat
flickerstreak@109 782 if s == "" then
flickerstreak@109 783 return true
flickerstreak@109 784 end
flickerstreak@109 785 local c, r = s:match("(%b[])(.*)")
flickerstreak@109 786 if c == nil and s and #s > 0 then
flickerstreak@109 787 return format(L["Invalid custom rule '%s': each clause must appear within [brackets]"],value or "")
flickerstreak@109 788 end
flickerstreak@109 789 s = r
flickerstreak@109 790 until c == nil
flickerstreak@109 791 return true
flickerstreak@109 792 end
flickerstreak@109 793
flickerstreak@109 794 function StateHandler:GetKeybindDisabled()
flickerstreak@109 795 return self:GetRuleField("type") ~= "keybind"
flickerstreak@109 796 end
flickerstreak@109 797
flickerstreak@109 798 function StateHandler:GetKeybind()
flickerstreak@109 799 return self:GetRuleField("keybind")
flickerstreak@109 800 end
flickerstreak@109 801
flickerstreak@109 802 function StateHandler:SetKeybind(info, value)
flickerstreak@109 803 if value and #value == 0 then
flickerstreak@109 804 value = nil
flickerstreak@109 805 end
flickerstreak@109 806 self:SetRuleField("keybind",value)
flickerstreak@109 807 ApplyStates(self.bar)
flickerstreak@109 808 end
flickerstreak@109 809
flickerstreak@109 810 local function CreateStateOptions(bar, name)
flickerstreak@109 811 local opts = {
flickerstreak@109 812 type = "group",
flickerstreak@109 813 name = name,
flickerstreak@109 814 childGroups = "tab",
flickerstreak@109 815 args = stateOptions
flickerstreak@109 816 }
flickerstreak@109 817
flickerstreak@109 818 opts.handler = StateHandler:New(bar,opts)
flickerstreak@109 819
flickerstreak@109 820 return opts
flickerstreak@109 821 end
flickerstreak@109 822
flickerstreak@109 823 function module:GetBarOptions(bar)
flickerstreak@109 824 local private = { }
flickerstreak@109 825 local states = tbuild(module.db.profile.bars, bar:GetName(), "states")
flickerstreak@109 826 local options = {
flickerstreak@109 827 name = L["Dynamic State"],
flickerstreak@109 828 type = "group",
flickerstreak@109 829 order = -1,
flickerstreak@109 830 childGroups = "tree",
flickerstreak@109 831 disabled = InCombatLockdown,
flickerstreak@109 832 args = {
flickerstreak@109 833 __desc__ = {
flickerstreak@109 834 name = L["States are evaluated in the order they are listed"],
flickerstreak@109 835 order = 1,
flickerstreak@109 836 type = "description",
flickerstreak@109 837 },
flickerstreak@109 838 __new__ = {
flickerstreak@109 839 name = L["New State..."],
flickerstreak@109 840 order = 2,
flickerstreak@109 841 type = "group",
flickerstreak@109 842 args = {
flickerstreak@109 843 name = {
flickerstreak@109 844 name = L["State Name"],
flickerstreak@109 845 desc = L["Set a name for the new state"],
flickerstreak@109 846 order = 1,
flickerstreak@109 847 type = "input",
flickerstreak@109 848 get = function() return private.newstatename or "" end,
flickerstreak@109 849 set = function(info,value) private.newstatename = value end,
flickerstreak@109 850 pattern = "^%w*$",
flickerstreak@109 851 usage = L["State names must be alphanumeric without spaces"],
flickerstreak@109 852 },
flickerstreak@109 853 create = {
flickerstreak@109 854 name = L["Create State"],
flickerstreak@109 855 order = 2,
flickerstreak@109 856 type = "execute",
flickerstreak@109 857 func = function ()
flickerstreak@109 858 local name = private.newstatename
flickerstreak@109 859 if states[name] then
flickerstreak@109 860 ReAction:UserError(format(L["State named '%s' already exists"],name))
flickerstreak@109 861 else
flickerstreak@109 862 -- TODO: select default state options and pass as final argument
flickerstreak@109 863 states[name] = { }
flickerstreak@109 864 optionMap[bar].args[name] = CreateStateOptions(bar,name)
flickerstreak@109 865 ReAction:ShowEditor(bar, moduleID, name)
flickerstreak@109 866 private.newstatename = ""
flickerstreak@109 867 end
flickerstreak@109 868 end,
flickerstreak@109 869 disabled = function()
flickerstreak@109 870 local name = private.newstatename or ""
flickerstreak@109 871 return #name == 0 or name:find("%W")
flickerstreak@109 872 end,
flickerstreak@109 873 }
flickerstreak@109 874 }
flickerstreak@109 875 }
flickerstreak@109 876 }
flickerstreak@109 877 }
flickerstreak@109 878 for name, config in pairs(states) do
flickerstreak@109 879 options.args[name] = CreateStateOptions(bar,name)
flickerstreak@109 880 end
flickerstreak@109 881 optionMap[bar] = options
flickerstreak@109 882 return options
flickerstreak@109 883 end
flickerstreak@109 884 end
flickerstreak@109 885
flickerstreak@109 886 -- Module API --
flickerstreak@109 887
flickerstreak@109 888 -- Pass in a property field-name, an implementation secure snippet, a static options table, and an
flickerstreak@109 889 -- optional options handler method-table
flickerstreak@109 890 --
flickerstreak@109 891 -- The options table is static, i.e. not bar-specific and should only reference handler method
flickerstreak@109 892 -- strings (either existing ones or those added via optHandler). The existing options are ordered
flickerstreak@109 893 -- 90-99. Order #1 is reserved for the heading.
flickerstreak@109 894 --
flickerstreak@109 895 -- The contents of optHandler, if provided, will be added to the existing StateHandler options metatable.
flickerstreak@109 896 -- See above, for existing API. In particular see the properties set up in the New method: self.bar,
flickerstreak@109 897 -- self.states, and self:GetName(), and the generic property handlers self:GetProp() and self:SetProp().
flickerstreak@109 898 --
flickerstreak@109 899 function module:RegisterStateProperty( field, snippetHandler, options, optHandler )
flickerstreak@109 900 RegisterProperty(field, snippetHandler)
flickerstreak@109 901 RegisterPropertyOptions(field, options, optHandler)
flickerstreak@109 902 end
flickerstreak@109 903
flickerstreak@109 904 function module:UnregisterStateProperty( field )
flickerstreak@109 905 UnregisterProperty(field)
flickerstreak@109 906 UnregisterPropertyOptions(field)
flickerstreak@109 907 end
flickerstreak@109 908
flickerstreak@109 909
flickerstreak@109 910 -- Export methods to Bar class --
flickerstreak@109 911
flickerstreak@109 912 ReAction.Bar.GetStateProperty = GetProperty
flickerstreak@109 913 ReAction.Bar.SetStateProperty = SetProperty