Mercurial > wow > reaction
comparison State.lua @ 79:a45255f5d0c2
- Converted State options to use static options table + metatable handler
- Fixed bug with FixAll()
- Added external property handler registration
- Removed pages handler (to be migrated to ReAction_Action)
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Tue, 24 Jun 2008 23:39:43 +0000 |
parents | da8ba8783924 |
children | 42ec2938d65a |
comparison
equal
deleted
inserted
replaced
78:502cdb5666e2 | 79:a45255f5d0c2 |
---|---|
51 end) | 51 end) |
52 return r | 52 return r |
53 end | 53 end |
54 | 54 |
55 | 55 |
56 local InitRules, ApplyStates, SetProperty, GetProperty | 56 local InitRules, ApplyStates, SetProperty, GetProperty, RegisterProperty |
57 | 57 |
58 -- PRIVATE -- | 58 -- PRIVATE -- |
59 do | 59 do |
60 -- As far as I can tell the macro clauses are NOT locale-specific. | 60 -- As far as I can tell the macro clauses are NOT locale-specific. |
61 local ruleformats = { | 61 local ruleformats = { |
140 local ofskey = ofskeys[ckey] | 140 local ofskey = ofskeys[ckey] |
141 local default = select(barofsidx[ckey], bar:GetAnchor()) | 141 local default = select(barofsidx[ckey], bar:GetAnchor()) |
142 bar:SetStateAttribute(format("headofs%s",ofskeys[ckey]), map, default) | 142 bar:SetStateAttribute(format("headofs%s",ofskeys[ckey]), map, default) |
143 end | 143 end |
144 | 144 |
145 -- the name of the function maps to the name of the config element | 145 -- the table key name for each function maps to the name of the config element |
146 local propertyFuncs = { | 146 local propertyFuncs = { |
147 hide = function( bar, states ) | 147 hide = function( bar, states ) |
148 local hs = { } | 148 local hs = { } |
149 for state, config in pairs(states) do | 149 for state, config in pairs(states) do |
150 if config.hide then | 150 if config.hide then |
151 table.insert(hs, state) | 151 table.insert(hs, state) |
152 end | 152 end |
153 end | 153 end |
154 bar:SetStateAttribute("hidestates", nil, table.concat(hs,","), true) -- pass to buttons | 154 bar:SetStateAttribute("hidestates", nil, table.concat(hs,","), true) -- pass to buttons |
155 end, | |
156 | |
157 page = function( bar, states ) | |
158 local map = { } | |
159 for state, config in pairs(states) do | |
160 if config.page then | |
161 map[state] = format("page%d",config.page) | |
162 end | |
163 end | |
164 bar:SetStateAttribute("statebutton", map) | |
165 end, | 155 end, |
166 | 156 |
167 keybindstate = function( bar, states ) | 157 keybindstate = function( bar, states ) |
168 local map = { } | 158 local map = { } |
169 for state, config in pairs(states) do | 159 for state, config in pairs(states) do |
211 local states = tbuild(module.db.profile.bars, bar:GetName(), "states") | 201 local states = tbuild(module.db.profile.bars, bar:GetName(), "states") |
212 tbuild(states, state)[propname] = value | 202 tbuild(states, state)[propname] = value |
213 local f = propertyFuncs[propname] | 203 local f = propertyFuncs[propname] |
214 if f then | 204 if f then |
215 f(bar, states) | 205 f(bar, states) |
206 end | |
207 end | |
208 | |
209 function RegisterProperty( propname, f ) | |
210 propertyFuncs[propname] = f | |
211 for bar in ReAction:IterateBars() do | |
212 local states = tfetch(module.db.profile.bars, bar:GetName(), "states") | |
213 if states then | |
214 f(bar,states) | |
215 end | |
216 end | 216 end |
217 end | 217 end |
218 | 218 |
219 | 219 |
220 | 220 |
377 local bars = self.db.profile.bars | 377 local bars = self.db.profile.bars |
378 bars[newname], bars[oldname] = bars[oldname], nil | 378 bars[newname], bars[oldname] = bars[oldname], nil |
379 end | 379 end |
380 | 380 |
381 function module:OnConfigModeChanged(event, mode) | 381 function module:OnConfigModeChanged(event, mode) |
382 -- TODO: unregister all state drivers (temporarily) and hidestates | 382 -- nothing to do (yet) |
383 end | 383 end |
384 | 384 |
385 | 385 |
386 | 386 |
387 -- Options -- | 387 -- Options -- |
388 | 388 |
389 local CreateBarOptions | 389 local CreateBarOptions, RegisterPropertyOptions |
390 do | 390 do |
391 local playerClass = select(2, UnitClass("player")) | |
391 local function ClassCheck(...) | 392 local function ClassCheck(...) |
392 for i = 1, select('#',...) do | 393 for i = 1, select('#',...) do |
393 local _, c = UnitClass("player") | 394 if playerClass == select(i,...) then |
394 if c == select(i,...) then | |
395 return false | 395 return false |
396 end | 396 end |
397 end | 397 end |
398 return true | 398 return true |
399 end | 399 end |
440 table.insert(ruleMap, key) | 440 table.insert(ruleMap, key) |
441 end | 441 end |
442 end | 442 end |
443 end | 443 end |
444 | 444 |
445 local stateOptions = { | |
446 ordering = { | |
447 name = L["Info"], | |
448 order = 1, | |
449 type = "group", | |
450 args = { | |
451 delete = { | |
452 name = L["Delete this State"], | |
453 order = -1, | |
454 type = "execute", | |
455 func = "DeleteState", | |
456 }, | |
457 rename = { | |
458 name = L["Name"], | |
459 order = 1, | |
460 type = "input", | |
461 get = "GetName", | |
462 set = "SetStateName", | |
463 pattern = "^%w*$", | |
464 usage = L["State names must be alphanumeric without spaces"], | |
465 }, | |
466 ordering = { | |
467 name = L["Evaluation Order"], | |
468 desc = L["State transitions are evaluated in the order listed:\nMove a state up or down to change the order"], | |
469 order = 2, | |
470 type = "group", | |
471 inline = true, | |
472 args = { | |
473 up = { | |
474 name = L["Up"], | |
475 order = 1, | |
476 type = "execute", | |
477 width = "half", | |
478 func = "MoveStateUp", | |
479 }, | |
480 down = { | |
481 name = L["Down"], | |
482 order = 2, | |
483 type = "execute", | |
484 width = "half", | |
485 func = "MoveStateDown", | |
486 } | |
487 } | |
488 } | |
489 } | |
490 }, | |
491 properties = { | |
492 name = L["Properties"], | |
493 order = 2, | |
494 type = "group", | |
495 args = { | |
496 desc = { | |
497 name = L["Set the properties for the bar when in this state"], | |
498 order = 1, | |
499 type = "description" | |
500 }, | |
501 hide = { | |
502 name = L["Hide Bar"], | |
503 order = 91, | |
504 type = "toggle", | |
505 set = "SetProp", | |
506 get = "GetProp", | |
507 }, | |
508 keybindstate = { | |
509 name = L["Override Keybinds"], | |
510 desc = L["Set this state to maintain its own set of keybinds which override the defaults when active"], | |
511 order = 92, | |
512 type = "toggle", | |
513 set = "SetProp", | |
514 get = "GetProp", | |
515 }, | |
516 position = { | |
517 name = L["Position"], | |
518 order = 93, | |
519 type = "group", | |
520 inline = true, | |
521 args = { | |
522 enableAnchor = { | |
523 name = L["Set New Position"], | |
524 order = 1, | |
525 type = "toggle", | |
526 set = "SetProp", | |
527 get = "GetProp", | |
528 }, | |
529 anchorPoint = { | |
530 name = L["Point"], | |
531 order = 2, | |
532 type = "select", | |
533 values = pointTable, | |
534 set = "SetAnchorPointProp", | |
535 get = "GetAnchorPointProp", | |
536 disabled = "GetAnchorDisabled", | |
537 hidden = "GetAnchorDisabled", | |
538 }, | |
539 anchorRelPoint = { | |
540 name = L["Relative Point"], | |
541 order = 3, | |
542 type = "select", | |
543 values = pointTable, | |
544 set = "SetAnchorPointProp", | |
545 get = "GetAnchorPointProp", | |
546 disabled = "GetAnchorDisabled", | |
547 hidden = "GetAnchorDisabled", | |
548 }, | |
549 anchorX = { | |
550 name = L["X Offset"], | |
551 order = 4, | |
552 type = "range", | |
553 min = -100, | |
554 max = 100, | |
555 step = 1, | |
556 set = "SetProp", | |
557 get = "GetProp", | |
558 disabled = "GetAnchorDisabled", | |
559 hidden = "GetAnchorDisabled", | |
560 }, | |
561 anchorY = { | |
562 name = L["Y Offset"], | |
563 order = 5, | |
564 type = "range", | |
565 min = -100, | |
566 max = 100, | |
567 step = 1, | |
568 set = "SetProp", | |
569 get = "GetProp", | |
570 disabled = "GetAnchorDisabled", | |
571 hidden = "GetAnchorDisabled", | |
572 }, | |
573 }, | |
574 }, | |
575 scale = { | |
576 name = L["Scale"], | |
577 order = 94, | |
578 type = "group", | |
579 inline = true, | |
580 args = { | |
581 enableScale = { | |
582 name = L["Set New Scale"], | |
583 order = 1, | |
584 type = "toggle", | |
585 set = "SetProp", | |
586 get = "GetProp", | |
587 }, | |
588 scale = { | |
589 name = L["Scale"], | |
590 order = 2, | |
591 type = "range", | |
592 min = 0.1, | |
593 max = 2.5, | |
594 step = 0.05, | |
595 isPercent = true, | |
596 set = "SetProp", | |
597 get = "GetProp", | |
598 disabled = "GetScaleDisabled", | |
599 hidden = "GetScaleDisabled", | |
600 }, | |
601 }, | |
602 }, | |
603 }, | |
604 plugins = { } | |
605 }, | |
606 rules = { | |
607 name = L["Rule"], | |
608 order = 3, | |
609 type = "group", | |
610 args = { | |
611 mode = { | |
612 name = L["Select this state"], | |
613 order = 2, | |
614 type = "select", | |
615 style = "radio", | |
616 values = { | |
617 default = L["by default"], | |
618 any = L["when ANY of these"], | |
619 all = L["when ALL of these"], | |
620 custom = L["via custom rule"], | |
621 keybind = L["via keybinding"], | |
622 }, | |
623 set = "SetType", | |
624 get = "GetType", | |
625 }, | |
626 clear = { | |
627 name = L["Clear All"], | |
628 order = 3, | |
629 type = "execute", | |
630 hidden = "GetClearAllDisabled", | |
631 disabled = "GetClearAllDisabled", | |
632 func = "ClearAllConditions", | |
633 }, | |
634 inputs = { | |
635 name = L["Conditions"], | |
636 order = 4, | |
637 type = "multiselect", | |
638 hidden = "GetConditionsDisabled", | |
639 disabled = "GetConditionsDisabled", | |
640 values = ruleSelect, | |
641 set = "SetCondition", | |
642 get = "GetCondition", | |
643 }, | |
644 custom = { | |
645 name = L["Custom Rule"], | |
646 order = 5, | |
647 type = "input", | |
648 multiline = true, | |
649 hidden = "GetCustomDisabled", | |
650 disabled = "GetCustomDisabled", | |
651 desc = L["Syntax like macro rules: see preset rules for examples"], | |
652 set = "SetCustomRule", | |
653 get = "GetCustomRule", | |
654 validate = "ValidateCustomRule", | |
655 }, | |
656 keybind = { | |
657 name = L["Keybinding"], | |
658 order = 6, | |
659 inline = true, | |
660 hidden = "GetKeybindDisabled", | |
661 disabled = "GetKeybindDisabled", | |
662 type = "group", | |
663 args = { | |
664 desc = { | |
665 name = L["Invoking a state keybind toggles an override of all other transition rules."], | |
666 order = 1, | |
667 type = "description", | |
668 }, | |
669 keybind = { | |
670 name = L["State Hotkey"], | |
671 desc = L["Define an override toggle keybind"], | |
672 order = 2, | |
673 type = "keybinding", | |
674 set = "SetKeybind", | |
675 get = "GetKeybind", | |
676 }, | |
677 }, | |
678 }, | |
679 }, | |
680 }, | |
681 } | |
682 | |
683 local StateHandler = { } | |
684 | |
685 function StateHandler:New( bar, opts ) | |
686 local self = setmetatable({ bar = bar }, { __index = StateHandler }) | |
687 | |
688 function self:GetName() | |
689 return opts.name | |
690 end | |
691 | |
692 function self:SetName(name) | |
693 opts.name = name | |
694 end | |
695 | |
696 function self:GetOrder() | |
697 return opts.order | |
698 end | |
699 | |
700 -- get reference to states table: even if the bar | |
701 -- name changes the states table ref won't | |
702 self.states = tbuild(module.db.profile.bars, bar:GetName(), "states") | |
703 | |
704 tbuild(self.states, opts.name) | |
705 | |
706 opts.order = self:GetRule("order") | |
707 if opts.order == nil then | |
708 -- add after the highest | |
709 opts.order = 100 | |
710 for _, state in pairs(self.states) do | |
711 local x = tonumber(tfetch(state, "rule", "order")) | |
712 if x and x >= opts.order then | |
713 opts.order = x + 1 | |
714 end | |
715 end | |
716 self:SetRule("order",opts.order) | |
717 end | |
718 | |
719 return self | |
720 end | |
721 | |
722 -- helper methods | |
723 | |
724 function StateHandler:SetRule( key, value, ... ) | |
725 tbuild(self.states, self:GetName(), "rule", ...)[key] = value | |
726 end | |
727 | |
728 function StateHandler:GetRule( ... ) | |
729 return tfetch(self.states, self:GetName(), "rule", ...) | |
730 end | |
731 | |
732 function StateHandler:FixAll( setkey ) | |
733 -- if multiple selections in the same group are chosen when 'all' is selected, | |
734 -- keep only one of them. If changing the mode, the first in the fields list will | |
735 -- be chosen arbitrarily. Otherwise, if selecting a new checkbox from the field-set, | |
736 -- it will be retained. | |
737 local notified = false | |
738 if self:GetRule("type") == "all" then | |
739 for _, c in ipairs(rules) do | |
740 local rule, hidden, fields = unpack(c) | |
741 local once = false | |
742 if setkey then | |
743 for idx, field in ipairs(fields) do | |
744 if next(field) == setkey then | |
745 once = true | |
746 end | |
747 end | |
748 end | |
749 for idx, field in ipairs(fields) do | |
750 local key = next(field) | |
751 if self:GetRule("values",key) then | |
752 if once and key ~= setkey then | |
753 self:SetRule(key,false,"values") | |
754 if not setkey and not notified then | |
755 ReAction:UserError(L["Warning: one or more incompatible rules were turned off"]) | |
756 notified = true | |
757 end | |
758 end | |
759 once = true | |
760 end | |
761 end | |
762 end | |
763 end | |
764 end | |
765 | |
766 function StateHandler:GetNeighbors() | |
767 local before, after | |
768 for k, v in pairs(self.states) do | |
769 local o = tonumber(tfetch(v, "rule", "order")) | |
770 if o and k ~= self:GetName() then | |
771 local obefore = tfetch(self.states,before,"rule","order") | |
772 local oafter = tfetch(self.states,after,"rule","order") | |
773 if o < self:GetOrder() and (not obefore or obefore < o) then | |
774 before = k | |
775 end | |
776 if o > self:GetOrder() and (not oafter or oafter > o) then | |
777 after = k | |
778 end | |
779 end | |
780 end | |
781 return before, after | |
782 end | |
783 | |
784 function StateHandler:SwapOrder( a, b ) | |
785 -- do options table | |
786 local args = optionMap[self.bar].args | |
787 args[a].order, args[b].order = args[b].order, args[a].order | |
788 -- do profile | |
789 a = tbuild(self.states, a, "rule") | |
790 b = tbuild(self.states, b, "rule") | |
791 a.order, b.order = b.order, a.order | |
792 end | |
793 | |
794 -- handler methods | |
795 | |
796 function StateHandler:GetProp( info ) | |
797 -- gets property of the same name as the options arg | |
798 return GetProperty(self.bar, self:GetName(), info[#info]) | |
799 end | |
800 | |
801 function StateHandler:SetProp( info, value ) | |
802 -- sets property of the same name as the options arg | |
803 SetProperty(self.bar, self:GetName(), info[#info], value) | |
804 end | |
805 | |
806 function StateHandler:DeleteState() | |
807 if self.states[self:GetName()] then | |
808 self.states[self:GetName()] = nil | |
809 ApplyStates(self.bar) | |
810 end | |
811 optionMap[self.bar].args[self:GetName()] = nil | |
812 end | |
813 | |
814 function StateHandler:SetStateName(info, value) | |
815 -- check for existing state name | |
816 if self.states[value] then | |
817 ReAction:UserError(format(L["State named '%s' already exists"],value)) | |
818 return | |
819 end | |
820 local args = optionMap[self.bar].args | |
821 local name = self:GetName() | |
822 self.states[value], args[value], self.states[name], args[name] = self.states[name], args[name], nil, nil | |
823 self:SetName(value) | |
824 ApplyStates(self.bar) | |
825 end | |
826 | |
827 function StateHandler:MoveStateUp() | |
828 local before, after = self:GetNeighbors() | |
829 if before then | |
830 self:SwapOrder(before, self:GetName()) | |
831 ApplyStates(self.bar) | |
832 end | |
833 end | |
834 | |
835 function StateHandler:MoveStateDown() | |
836 local before, after = self:GetNeighbors() | |
837 if after then | |
838 self:SwapOrder(self:GetName(), after) | |
839 ApplyStates(self.bar) | |
840 end | |
841 end | |
842 | |
843 function StateHandler:GetAnchorDisabled() | |
844 return not GetProperty(self.bar, self:GetName(), "enableAnchor") | |
845 end | |
846 | |
847 function StateHandler:SetAnchorPointProp(info, value) | |
848 self:SetProp(info, value ~= "NONE" and value or nil) | |
849 end | |
850 | |
851 function StateHandler:GetAnchorPointProp(info) | |
852 return self:GetProp(info) or "NONE" | |
853 end | |
854 | |
855 function StateHandler:GetScaleDisabled() | |
856 return not GetProperty(self.bar, self:GetName(), "enableScale") | |
857 end | |
858 | |
859 function StateHandler:SetType(info, value) | |
860 self:SetRule("type", value) | |
861 self:FixAll() | |
862 ApplyStates(self.bar) | |
863 end | |
864 | |
865 function StateHandler:GetType() | |
866 return self:GetRule("type") | |
867 end | |
868 | |
869 function StateHandler:GetClearAllDisabled() | |
870 local t = self:GetRule("type") | |
871 return not( t == "any" or t == "all" or t == "custom") | |
872 end | |
873 | |
874 function StateHandler:ClearAllConditions() | |
875 local t = self:GetRule("type") | |
876 if t == "custom" then | |
877 self:SetRule("custom","") | |
878 elseif t == "any" or t == "all" then | |
879 self:SetRule("values", {}) | |
880 end | |
881 ApplyStates(self.bar) | |
882 end | |
883 | |
884 function StateHandler:GetConditionsDisabled() | |
885 local t = self:GetRule("type") | |
886 return not( t == "any" or t == "all") | |
887 end | |
888 | |
889 function StateHandler:SetCondition(info, key, value) | |
890 self:SetRule(ruleMap[key], value or nil, "values") | |
891 if value then | |
892 self:FixAll(ruleMap[key]) | |
893 end | |
894 ApplyStates(self.bar) | |
895 end | |
896 | |
897 function StateHandler:GetCondition(info, key) | |
898 return self:GetRule("values", ruleMap[key]) or false | |
899 end | |
900 | |
901 function StateHandler:GetCustomDisabled() | |
902 return self:GetRule("type") ~= "custom" | |
903 end | |
904 | |
905 function StateHandler:SetCustomRule(info, value) | |
906 self:SetRule("custom",value) | |
907 ApplyStates(self.bar) | |
908 end | |
909 | |
910 function StateHandler:GetCustomRule() | |
911 return self:GetRule("custom") or "" | |
912 end | |
913 | |
914 function StateHandler:ValidateCustomRule(info, value) | |
915 local s = value:gsub("%s","") -- remove all spaces | |
916 -- unfortunately %b and captures don't support the '+' notation, or this would be considerably simpler | |
917 repeat | |
918 if s == "" then | |
919 return true | |
920 end | |
921 local c, r = s:match("(%b[])(.*)") | |
922 if c == nil and s and #s > 0 then | |
923 return format(L["Invalid custom rule '%s': each clause must appear within [brackets]"],value or "") | |
924 end | |
925 s = r | |
926 until c == nil | |
927 return true | |
928 end | |
929 | |
930 function StateHandler:GetKeybindDisabled() | |
931 return self:GetRule("type") ~= "keybind" | |
932 end | |
933 | |
934 function StateHandler:GetKeybind() | |
935 return self:GetRule("keybind") | |
936 end | |
937 | |
938 function StateHandler:SetKeybind(info, value) | |
939 if value and #value == 0 then | |
940 value = nil | |
941 end | |
942 self:SetRule("keybind",value) | |
943 ApplyStates(self.bar) | |
944 end | |
945 | |
445 local function CreateStateOptions(bar, name) | 946 local function CreateStateOptions(bar, name) |
446 local opts = { | 947 local opts = { |
447 type = "group", | 948 type = "group", |
448 name = name, | 949 name = name, |
449 childGroups = "tab", | 950 childGroups = "tab", |
951 args = stateOptions | |
450 } | 952 } |
451 | 953 |
452 local states = tbuild(module.db.profile.bars, bar:GetName(), "states") | 954 opts.handler = StateHandler:New(bar,opts) |
453 | 955 |
454 local function update() | |
455 ApplyStates(bar) | |
456 end | |
457 | |
458 local function setrule( key, value, ... ) | |
459 tbuild(states, opts.name, "rule", ...)[key] = value | |
460 end | |
461 | |
462 local function getrule( ... ) | |
463 return tfetch(states, opts.name, "rule", ...) | |
464 end | |
465 | |
466 local function setprop(info, value) | |
467 SetProperty(bar, opts.name, info[#info], value) | |
468 end | |
469 | |
470 local function getprop(info) | |
471 return GetProperty(bar, opts.name, info[#info]) | |
472 end | |
473 | |
474 local function fixall(setkey) | |
475 -- if multiple selections in the same group are chosen when 'all' is selected, | |
476 -- keep only one of them. If changing the mode, the first in the fields list will | |
477 -- be chosen arbitrarily. Otherwise, if selecting a new checkbox from the field-set, | |
478 -- it will be retained. | |
479 local notified = false | |
480 for _, c in ipairs(rules) do | |
481 local rule, hidden, fields = unpack(c) | |
482 local found = false | |
483 for key in ipairs(fields) do | |
484 if getrule("values",key) then | |
485 if (found or setkey) and key ~= setkey then | |
486 setrule(key,false,"values") | |
487 if not setkey and not notified then | |
488 ReAction:UserError(L["Warning: one or more incompatible rules were turned off"]) | |
489 notified = true | |
490 end | |
491 end | |
492 found = true | |
493 end | |
494 end | |
495 end | |
496 end | |
497 | |
498 local function getNeighbors() | |
499 local before, after | |
500 for k, v in pairs(states) do | |
501 local o = tonumber(tfetch(v, "rule", "order")) | |
502 if o and k ~= opts.name then | |
503 local obefore = tfetch(states,before,"rule","order") | |
504 local oafter = tfetch(states,after,"rule","order") | |
505 if o < opts.order and (not obefore or obefore < o) then | |
506 before = k | |
507 end | |
508 if o > opts.order and (not oafter or oafter > o) then | |
509 after = k | |
510 end | |
511 end | |
512 end | |
513 return before, after | |
514 end | |
515 | |
516 local function swapOrder( a, b ) | |
517 -- do options table | |
518 local args = optionMap[bar].args | |
519 args[a].order, args[b].order = args[b].order, args[a].order | |
520 -- do profile | |
521 a = tbuild(states, a, "rule") | |
522 b = tbuild(states, b, "rule") | |
523 a.order, b.order = b.order, a.order | |
524 end | |
525 | |
526 local function anchordisable() | |
527 return not GetProperty(bar, opts.name, "enableAnchor") | |
528 end | |
529 | |
530 tbuild(states, name) | |
531 | |
532 opts.order = getrule("order") | |
533 if opts.order == nil then | |
534 -- add after the highest | |
535 opts.order = 100 | |
536 for _, state in pairs(states) do | |
537 local x = tonumber(tfetch(state, "rule", "order")) | |
538 if x and x >= opts.order then | |
539 opts.order = x + 1 | |
540 end | |
541 end | |
542 setrule("order",opts.order) | |
543 end | |
544 | |
545 opts.args = { | |
546 ordering = { | |
547 name = L["Info"], | |
548 order = 1, | |
549 type = "group", | |
550 args = { | |
551 delete = { | |
552 name = L["Delete this State"], | |
553 order = -1, | |
554 type = "execute", | |
555 func = function(info) | |
556 if states[opts.name] then | |
557 states[opts.name] = nil | |
558 ApplyStates(bar) | |
559 end | |
560 optionMap[bar].args[opts.name] = nil | |
561 end, | |
562 }, | |
563 rename = { | |
564 name = L["Name"], | |
565 order = 1, | |
566 type = "input", | |
567 get = function() return opts.name end, | |
568 set = function(info, value) | |
569 -- check for existing state name | |
570 if states[value] then | |
571 format(L["State named '%s' already exists"],value) | |
572 end | |
573 local args = optionMap[bar].args | |
574 states[value], args[value], states[opts.name], args[opts.name] = states[opts.name], args[opts.name], nil, nil | |
575 opts.name = value | |
576 update() | |
577 end, | |
578 pattern = "^%w*$", | |
579 usage = L["State names must be alphanumeric without spaces"], | |
580 }, | |
581 ordering = { | |
582 name = L["Evaluation Order"], | |
583 desc = L["State transitions are evaluated in the order listed:\nMove a state up or down to change the order"], | |
584 order = 2, | |
585 type = "group", | |
586 inline = true, | |
587 args = { | |
588 up = { | |
589 name = L["Up"], | |
590 order = 1, | |
591 type = "execute", | |
592 width = "half", | |
593 func = function() | |
594 local before, after = getNeighbors() | |
595 if before then | |
596 swapOrder(before, opts.name) | |
597 update() | |
598 end | |
599 end, | |
600 }, | |
601 down = { | |
602 name = L["Down"], | |
603 order = 2, | |
604 type = "execute", | |
605 width = "half", | |
606 func = function() | |
607 local before, after = getNeighbors() | |
608 if after then | |
609 swapOrder(opts.name, after) | |
610 update() | |
611 end | |
612 end, | |
613 } | |
614 } | |
615 } | |
616 } | |
617 }, | |
618 properties = { | |
619 name = L["Properties"], | |
620 order = 2, | |
621 type = "group", | |
622 args = { | |
623 desc = { | |
624 name = L["Set the properties for the bar when in this state"], | |
625 order = 1, | |
626 type = "description" | |
627 }, | |
628 hide = { | |
629 name = L["Hide Bar"], | |
630 order = 2, | |
631 type = "toggle", | |
632 set = setprop, | |
633 get = getprop, | |
634 }, | |
635 page = { | |
636 name = L["Show Page #"], | |
637 order = 3, | |
638 type = "select", | |
639 disabled = function() | |
640 --return bar:GetNumPages() < 2 | |
641 return true | |
642 end, | |
643 hidden = function() | |
644 --return bar:GetNumPages() < 2 | |
645 return true | |
646 end, | |
647 values = function() | |
648 -- use off-by-one ordering to put (none) first in the list | |
649 local pages = { [1] = L["(none)"] } | |
650 --for i = 1, bar:GetNumPages() do | |
651 -- pages[i+1] = i | |
652 --end | |
653 return pages | |
654 end, | |
655 set = function(info, value) | |
656 value = value - 1 | |
657 setprop(info, value > 0 and value or nil) | |
658 end, | |
659 get = function(info) | |
660 return getprop(info) or L["(none)"] | |
661 end, | |
662 }, | |
663 keybindstate = { | |
664 name = L["Override Keybinds"], | |
665 desc = L["Set this state to maintain its own set of keybinds which override the defaults when active"], | |
666 order = 4, | |
667 type = "toggle", | |
668 set = setprop, | |
669 get = getprop, | |
670 }, | |
671 position = { | |
672 name = L["Position"], | |
673 order = 5, | |
674 type = "group", | |
675 inline = true, | |
676 args = { | |
677 enableAnchor = { | |
678 name = L["Set New Position"], | |
679 order = 1, | |
680 type = "toggle", | |
681 set = setprop, | |
682 get = getprop, | |
683 }, | |
684 anchorPoint = { | |
685 name = L["Point"], | |
686 order = 2, | |
687 type = "select", | |
688 values = pointTable, | |
689 set = function(info, value) setprop(info, value ~= "NONE" and value or nil) end, | |
690 get = function(info) return getprop(info) or "NONE" end, | |
691 disabled = anchordisable, | |
692 hidden = anchordisable, | |
693 }, | |
694 anchorRelPoint = { | |
695 name = L["Relative Point"], | |
696 order = 3, | |
697 type = "select", | |
698 values = pointTable, | |
699 set = function(info, value) setprop(info, value ~= "NONE" and value or nil) end, | |
700 get = function(info) return getprop(info) or "NONE" end, | |
701 disabled = anchordisable, | |
702 hidden = anchordisable, | |
703 }, | |
704 anchorX = { | |
705 name = L["X Offset"], | |
706 order = 4, | |
707 type = "range", | |
708 min = -100, | |
709 max = 100, | |
710 step = 1, | |
711 set = setprop, | |
712 get = getprop, | |
713 disabled = anchordisable, | |
714 hidden = anchordisable, | |
715 }, | |
716 anchorY = { | |
717 name = L["Y Offset"], | |
718 order = 5, | |
719 type = "range", | |
720 min = -100, | |
721 max = 100, | |
722 step = 1, | |
723 set = setprop, | |
724 get = getprop, | |
725 disabled = anchordisable, | |
726 hidden = anchordisable, | |
727 }, | |
728 }, | |
729 }, | |
730 scale = { | |
731 name = L["Scale"], | |
732 order = 6, | |
733 type = "group", | |
734 inline = true, | |
735 args = { | |
736 enableScale = { | |
737 name = L["Set New Scale"], | |
738 order = 1, | |
739 type = "toggle", | |
740 set = setprop, | |
741 get = getprop, | |
742 }, | |
743 scale = { | |
744 name = L["Scale"], | |
745 order = 2, | |
746 type = "range", | |
747 min = 0.1, | |
748 max = 2.5, | |
749 step = 0.05, | |
750 isPercent = true, | |
751 set = setprop, | |
752 get = function(info) return getprop(info) or 1 end, | |
753 disabled = function() return not GetProperty(bar, opts.name, "enableScale") end, | |
754 hidden = function() return not GetProperty(bar, opts.name, "enableScale") end, | |
755 }, | |
756 }, | |
757 }, | |
758 }, | |
759 }, | |
760 rules = { | |
761 name = L["Rule"], | |
762 order = 3, | |
763 type = "group", | |
764 args = { | |
765 mode = { | |
766 name = L["Select this state"], | |
767 order = 2, | |
768 type = "select", | |
769 style = "radio", | |
770 values = { | |
771 default = L["by default"], | |
772 any = L["when ANY of these"], | |
773 all = L["when ALL of these"], | |
774 custom = L["via custom rule"], | |
775 keybind = L["via keybinding"], | |
776 }, | |
777 set = function( info, value ) | |
778 setrule("type", value) | |
779 fixall() | |
780 update() | |
781 end, | |
782 get = function( info ) | |
783 return getrule("type") | |
784 end, | |
785 }, | |
786 clear = { | |
787 name = L["Clear All"], | |
788 order = 3, | |
789 type = "execute", | |
790 hidden = function() | |
791 local t = getrule("type") | |
792 return t ~= "any" and t ~= "all" | |
793 end, | |
794 disabled = function() | |
795 local t = getrule("type") | |
796 return t ~= "any" and t ~= "all" | |
797 end, | |
798 func = function() | |
799 local type = getrule("type") | |
800 if type == "custom" then | |
801 setrule("custom","") | |
802 elseif type == "any" or type == "all" then | |
803 setrule("values", {}) | |
804 end | |
805 update() | |
806 end, | |
807 }, | |
808 inputs = { | |
809 name = L["Conditions"], | |
810 order = 4, | |
811 type = "multiselect", | |
812 hidden = function() | |
813 local t = getrule("type") | |
814 return t ~= "any" and t ~= "all" | |
815 end, | |
816 disabled = function() | |
817 local t = getrule("type") | |
818 return t ~= "any" and t ~= "all" | |
819 end, | |
820 values = ruleSelect, | |
821 set = function(info, key, value ) | |
822 setrule(ruleMap[key], value or nil, "values") | |
823 if value then | |
824 fixall(ruleMap[key]) | |
825 end | |
826 update() | |
827 end, | |
828 get = function(info, key) | |
829 return getrule("values", ruleMap[key]) or false | |
830 end, | |
831 }, | |
832 custom = { | |
833 name = L["Custom Rule"], | |
834 order = 5, | |
835 type = "input", | |
836 multiline = true, | |
837 hidden = function() | |
838 return getrule("type") ~= "custom" | |
839 end, | |
840 disabled = function() | |
841 return getrule("type") ~= "custom" | |
842 end, | |
843 desc = L["Syntax like macro rules: see preset rules for examples"], | |
844 set = function(info, value) | |
845 setrule("custom",value) | |
846 update() | |
847 end, | |
848 get = function(info) | |
849 return getrule("custom") or "" | |
850 end, | |
851 validate = function (info, rule) | |
852 local s = rule:gsub("%s","") -- remove all spaces | |
853 -- unfortunately %b and captures don't support the '+' notation, or this would be considerably simpler | |
854 repeat | |
855 if s == "" then | |
856 return true | |
857 end | |
858 local c, r = s:match("(%b[])(.*)") | |
859 if c == nil and s and #s > 0 then | |
860 return format(L["Invalid custom rule '%s': each clause must appear within [brackets]"],rule) | |
861 end | |
862 s = r | |
863 until c == nil | |
864 return true | |
865 end, | |
866 }, | |
867 keybind = { | |
868 name = L["Keybinding"], | |
869 order = 6, | |
870 inline = true, | |
871 hidden = function() return getrule("type") ~= "keybind" end, | |
872 disabled = function() return getrule("type") ~= "keybind" end, | |
873 type = "group", | |
874 args = { | |
875 desc = { | |
876 name = L["Invoking a state keybind toggles an override of all other transition rules."], | |
877 order = 1, | |
878 type = "description", | |
879 }, | |
880 keybind = { | |
881 name = L["State Hotkey"], | |
882 desc = L["Define an override toggle keybind"], | |
883 order = 2, | |
884 type = "keybinding", | |
885 set = function(info, value) | |
886 if value and #value == 0 then | |
887 value = nil | |
888 end | |
889 setrule("keybind",value) | |
890 update() | |
891 end, | |
892 get = function() return getrule("keybind") end, | |
893 }, | |
894 }, | |
895 }, | |
896 }, | |
897 }, | |
898 } | |
899 return opts | 956 return opts |
900 end | 957 end |
901 | 958 |
902 | 959 |
903 CreateBarOptions = function(bar) | 960 function RegisterPropertyOptions( field, options, handler ) |
961 stateOptions.properties.plugins[field] = options | |
962 if handler then | |
963 for k,v in pairs(handler) do | |
964 StateHandler[k] = v | |
965 end | |
966 end | |
967 end | |
968 | |
969 | |
970 function module:GetBarOptions(bar) | |
904 local private = { } | 971 local private = { } |
905 local states = tbuild(module.db.profile.bars, bar:GetName(), "states") | 972 local states = tbuild(module.db.profile.bars, bar:GetName(), "states") |
906 local options = { | 973 local options = { |
907 name = L["Dynamic State"], | 974 name = L["Dynamic State"], |
908 type = "group", | 975 type = "group", |
952 } | 1019 } |
953 } | 1020 } |
954 } | 1021 } |
955 } | 1022 } |
956 } | 1023 } |
957 local states = tfetch(module.db.profile.bars, bar:GetName(), "states") | 1024 for name, config in pairs(states) do |
958 if states then | 1025 options.args[name] = CreateStateOptions(bar,name) |
959 for name, config in pairs(states) do | |
960 options.args[name] = CreateStateOptions(bar,name) | |
961 end | |
962 end | 1026 end |
963 optionMap[bar] = options | 1027 optionMap[bar] = options |
964 return options | 1028 return options |
965 end | 1029 end |
966 end | 1030 end |
967 | 1031 |
968 function module:GetBarOptions(bar) | 1032 -- Module API -- |
969 return CreateBarOptions(bar) | 1033 |
970 end | 1034 -- Pass in a property field-name, an implementation function, a static options table, and an |
1035 -- optional options handler method-table | |
1036 -- | |
1037 -- propertyImplFunc prototype: | |
1038 -- propertyImplFunc( bar, stateTable ) | |
1039 -- where stateTable is a { ["statename"] = { state config } } table. | |
1040 -- | |
1041 -- The options table is static, i.e. not bar-specific and should only reference handler method | |
1042 -- strings (either existing ones or those added via optHandler). The existing options are ordered | |
1043 -- 91-100. Order #1 is reserved for the heading. | |
1044 -- | |
1045 -- The contents of optHandler, if provided, will be added to the existing StateHandler metatable. | |
1046 -- See above, for existing API. In particular see the properties set up in the New method: self.bar, | |
1047 -- self.states, and self:GetName(), and the generic property handlers self:GetProp() and self:SetProp(). | |
1048 -- | |
1049 function module:RegisterStateProperty( field, propertyImplFunc, options, optHandler ) | |
1050 RegisterProperty(field, propertyImplFunc) | |
1051 RegisterPropertyOptions(field, options, optHandler) | |
1052 end | |
1053 |