comparison modules/ReAction_State/ReAction_State.lua @ 68:fcb5dad031f9

State transitions now working. Keybind toggle states, stance switching, etc. Hide bar is the only working state property, but the config is there for page #, re-anchoring, re-scaling, and keybind override.
author Flick <flickerstreak@gmail.com>
date Tue, 03 Jun 2008 22:57:34 +0000
parents 84721edaa749
children
comparison
equal deleted inserted replaced
67:84721edaa749 68:fcb5dad031f9
32 end 32 end
33 return t 33 return t
34 end 34 end
35 35
36 -- PRIVATE -- 36 -- PRIVATE --
37 local InitRules, ApplyStates 37
38 local InitRules, ApplyStates, SetProperty, GetProperty
38 do 39 do
39 -- As far as I can tell the macro clauses are NOT locale-specific. 40 -- As far as I can tell the macro clauses are NOT locale-specific.
40 local ruleformats = { 41 local ruleformats = {
41 stealth = "stealth", 42 stealth = "stealth",
42 nostealth = "nostealth", 43 nostealth = "nostealth",
87 ruleformats.bear = ("form:%d"):format(bear) 88 ruleformats.bear = ("form:%d"):format(bear)
88 ruleformats.cat = ("form:%d"):format(cat) 89 ruleformats.cat = ("form:%d"):format(cat)
89 ruleformats.treeOrMoonkin = ("form:%d"):format(treekin) 90 ruleformats.treeOrMoonkin = ("form:%d"):format(treekin)
90 end 91 end
91 92
93 -- return a new array of keys of table 't', sorted by comparing
94 -- sub-fields (obtained via tfetch) of the table values
95 local function fieldsort( t, ... )
96 local r = { }
97 for k in pairs(t) do
98 table.insert(r,k)
99 end
100 local dotdotdot = { ... }
101 table.sort(r, function(lhs, rhs)
102 local olhs = tfetch(t[lhs], unpack(dotdotdot)) or 0
103 local orhs = tfetch(t[rhs], unpack(dotdotdot)) or 0
104 return olhs < orhs
105 end)
106 return r
107 end
108
92 local function BuildRuleString(states) 109 local function BuildRuleString(states)
93 local s = "" 110 local s = ""
94 local default 111 local default
95 local sorted = { } 112 local sorted = fieldsort(states, "rule", "order")
96 for name in pairs(states) do
97 table.insert(sorted,name)
98 end
99 table.sort(sorted, function(lhs, rhs)
100 local olhs = tfetch(states[lhs],"rule","order") or 0
101 local orhs = tfetch(states[rhs],"rule","order") or 0
102 return olhs < orhs
103 end)
104 for idx, name in ipairs(sorted) do 113 for idx, name in ipairs(sorted) do
105 local state = states[name] 114 local state = states[name]
106 local semi = #s > 0 and "; " or "" 115 local semi = #s > 0 and "; " or ""
107 local mode = tfetch(state,"rule","type") 116 local mode = tfetch(state,"rule","type")
108 if mode == "default" then 117 if mode == "default" then
135 end 144 end
136 end 145 end
137 if default then 146 if default then
138 s = ("%s%s%s"):format(s, #s > 0 and "; " or "", default) 147 s = ("%s%s%s"):format(s, #s > 0 and "; " or "", default)
139 end 148 end
140 return s 149 return s, default
141 end 150 end
142 151
143 local drivers = setmetatable({},{__mode="k"}) 152 local drivers = setmetatable({},{__mode="k"})
153 local propertyFuncs = { }
144 154
145 function ApplyStates( bar ) 155 function ApplyStates( bar )
146 local states = tfetch(module.db.profile.bars, bar:GetName(), "states") 156 local states = tfetch(module.db.profile.bars, bar:GetName(), "states")
147 if states then 157 if states then
148 local frame = bar:GetFrame() 158 local frame = bar:GetFrame()
149 local string = BuildRuleString(states) 159 local string, default = BuildRuleString(states)
150 ReAction:Print("'"..string.."'")
151 if string and #string > 0 then 160 if string and #string > 0 then
161 drivers[bar] = true
162 -- register a map for each "statemap-reaction-XXX" to set 'state' to 'XXX'
163 -- UNLESS we're in a keybound state AND there's a default state, in which case
164 -- all keybound states go back to themselves.
165 local keybindprefix
166 if default then
167 local tmp = { }
168 for state, config in pairs(states) do
169 if tfetch(config, "rule", "type") == "keybind" then
170 bar:SetStateKeybind(tfetch(config,"rule","keybind"), state, tfetch(config,"rule","keybindreturn") or default or 0)
171 table.insert(tmp, ("%s:%s"):format(state,state))
172 end
173 end
174 if #tmp > 0 then
175 table.insert(tmp,"") -- to get a final ';'
176 end
177 keybindprefix = table.concat(tmp,";")
178 end
179 for state in pairs(states) do
180 frame:SetAttribute(("statemap-reaction-%s"):format(state), ("%s%s"):format(keybindprefix or "",state))
181 end
152 -- register a handler to set the value of attribute "state-reaction" 182 -- register a handler to set the value of attribute "state-reaction"
153 -- in response to events as per the rule string 183 -- in response to events as per the rule string
154 RegisterStateDriver(frame, "reaction", string) 184 RegisterStateDriver(frame, "reaction", string)
155 drivers[bar] = true 185 SecureStateHeader_Refresh(frame)
156 -- register a trivial map for each "statemap-reaction-XXX" to set 'state' to 'XXX'
157 for state in pairs(states) do
158 frame:SetAttribute(("statemap-reaction-%s"):format(state), state)
159 end
160 elseif drivers[bar] then 186 elseif drivers[bar] then
161 UnregisterStateDriver(frame, "reaction") 187 UnregisterStateDriver(frame, "reaction")
162 drivers[bar] = nil 188 drivers[bar] = nil
163 end 189 end
164 end 190 for k, f in pairs(propertyFuncs) do
165 end 191 f(bar, states)
166 end 192 end
167 193 end
168 194 end
169 -- module event handlers 195
196 function GetProperty( bar, state, propname )
197 return tfetch(module.db.profile.bars, bar:GetName(), "states", state, propname)
198 end
199
200 function SetProperty( bar, state, propname, value )
201 local states = tbuild(module.db.profile.bars, bar:GetName(), "states")
202 tbuild(states, state)[propname] = value
203 local f = propertyFuncs[propname]
204 if f then
205 f(bar, states)
206 end
207 end
208
209 -- state property functions
210 function propertyFuncs.hide( bar, states )
211 local tmp = { }
212 for state, config in pairs(states) do
213 if config.hide then
214 table.insert(tmp, state)
215 end
216 end
217 local s = table.concat(tmp,",")
218 bar:SetHideStates(s)
219 end
220
221 function propertyFuncs.page( bar, states )
222 local map = { }
223 for state, config in pairs(states) do
224 map[state] = config.page
225 end
226 bar:SetStatePageMap(state, map)
227 end
228
229 function propertyFuncs.keybindstate( bar, states )
230 local map = { }
231 for state, config in pairs(states) do
232 if config.keybindstate then
233 table.insert(map,state)
234 end
235 end
236 bar:SetStateKeybindOverrideMap(map)
237 end
238
239 function propertyFuncs.enableanchor( bar, states )
240
241 end
242
243 function propertyFuncs.anchorPoint( bar, states )
244
245 end
246
247 function propertyFuncs.anchorRelPoint( bar, states )
248
249 end
250
251 function propertyFuncs.anchorX( bar, states )
252
253 end
254
255 function propertyFuncs.anchorY( bar, states )
256
257 end
258
259 function propertyFuncs.enablescale( bar, states )
260
261 end
262
263 function propertyFuncs.scale( bar, states )
264
265 end
266
267 end
268
269
270
271 -- module event handlers --
272
170 function module:OnInitialize() 273 function module:OnInitialize()
171 self.db = ReAction.db:RegisterNamespace( moduleID, 274 self.db = ReAction.db:RegisterNamespace( moduleID,
172 { 275 {
173 profile = { 276 profile = {
174 bars = { }, 277 bars = { },
203 end 306 end
204 307
205 function module:OnRefreshBar(event, bar, name) 308 function module:OnRefreshBar(event, bar, name)
206 local c = self.db.profile.bars[name] 309 local c = self.db.profile.bars[name]
207 if c then 310 if c then
208 self:UpdateStates(bar) 311 ApplyStates(bar)
209 end 312 end
210 end 313 end
211 314
212 function module:OnEraseBar(event, bar, name) 315 function module:OnEraseBar(event, bar, name)
213 self.db.profile.bars[name] = nil 316 self.db.profile.bars[name] = nil
221 function module:OnConfigModeChanged(event, mode) 324 function module:OnConfigModeChanged(event, mode)
222 -- TODO: unregister all state drivers (temporarily) and hidestates 325 -- TODO: unregister all state drivers (temporarily) and hidestates
223 end 326 end
224 327
225 328
226 -- API --
227
228 function module:UpdateStates( bar )
229 ApplyStates(bar)
230 end
231
232 function module:CreateState( bar, name )
233 local states = tbuild(self.db.profile.bars, bar:GetName(), "states")
234 if states[name] then
235 ReAction:UserError(L["State named '%s' already exists"]:format(name))
236 else
237 states[name] = { }
238 end
239 end
240
241 function module:DeleteState( bar, name )
242 local states = tfetch(self.db.profile.bars, bar:GetName(), "states")
243 if states[name] then
244 states[name] = nil
245 self:UpdateStates(bar)
246 end
247 end
248 329
249 -- Options -- 330 -- Options --
250 331
251 local CreateBarOptions 332 local CreateBarOptions
252 do 333 do
276 357
277 local ruleSelect = { } 358 local ruleSelect = { }
278 local ruleMap = { } 359 local ruleMap = { }
279 local optionMap = setmetatable({},{__mode="k"}) 360 local optionMap = setmetatable({},{__mode="k"})
280 361
362 local pointTable = {
363 NONE = " ",
364 CENTER = L["Center"],
365 LEFT = L["Left"],
366 RIGHT = L["Right"],
367 TOP = L["Top"],
368 BOTTOM = L["Bottom"],
369 TOPLEFT = L["Top Left"],
370 TOPRIGHT = L["Top Right"],
371 BOTTOMLEFT = L["Bottom Left"],
372 BOTTOMRIGHT = L["Bottom Right"],
373 }
374
281 -- unpack rules table into ruleSelect and ruleMap 375 -- unpack rules table into ruleSelect and ruleMap
282 for _, c in ipairs(rules) do 376 for _, c in ipairs(rules) do
283 local rule, hidden, fields = unpack(c) 377 local rule, hidden, fields = unpack(c)
284 if not hidden then 378 if not hidden then
285 for _, field in ipairs(fields) do 379 for _, field in ipairs(fields) do
297 childGroups = "tab", 391 childGroups = "tab",
298 } 392 }
299 393
300 local states = tbuild(module.db.profile.bars, bar:GetName(), "states") 394 local states = tbuild(module.db.profile.bars, bar:GetName(), "states")
301 395
302 local function put( key, value, ... ) 396 local function update()
397 ApplyStates(bar)
398 end
399
400 local function setrule( key, value, ... )
303 tbuild(states, opts.name, "rule", ...)[key] = value 401 tbuild(states, opts.name, "rule", ...)[key] = value
304 end 402 end
305 403
306 local function fetch( ... ) 404 local function getrule( ... )
307 return tfetch(states, opts.name, "rule", ...) 405 return tfetch(states, opts.name, "rule", ...)
406 end
407
408 local function setprop(info, value)
409 SetProperty(bar, opts.name, info[#info], value)
410 end
411
412 local function getprop(info)
413 return GetProperty(bar, opts.name, info[#info])
308 end 414 end
309 415
310 local function fixall(setkey) 416 local function fixall(setkey)
311 -- if multiple selections in the same group are chosen when 'all' is selected, 417 -- if multiple selections in the same group are chosen when 'all' is selected,
312 -- keep only one of them. If changing the mode, the first in the fields list will 418 -- keep only one of them. If changing the mode, the first in the fields list will
315 local notified = false 421 local notified = false
316 for _, c in ipairs(rules) do 422 for _, c in ipairs(rules) do
317 local rule, hidden, fields = unpack(c) 423 local rule, hidden, fields = unpack(c)
318 local found = false 424 local found = false
319 for key in ipairs(fields) do 425 for key in ipairs(fields) do
320 if fetch("values",key) then 426 if getrule("values",key) then
321 if (found or setkey) and key ~= setkey then 427 if (found or setkey) and key ~= setkey then
322 put(key,false,"values") 428 setrule(key,false,"values")
323 if not setkey and not notified then 429 if not setkey and not notified then
324 ReAction:UserError(L["Warning: one or more incompatible rules were turned off"]) 430 ReAction:UserError(L["Warning: one or more incompatible rules were turned off"])
325 notified = true 431 notified = true
326 end 432 end
327 end 433 end
357 a = tbuild(states, a, "rule") 463 a = tbuild(states, a, "rule")
358 b = tbuild(states, b, "rule") 464 b = tbuild(states, b, "rule")
359 a.order, b.order = b.order, a.order 465 a.order, b.order = b.order, a.order
360 end 466 end
361 467
362 local function update() 468 local function anchordisable()
363 module:UpdateStates(bar) 469 return not GetProperty(bar, opts.name, "enableanchor")
364 end 470 end
365 471
366 472 tbuild(states, name)
367 opts.order = fetch("order") 473
474 opts.order = getrule("order")
368 if opts.order == nil then 475 if opts.order == nil then
369 -- add after the highest 476 -- add after the highest
370 opts.order = 100 477 opts.order = 100
371 for _, state in pairs(states) do 478 for _, state in pairs(states) do
372 local x = tonumber(tfetch(state, "rule", "order")) 479 local x = tonumber(tfetch(state, "rule", "order"))
373 if x and x >= opts.order then 480 if x and x >= opts.order then
374 opts.order = x + 1 481 opts.order = x + 1
375 end 482 end
376 end 483 end
377 put("order",opts.order) 484 setrule("order",opts.order)
378 end 485 end
379 486
380 opts.args = { 487 opts.args = {
381 properties = { 488 ordering = {
489 name = L["Info"],
490 order = 1,
382 type = "group", 491 type = "group",
383 name = L["Properties"],
384 order = 1,
385 args = { 492 args = {
386 delete = { 493 delete = {
494 name = L["Delete this State"],
495 order = -1,
387 type = "execute", 496 type = "execute",
388 name = L["Delete this State"],
389 func = function(info) 497 func = function(info)
390 module:DeleteState(bar,opts.name) 498 if states[opts.name] then
499 states[opts.name] = nil
500 ApplyStates(bar)
501 end
391 optionMap[bar].args[opts.name] = nil 502 optionMap[bar].args[opts.name] = nil
392 end, 503 end,
393 order = -1
394 }, 504 },
395 rename = { 505 rename = {
396 type = "input",
397 name = L["Name"], 506 name = L["Name"],
398 order = 1, 507 order = 1,
508 type = "input",
399 get = function() return opts.name end, 509 get = function() return opts.name end,
400 set = function(info, value) 510 set = function(info, value)
401 -- check for existing state name 511 -- check for existing state name
402 if states[value] then 512 if states[value] then
403 L["State named '%s' already exists"]:format(value) 513 L["State named '%s' already exists"]:format(value)
409 end, 519 end,
410 pattern = "^%w*$", 520 pattern = "^%w*$",
411 usage = L["State names must be alphanumeric without spaces"], 521 usage = L["State names must be alphanumeric without spaces"],
412 }, 522 },
413 ordering = { 523 ordering = {
414 type = "group",
415 inline = true,
416 name = L["Evaluation Order"], 524 name = L["Evaluation Order"],
417 desc = L["State transitions are evaluated in the order listed:\nMove a state up or down to change the order"], 525 desc = L["State transitions are evaluated in the order listed:\nMove a state up or down to change the order"],
418 order = 2, 526 order = 2,
527 type = "group",
528 inline = true,
419 args = { 529 args = {
420 up = { 530 up = {
531 name = L["Up"],
532 order = 1,
421 type = "execute", 533 type = "execute",
422 name = L["Up"],
423 width = "half", 534 width = "half",
424 order = 1,
425 func = function() 535 func = function()
426 local before, after = getNeighbors() 536 local before, after = getNeighbors()
427 if before then 537 if before then
428 swapOrder(before, opts.name) 538 swapOrder(before, opts.name)
429 update() 539 update()
430 end 540 end
431 end, 541 end,
432 }, 542 },
433 down = { 543 down = {
544 name = L["Down"],
545 order = 2,
434 type = "execute", 546 type = "execute",
435 name = L["Down"],
436 width = "half", 547 width = "half",
437 order = 2,
438 func = function() 548 func = function()
439 local before, after = getNeighbors() 549 local before, after = getNeighbors()
440 if after then 550 if after then
441 ReAction:Print(opts.name, after)
442 swapOrder(opts.name, after) 551 swapOrder(opts.name, after)
443 update() 552 update()
444 end 553 end
445 end, 554 end,
446 } 555 }
447 } 556 }
448 }, 557 }
449 -- keybinding for show-this-state would go here
450 -- show/hide would go here
451 -- page # would go here
452 -- anchoring would go here
453 } 558 }
454 }, 559 },
560 properties = {
561 name = L["Properties"],
562 order = 2,
563 type = "group",
564 args = {
565 desc = {
566 name = L["Set the properties for the bar when in this state"],
567 order = 1,
568 type = "description"
569 },
570 hide = {
571 name = L["Hide Bar"],
572 order = 2,
573 type = "toggle",
574 set = setprop,
575 get = getprop,
576 },
577 page = {
578 name = L["Show Page #"],
579 order = 3,
580 type = "select",
581 disabled = function()
582 return bar:GetNumPages() < 2
583 end,
584 hidden = function()
585 return bar:GetNumPages() < 2
586 end,
587 values = function()
588 local pages = { none = " " }
589 for i = 1, bar:GetNumPages() do
590 pages[i] = i
591 end
592 return pages
593 end,
594 set = function(info, value)
595 if value == "none" then
596 setprop(info, nil)
597 else
598 setprop(info, value)
599 end
600 end,
601 get = function(info)
602 return getprop(info) or "none"
603 end,
604 },
605 keybindstate = {
606 name = L["Override Keybinds"],
607 desc = L["Set this state to maintain its own set of keybinds which override the defaults when active"],
608 order = 4,
609 type = "toggle",
610 set = setprop,
611 get = getprop,
612 },
613 position = {
614 name = L["Position"],
615 order = 5,
616 type = "group",
617 inline = true,
618 args = {
619 enableanchor = {
620 name = L["Set New Position"],
621 order = 1,
622 type = "toggle",
623 set = setprop,
624 get = getprop,
625 },
626 anchorPoint = {
627 name = L["Point"],
628 order = 2,
629 type = "select",
630 values = pointTable,
631 set = function(info, value) setprop(info, value ~= "NONE" and value or nil) end,
632 get = function(info) return getprop(info) or "NONE" end,
633 disabled = anchordisable,
634 hidden = anchordisable,
635 },
636 anchorRelPoint = {
637 name = L["Relative Point"],
638 order = 3,
639 type = "select",
640 values = pointTable,
641 set = function(info, value) setprop(info, value ~= "NONE" and value or nil) end,
642 get = function(info) return getprop(info) or "NONE" end,
643 disabled = anchordisable,
644 hidden = anchordisable,
645 },
646 anchorX = {
647 name = L["X Offset"],
648 order = 4,
649 type = "range",
650 min = -100,
651 max = 100,
652 step = 1,
653 set = setprop,
654 get = getprop,
655 disabled = anchordisable,
656 hidden = anchordisable,
657 },
658 anchorY = {
659 name = L["Y Offset"],
660 order = 5,
661 type = "range",
662 min = -100,
663 max = 100,
664 step = 1,
665 set = setprop,
666 get = getprop,
667 disabled = anchordisable,
668 hidden = anchordisable,
669 },
670 },
671 },
672 scale = {
673 name = L["Scale"],
674 order = 6,
675 type = "group",
676 inline = true,
677 args = {
678 enablescale = {
679 name = L["Set New Scale"],
680 order = 1,
681 type = "toggle",
682 set = setprop,
683 get = getprop,
684 },
685 scale = {
686 name = L["Scale"],
687 order = 2,
688 type = "range",
689 min = 0.1,
690 max = 2.5,
691 step = 0.05,
692 isPercent = true,
693 set = setprop,
694 get = function(info) return getprop(info) or 1 end,
695 disabled = function() return not GetProperty(bar, opts.name, "enablescale") end,
696 hidden = function() return not GetProperty(bar, opts.name, "enablescale") end,
697 },
698 },
699 },
700 },
701 },
455 rules = { 702 rules = {
703 name = L["Selection Rule"],
704 order = 3,
456 type = "group", 705 type = "group",
457 name = L["Rules"],
458 order = 2,
459 args = { 706 args = {
460 mode = { 707 mode = {
708 name = L["Select this state"],
709 order = 2,
461 type = "select", 710 type = "select",
462 style = "radio", 711 style = "radio",
463 name = L["Select this state"],
464 values = { 712 values = {
465 default = L["by default"], 713 default = L["by default"],
466 any = L["when ANY of these"], 714 any = L["when ANY of these"],
467 all = L["when ALL of these"], 715 all = L["when ALL of these"],
468 custom = L["via custom rule"] 716 custom = L["via custom rule"],
717 keybind = L["via keybinding"],
469 }, 718 },
470 set = function( info, value ) 719 set = function( info, value )
471 put("type", value) 720 setrule("type", value)
472 fixall() 721 fixall()
473 update() 722 update()
474 end, 723 end,
475 get = function( info ) 724 get = function( info )
476 return fetch("type") 725 return getrule("type")
477 end, 726 end,
478 order = 2
479 }, 727 },
480 clear = { 728 clear = {
729 name = L["Clear All"],
730 order = 3,
481 type = "execute", 731 type = "execute",
482 name = L["Clear All"], 732 hidden = function()
733 local t = getrule("type")
734 return t ~= "any" and t ~= "all"
735 end,
736 disabled = function()
737 local t = getrule("type")
738 return t ~= "any" and t ~= "all"
739 end,
483 func = function() 740 func = function()
484 local type = fetch("type") 741 local type = getrule("type")
485 if type == "custom" then 742 if type == "custom" then
486 put("custom","") 743 setrule("custom","")
487 elseif type == "any" or type == "all" then 744 elseif type == "any" or type == "all" then
488 put("values", {}) 745 setrule("values", {})
489 end 746 end
490 update() 747 update()
491 end, 748 end,
492 order = 3
493 }, 749 },
494 inputs = { 750 inputs = {
751 name = L["Conditions"],
752 order = 4,
495 type = "multiselect", 753 type = "multiselect",
496 name = L["Rules"],
497 hidden = function() 754 hidden = function()
498 return fetch("type") == "custom" 755 local t = getrule("type")
756 return t ~= "any" and t ~= "all"
499 end, 757 end,
500 disabled = function() 758 disabled = function()
501 return fetch("type") == "default" 759 local t = getrule("type")
760 return t ~= "any" and t ~= "all"
502 end, 761 end,
503 values = ruleSelect, 762 values = ruleSelect,
504 set = function(info, key, value ) 763 set = function(info, key, value )
505 put(ruleMap[key], value or nil, "values") 764 setrule(ruleMap[key], value or nil, "values")
506 if value then 765 if value then
507 fixall(ruleMap[key]) 766 fixall(ruleMap[key])
508 end 767 end
509 update() 768 update()
510 end, 769 end,
511 get = function(info, key) 770 get = function(info, key)
512 return fetch("values", ruleMap[key]) or false 771 return getrule("values", ruleMap[key]) or false
513 end, 772 end,
514 order = 4
515 }, 773 },
516 custom = { 774 custom = {
775 name = L["Custom Rule"],
776 order = 5,
517 type = "input", 777 type = "input",
518 multiline = true, 778 multiline = true,
519 hidden = function() 779 hidden = function()
520 return fetch("type") ~= "custom" 780 return getrule("type") ~= "custom"
521 end, 781 end,
522 disabled = function() 782 disabled = function()
523 return fetch("type") == "default" 783 return getrule("type") ~= "custom"
524 end, 784 end,
525 name = L["Custom Rule"],
526 desc = L["Syntax like macro rules: see preset rules for examples"], 785 desc = L["Syntax like macro rules: see preset rules for examples"],
527 set = function(info, value) 786 set = function(info, value)
528 put("custom",value) 787 setrule("custom",value)
529 update() 788 update()
530 end, 789 end,
531 get = function(info) 790 get = function(info)
532 return fetch("custom") or "" 791 return getrule("custom") or ""
533 end, 792 end,
534 validate = function (info, rule) 793 validate = function (info, rule)
535 local s = rule:gsub("%s","") -- remove all spaces 794 local s = rule:gsub("%s","") -- remove all spaces
536 -- unfortunately %b and captures don't support the '+' notation, or this would be considerably simpler 795 -- unfortunately %b and captures don't support the '+' notation, or this would be considerably simpler
537 repeat 796 repeat
544 end 803 end
545 s = r 804 s = r
546 until c == nil 805 until c == nil
547 return true 806 return true
548 end, 807 end,
549 order = 5, 808 },
550 } 809 keybind = {
551 } 810 name = L["Keybinding"],
552 } 811 order = 6,
812 inline = true,
813 hidden = function() return getrule("type") ~= "keybind" end,
814 disabled = function() return getrule("type") ~= "keybind" end,
815 type = "group",
816 args = {
817 desc = {
818 name = L["Invoking a state keybind overrides all other transition rules. Toggle the keybind again to remove the override and return to the specified toggle-off state."],
819 order = 1,
820 type = "description",
821 },
822 keybind = {
823 name = L["State Hotkey"],
824 desc = L["Define an override toggle keybind"],
825 order = 2,
826 type = "keybinding",
827 set = function(info, value)
828 setrule("keybind",value)
829 update()
830 end,
831 get = function() return getrule("keybind") end,
832 },
833 default = {
834 name = L["Toggle Off State"],
835 desc = L["Select a state to return to when the keybind override is toggled off"],
836 order = 3,
837 type = "select",
838 values = function()
839 local t = { }
840 for k in pairs(states) do
841 if k ~= opts.name then
842 t[k] = k
843 end
844 end
845 return t
846 end,
847 set = function(info, value)
848 setrule("keybindreturn",value)
849 update()
850 end,
851 get = function() return getrule("keybindreturn") end,
852 },
853 },
854 },
855 },
856 },
553 } 857 }
554 return opts 858 return opts
555 end 859 end
556 860
557 861
562 name = L["Dynamic State"], 866 name = L["Dynamic State"],
563 childGroups = "tree", 867 childGroups = "tree",
564 disabled = InCombatLockdown, 868 disabled = InCombatLockdown,
565 args = { 869 args = {
566 __desc__ = { 870 __desc__ = {
871 name = L["States are evaluated in the order they are listed"],
872 order = 1,
567 type = "description", 873 type = "description",
568 name = L["States are evaluated in the order they are listed"],
569 order = 1
570 }, 874 },
571 __new__ = { 875 __new__ = {
572 type = "group",
573 name = L["New State..."], 876 name = L["New State..."],
574 order = 2, 877 order = 2,
878 type = "group",
575 args = { 879 args = {
576 name = { 880 name = {
577 type = "input",
578 name = L["State Name"], 881 name = L["State Name"],
579 desc = L["Set a name for the new state"], 882 desc = L["Set a name for the new state"],
883 order = 1,
884 type = "input",
580 get = function() return private.newstatename or "" end, 885 get = function() return private.newstatename or "" end,
581 set = function(info,value) private.newstatename = value end, 886 set = function(info,value) private.newstatename = value end,
582 pattern = "^%w*$", 887 pattern = "^%w*$",
583 usage = L["State names must be alphanumeric without spaces"], 888 usage = L["State names must be alphanumeric without spaces"],
584 order = 1
585 }, 889 },
586 create = { 890 create = {
891 name = L["Create State"],
892 order = 2,
587 type = "execute", 893 type = "execute",
588 name = L["Create State"],
589 func = function () 894 func = function ()
590 local name = private.newstatename 895 local name = private.newstatename
591 module:CreateState(bar,name) -- TODO: select default state options and pass as final argument 896 if states[name] then
592 optionMap[bar].args[name] = CreateStateOptions(bar,name) 897 ReAction:UserError(L["State named '%s' already exists"]:format(name))
593 private.newstatename = "" 898 else
899 -- TODO: select default state options and pass as final argument
900 states[name] = { }
901 optionMap[bar].args[name] = CreateStateOptions(bar,name)
902 private.newstatename = ""
903 end
594 end, 904 end,
595 disabled = function() 905 disabled = function()
596 local name = private.newstatename or "" 906 local name = private.newstatename or ""
597 return #name == 0 or name:find("%W") 907 return #name == 0 or name:find("%W")
598 end, 908 end,
599 order = 2,
600 } 909 }
601 } 910 }
602 } 911 }
603 } 912 }
604 } 913 }