comparison modules/Action.lua @ 116:fb48811a8736

Convert to standard keybindings
author Flick <flickerstreak@gmail.com>
date Fri, 23 Jan 2009 23:44:55 +0000
parents 77bb68eb402b
children fb6c3a642ae3
comparison
equal deleted inserted replaced
115:af0172ed7037 116:fb48811a8736
15 local CreateFrame = CreateFrame 15 local CreateFrame = CreateFrame
16 local format = string.format 16 local format = string.format
17 local wipe = wipe 17 local wipe = wipe
18 18
19 ReAction:UpdateRevision("$Revision$") 19 ReAction:UpdateRevision("$Revision$")
20
21 local weak = { __mode="k" }
20 22
21 -- libraries 23 -- libraries
22 local KB = LibStub("LibKeyBound-1.0") 24 local KB = LibStub("LibKeyBound-1.0")
23 local LBF -- initialized later 25 local LBF -- initialized later
24 26
265 }, 267 },
266 }, 268 },
267 }, 269 },
268 } 270 }
269 271
270 local weak = { __mode="k" }
271 local meta = { __index = Handle } 272 local meta = { __index = Handle }
272 273
273 function Handle:New( bar, config ) 274 function Handle:New( bar, config )
274 local self = setmetatable( 275 local self = setmetatable(
275 { 276 {
363 ]]) 364 ]])
364 end 365 end
365 366
366 function Handle:SetKeybindMode(mode) 367 function Handle:SetKeybindMode(mode)
367 for _, b in pairs(self.btns) do 368 for _, b in pairs(self.btns) do
368 if mode then 369 b:SetKeybindMode(mode)
369 -- set the border for all buttons to the keybind-enable color
370 b.border:SetVertexColor(KB:GetColorKeyBoundMode())
371 b.border:Show()
372 elseif IsEquippedAction(b:GetActionID()) then
373 b.border:SetVertexColor(0, 1.0, 0, 0.35) -- from ActionButton.lua
374 else
375 b.border:Hide()
376 end
377 end 370 end
378 end 371 end
379 372
380 function Handle:GetLastButton() 373 function Handle:GetLastButton()
381 return self.btns[#self.btns] 374 return self.btns[#self.btns]
761 end 754 end
762 end 755 end
763 end 756 end
764 757
765 ------ Button class ------ 758 ------ Button class ------
766 759 local frameRecycler = { }
760 local trash = CreateFrame("Frame")
761 local OnUpdate, KBAttach, GetHotkey
767 do 762 do
768 local frameRecycler = { } 763 local ATTACK_BUTTON_FLASH_TIME = ATTACK_BUTTON_FLASH_TIME
769 local trash = CreateFrame("Frame") 764 local IsActionInRange = IsActionInRange
770 local OnUpdate, KBAttach, GetActionName, GetHotkey, SetKey, FreeKey, ClearBindings, GetBindings 765
771 do 766 function OnUpdate(frame, elapsed)
772 local ATTACK_BUTTON_FLASH_TIME = ATTACK_BUTTON_FLASH_TIME 767 -- note: This function taints frame.flashtime and frame.rangeTimer. Both of these
773 local IsActionInRange = IsActionInRange 768 -- are only read by ActionButton_OnUpdate (which this function replaces). In
774 769 -- all other places they're just written, so it doesn't taint any secure code.
775 local buttonLookup = setmetatable({},{__mode="kv"}) 770 if frame.flashing == 1 then
776 771 frame.flashtime = frame.flashtime - elapsed
777 function OnUpdate(frame, elapsed) 772 if frame.flashtime <= 0 then
778 -- note: This function taints frame.flashtime and frame.rangeTimer. Both of these 773 local overtime = -frame.flashtime
779 -- are only read by ActionButton_OnUpdate (which this function replaces). In 774 if overtime >= ATTACK_BUTTON_FLASH_TIME then
780 -- all other places they're just written, so it doesn't taint any secure code. 775 overtime = 0
781 if frame.flashing == 1 then
782 frame.flashtime = frame.flashtime - elapsed
783 if frame.flashtime <= 0 then
784 local overtime = -frame.flashtime
785 if overtime >= ATTACK_BUTTON_FLASH_TIME then
786 overtime = 0
787 end
788 frame.flashtime = ATTACK_BUTTON_FLASH_TIME - overtime
789
790 local flashTexture = frame.flash
791 if flashTexture:IsShown() then
792 flashTexture:Hide()
793 else
794 flashTexture:Show()
795 end
796 end 776 end
797 end 777 frame.flashtime = ATTACK_BUTTON_FLASH_TIME - overtime
798 778
799 if frame.rangeTimer then 779 local flashTexture = frame.flash
800 frame.rangeTimer = frame.rangeTimer - elapsed; 780 if flashTexture:IsShown() then
801 781 flashTexture:Hide()
802 if frame.rangeTimer <= 0 then 782 else
803 if IsActionInRange(frame.action) == 0 then 783 flashTexture:Show()
804 frame.icon:SetVertexColor(1.0,0.1,0.1)
805 else
806 ActionButton_UpdateUsable(frame)
807 end
808 frame.rangeTimer = 0.1
809 end 784 end
810 end 785 end
811 end 786 end
812 787
813 -- Use KeyBound-1.0 for binding, but use Override bindings instead of 788 if frame.rangeTimer then
814 -- regular bindings to support multiple profile use. This is a little 789 frame.rangeTimer = frame.rangeTimer - elapsed;
815 -- weird with the KeyBound dialog box (which has per-char selector as well 790
816 -- as an OK/Cancel box) but it's the least amount of effort to implement. 791 if frame.rangeTimer <= 0 then
817 function GetActionName(f) 792 if IsActionInRange(frame.action) == 0 then
818 local b = buttonLookup[f] 793 frame.icon:SetVertexColor(1.0,0.1,0.1)
819 if b then 794 else
820 return format("%s:%s", b.bar:GetName(), b.idx) 795 ActionButton_UpdateUsable(frame)
821 end
822 end
823
824 function GetHotkey(f)
825 local b = buttonLookup[f]
826 if b then
827 return KB:ToShortKey(b:GetConfig().hotkey)
828 end
829 end
830
831 function SetKey(f, key)
832 local b = buttonLookup[f]
833 if b then
834 local c = b:GetConfig()
835 if c.hotkey then
836 SetOverrideBinding(f, false, c.hotkey, nil)
837 end 796 end
838 if key then 797 frame.rangeTimer = 0.1
839 SetOverrideBindingClick(f, false, key, f:GetName(), nil) 798 end
840 end 799 end
841 c.hotkey = key 800 end
842 b:DisplayHotkey(GetHotkey(f)) 801
843 end 802 local function GetActionName(f)
844 end 803 local b = f and f._reactionButton
845 804 if b then
846 function FreeKey(f, key) 805 return format("%s:%s", b.bar:GetName(), b.idx)
847 local b = buttonLookup[f] 806 end
848 if b then 807 end
849 local c = b:GetConfig() 808
850 if c.hotkey == key then 809 function GetHotkey(f)
851 local action = f:GetActionName() 810 return KB:ToShortKey(GetBindingKey(format("CLICK %s:LeftButton",f:GetName())))
852 SetOverrideBinding(f, false, c.hotkey, nil) 811 end
853 c.hotkey = nil 812
854 b:DisplayHotkey(nil) 813 local function kb_onEnter( self )
855 return action 814 if ReAction:GetKeybindMode() then
856 end 815 KB:Set(self)
857 end 816 end
858 return ReAction:FreeOverrideHotkey(key) 817 end
859 end 818
860 819 function KBAttach( button )
861 function ClearBindings(f) 820 if not button.kbHooked then
862 SetKey(f, nil) 821 button.kbHooked = true
863 end
864
865 function GetBindings(f)
866 local b = buttonLookup[f]
867 if b then
868 return b:GetConfig().hotkey
869 end
870 end
871
872 function KBAttach( button )
873 local f = button:GetFrame() 822 local f = button:GetFrame()
823 f:HookScript("OnEnter", kb_onEnter)
874 f.GetActionName = GetActionName 824 f.GetActionName = GetActionName
875 f.GetHotkey = GetHotkey 825 f.GetHotkey = GetHotkey
876 f.SetKey = SetKey 826 end
877 f.FreeKey = FreeKey 827 end
878 f.ClearBindings = ClearBindings 828
879 f.GetBindings = GetBindings 829 -- This is a bit hokey : install a bare hook on ActionButton_UpdateHotkey because
880 buttonLookup[f] = button 830 -- even though it's secure it's never called in a way that can cause taint. This is
881 f:SetKey(button:GetConfig().hotkey) 831 -- for performance reasons to avoid having to hook frame:OnEvent securely.
882 ReAction:RegisterKeybindFrame(f) 832 local UpdateHotkey_old = ActionButton_UpdateHotkeys
883 if ReAction:GetKeybindMode() then 833 ActionButton_UpdateHotkeys = function( frame, ... )
884 button.border:SetVertexColor(KB:GetColorKeyBoundMode()) 834 local b = frame._reactionButton
885 button.border:Show() 835 if b then
886 end 836 b.hotkey:SetText( GetHotkey(frame) )
887 end
888 end
889
890 local meta = {__index = Button}
891
892 function Button:New( handle, idx, config, barConfig )
893 local bar = handle.bar
894
895 -- create new self
896 self = setmetatable(
897 {
898 bar = bar,
899 idx = idx,
900 config = config,
901 barConfig = barConfig,
902 }, meta )
903
904 local name = config.name or ("ReAction_%s_%s_%d"):format(bar:GetName(),moduleID,idx)
905 self.name = name
906 config.name = name
907 local lastButton = handle:GetLastButton()
908 config.actionID = IDAlloc:Acquire(config.actionID, lastButton and lastButton.config.actionID) -- gets a free one if none configured
909 self.nPages = 1
910
911 -- have to recycle frames with the same name: CreateFrame() doesn't overwrite
912 -- existing globals. Can't set to nil in the global because it's then tainted.
913 local parent = bar:GetFrame()
914 local f = frameRecycler[name]
915 if f then
916 f:SetParent(parent)
917 else 837 else
918 f = CreateFrame("CheckButton", name, parent, "ActionBarButtonTemplate") 838 return UpdateHotkey_old(frame, ...)
919 -- ditch the old hotkey text because it's tied in ActionButton_Update() to the 839 end
920 -- standard binding. We use override bindings. 840 end
921 local hotkey = _G[name.."HotKey"] 841 end
922 hotkey:SetParent(trash) 842
923 hotkey = f:CreateFontString(nil, "ARTWORK", "NumberFontNormalSmallGray") 843 local meta = {__index = Button}
924 hotkey:SetWidth(36) 844
925 hotkey:SetHeight(18) 845 function Button:New( handle, idx, config, barConfig )
926 hotkey:SetJustifyH("RIGHT") 846 local bar = handle.bar
927 hotkey:SetJustifyV("TOP") 847
928 hotkey:SetPoint("TOPLEFT",f,"TOPLEFT",-2,-2) 848 -- create new self
929 f.hotkey = hotkey 849 self = setmetatable(
930 f.icon = _G[name.."Icon"] 850 {
931 f.flash = _G[name.."Flash"] 851 bar = bar,
932 f:SetScript("OnUpdate",OnUpdate) 852 idx = idx,
933 end 853 config = config,
934 854 barConfig = barConfig,
935 self.hotkey = f.hotkey 855 }, meta )
936 self.border = _G[name.."Border"] 856
937 857 local name = config.name or ("ReAction_%s_%s_%d"):format(bar:GetName(),moduleID,idx)
938 f:SetAttribute("action", config.actionID) 858 self.name = name
939 f:SetAttribute("default-action", config.actionID) 859 config.name = name
940 -- install mind control actions for all buttons just for simplicity 860 local lastButton = handle:GetLastButton()
941 if self.idx <= 12 then 861 config.actionID = IDAlloc:Acquire(config.actionID, lastButton and lastButton.config.actionID) -- gets a free one if none configured
942 f:SetAttribute("mindcontrol-action", 120 + self.idx) 862 self.nPages = 1
943 end 863
944 864 -- have to recycle frames with the same name: CreateFrame() doesn't overwrite
945 -- set a _childupdate handler, called within the header's context 865 -- existing globals. Can't set to nil in the global because it's then tainted.
946 f:SetAttribute("_childupdate", 866 local parent = bar:GetFrame()
947 -- function _childupdate(self, snippetid, message) 867 local f = frameRecycler[name]
948 [[ 868 if f then
949 local action = "default-action" 869 f:SetParent(parent)
950 if doMindControl and GetBonusBarOffset() == 5 then 870 else
951 action = "mindcontrol-action" 871 f = CreateFrame("CheckButton", name, parent, "ActionBarButtonTemplate")
952 elseif page and state and page[state] then 872 -- ditch the old hotkey text because it's tied in ActionButton_Update() to the
953 action = "action-"..page[state] 873 -- standard binding.
954 end 874 local hotkey = _G[name.."HotKey"]
955 local value = self:GetAttribute(action) 875 hotkey:SetParent(trash)
956 if value then 876 hotkey = f:CreateFontString(nil, "ARTWORK", "NumberFontNormalSmallGray")
957 self:SetAttribute("action",value) 877 hotkey:SetWidth(36)
958 end 878 hotkey:SetHeight(18)
959 ]]) 879 hotkey:SetJustifyH("RIGHT")
960 880 hotkey:SetJustifyV("TOP")
961 -- install drag wrappers to lock buttons 881 hotkey:SetPoint("TOPLEFT",f,"TOPLEFT",-2,-2)
962 bar:GetFrame():WrapScript(f, "OnDragStart", 882 f.hotkey = hotkey
963 -- OnDragStart(self, button, kind, value, ...) 883 f.icon = _G[name.."Icon"]
964 [[ 884 f.flash = _G[name.."Flash"]
965 if lockButtons and (PlayerInCombat() or not lockButtonsCombat) and not IsModifiedClick("PICKUPACTION") then 885 f:SetScript("OnUpdate",OnUpdate)
966 return "clear" 886 end
967 end 887
968 ]]) 888 f._reactionButton = self
969 889
970 self.frame = f 890 self.hotkey = f.hotkey
971 891 self.border = _G[name.."Border"]
972 892
973 -- initialize the hide state 893 f:SetAttribute("action", config.actionID)
974 f:SetAttribute("showgrid",0) 894 f:SetAttribute("default-action", config.actionID)
975 self:ShowGrid(not barConfig.hideEmpty) 895 -- install mind control actions for all buttons just for simplicity
976 if ReAction:GetConfigMode() then 896 if self.idx <= 12 then
977 self:ShowGrid(true) 897 f:SetAttribute("mindcontrol-action", 120 + self.idx)
978 end 898 end
979 899
980 -- show the ID label if applicable 900 -- set a _childupdate handler, called within the header's context
981 self:ShowActionIDLabel(ReAction:GetConfigMode()) 901 f:SetAttribute("_childupdate",
982 902 -- function _childupdate(self, snippetid, message)
983 -- attach the keybinder 903 [[
984 KBAttach(self) 904 local action = "default-action"
985 905 if doMindControl and GetBonusBarOffset() == 5 then
986 -- attach to skinner 906 action = "mindcontrol-action"
987 bar:SkinButton(self, 907 elseif page and state and page[state] then
988 { 908 action = "action-"..page[state]
989 HotKey = self.hotkey, 909 end
990 } 910 local value = self:GetAttribute(action)
991 ) 911 if value then
992 912 self:SetAttribute("action",value)
993 self:Refresh() 913 end
994 return self 914 ]])
995 end 915
996 916 -- install drag wrappers to lock buttons
997 function Button:Destroy() 917 bar:GetFrame():WrapScript(f, "OnDragStart",
918 -- OnDragStart(self, button, kind, value, ...)
919 [[
920 if lockButtons and (PlayerInCombat() or not lockButtonsCombat) and not IsModifiedClick("PICKUPACTION") then
921 return "clear"
922 end
923 ]])
924
925 self.frame = f
926
927 -- initialize the hide state
928 f:SetAttribute("showgrid",0)
929 self:ShowGrid(not barConfig.hideEmpty)
930 if ReAction:GetConfigMode() then
931 self:ShowGrid(true)
932 end
933
934 -- set the hotkey text
935 self.hotkey:SetText( GetHotkey(self.frame) )
936
937 -- show the ID label if applicable
938 self:ShowActionIDLabel(ReAction:GetConfigMode())
939
940 -- attach to skinner
941 bar:SkinButton(self,
942 {
943 HotKey = self.hotkey,
944 }
945 )
946
947 self:Refresh()
948 return self
949 end
950
951 function Button:Destroy()
952 local f = self.frame
953 f:UnregisterAllEvents()
954 f:Hide()
955 f:SetParent(UIParent)
956 f:ClearAllPoints()
957 if self.name then
958 frameRecycler[self.name] = f
959 end
960 if self.config.actionID then
961 IDAlloc:Release(self.config.actionID)
962 end
963 if self.config.pageactions then
964 for _, id in ipairs(self.config.pageactions) do
965 IDAlloc:Release(id)
966 end
967 end
968 f._reactionButton = nil
969 self.frame = nil
970 self.config = nil
971 self.bar = nil
972 end
973
974 function Button:Refresh()
975 local f = self.frame
976 self.bar:PlaceButton(self, 36, 36)
977 self:RefreshPages()
978 end
979
980 function Button:GetFrame()
981 return self.frame
982 end
983
984 function Button:GetName()
985 return self.name
986 end
987
988 function Button:GetConfig()
989 return self.config
990 end
991
992 function Button:GetActionID(page)
993 if page == nil then
994 -- get the effective ID
995 return self.frame.action -- kept up-to-date by Blizzard's ActionButton_CalculateAction()
996 else
997 if page == 1 then
998 return self.config.actionID
999 else
1000 return self.config.pageactions and self.config.pageactions[page] or self.config.actionID
1001 end
1002 end
1003 end
1004
1005 function Button:SetActionID( id, page )
1006 id = tonumber(id)
1007 page = tonumber(page)
1008 if id == nil or id < 1 or id > 120 then
1009 error("Button:SetActionID - invalid action ID")
1010 end
1011 if page and page ~= 1 then
1012 if not self.config.pageactions then
1013 self.config.pageactions = { }
1014 end
1015 if self.config.pageactions[page] then
1016 IDAlloc:Release(self.config.pageactions[page])
1017 end
1018 self.config.pageactions[page] = id
1019 IDAlloc:Acquire(self.config.pageactions[page])
1020 self.frame:SetAttribute(("action-page%d"):format(page),id)
1021 else
1022 IDAlloc:Release(self.config.actionID)
1023 self.config.actionID = id
1024 IDAlloc:Acquire(self.config.actionID)
1025 self.frame:SetAttribute("action",id)
1026 if self.config.pageactions then
1027 self.config.pageactions[1] = id
1028 self.frame:SetAttribute("action-page1",id)
1029 end
1030 end
1031 end
1032
1033 function Button:RefreshPages( force )
1034 local nPages = self.barConfig.nPages
1035 if nPages and (nPages ~= self.nPages or force) then
1036 local f = self:GetFrame()
1037 local c = self.config.pageactions
1038 if nPages > 1 and not c then
1039 c = { }
1040 self.config.pageactions = c
1041 end
1042 for i = 1, nPages do
1043 if i > 1 then
1044 c[i] = IDAlloc:Acquire(c[i], self.config.actionID + (i-1)*self.bar:GetNumButtons())
1045 else
1046 c[i] = self.config.actionID -- page 1 is the same as the base actionID
1047 end
1048 f:SetAttribute(("action-page%d"):format(i),c[i])
1049 end
1050 for i = nPages+1, #c do
1051 IDAlloc:Release(c[i])
1052 c[i] = nil
1053 f:SetAttribute(("action-page%d"):format(i),nil)
1054 end
1055 self.nPages = nPages
1056 end
1057 end
1058
1059 function Button:ShowGrid( show )
1060 if not InCombatLockdown() then
998 local f = self.frame 1061 local f = self.frame
999 f:UnregisterAllEvents() 1062 local count = f:GetAttribute("showgrid")
1000 f:Hide() 1063 if show then
1001 f:SetParent(UIParent) 1064 count = count + 1
1002 f:ClearAllPoints()
1003 if self.name then
1004 frameRecycler[self.name] = f
1005 end
1006 if self.config.actionID then
1007 IDAlloc:Release(self.config.actionID)
1008 end
1009 if self.config.pageactions then
1010 for _, id in ipairs(self.config.pageactions) do
1011 IDAlloc:Release(id)
1012 end
1013 end
1014 self.frame = nil
1015 self.config = nil
1016 self.bar = nil
1017 end
1018
1019 function Button:Refresh()
1020 local f = self.frame
1021 self.bar:PlaceButton(self, 36, 36)
1022 self:RefreshPages()
1023 end
1024
1025 function Button:GetFrame()
1026 return self.frame
1027 end
1028
1029 function Button:GetName()
1030 return self.name
1031 end
1032
1033 function Button:GetConfig()
1034 return self.config
1035 end
1036
1037 function Button:GetActionID(page)
1038 if page == nil then
1039 -- get the effective ID
1040 return self.frame.action -- kept up-to-date by Blizzard's ActionButton_CalculateAction()
1041 else 1065 else
1042 if page == 1 then 1066 count = count - 1
1043 return self.config.actionID 1067 end
1068 if count < 0 then
1069 count = 0
1070 end
1071 f:SetAttribute("showgrid",count)
1072
1073 if count >= 1 and not f:GetAttribute("statehidden") then
1074 if LBF then
1075 LBF:SetNormalVertexColor(self.frame, 1.0, 1.0, 1.0, 0.5)
1044 else 1076 else
1045 return self.config.pageactions and self.config.pageactions[page] or self.config.actionID 1077 self.frame:GetNormalTexture():SetVertexColor(1.0, 1.0, 1.0, 0.5);
1046 end 1078 end
1047 end 1079 f:Show()
1048 end 1080 elseif count < 1 and not HasAction(self:GetActionID()) then
1049 1081 f:Hide()
1050 function Button:SetActionID( id, page ) 1082 end
1051 id = tonumber(id) 1083 end
1052 page = tonumber(page) 1084 end
1053 if id == nil or id < 1 or id > 120 then 1085
1054 error("Button:SetActionID - invalid action ID") 1086 function Button:ShowActionIDLabel( show )
1055 end 1087 local f = self:GetFrame()
1056 if page and page ~= 1 then 1088 if show then
1057 if not self.config.pageactions then 1089 local id = self:GetActionID()
1058 self.config.pageactions = { } 1090 if not f.actionIDLabel then
1059 end 1091 local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
1060 if self.config.pageactions[page] then 1092 label:SetAllPoints()
1061 IDAlloc:Release(self.config.pageactions[page]) 1093 label:SetJustifyH("CENTER")
1062 end 1094 label:SetShadowColor(0,0,0,1)
1063 self.config.pageactions[page] = id 1095 label:SetShadowOffset(2,-2)
1064 IDAlloc:Acquire(self.config.pageactions[page]) 1096 f.actionIDLabel = label -- store the label with the frame for recycling
1065 self.frame:SetAttribute(("action-page%d"):format(page),id) 1097
1066 else 1098 f:HookScript("OnAttributeChanged",
1067 IDAlloc:Release(self.config.actionID) 1099 function(frame, attr, value)
1068 self.config.actionID = id 1100 if label:IsVisible() and attr:match("action") then
1069 IDAlloc:Acquire(self.config.actionID) 1101 label:SetText(tostring(frame.action))
1070 self.frame:SetAttribute("action",id) 1102 end
1071 if self.config.pageactions then 1103 end)
1072 self.config.pageactions[1] = id 1104 end
1073 self.frame:SetAttribute("action-page1",id) 1105 f.actionIDLabel:SetText(tostring(id))
1074 end 1106 f.actionIDLabel:Show()
1075 end 1107 elseif f.actionIDLabel then
1076 end 1108 f.actionIDLabel:Hide()
1077 1109 end
1078 function Button:RefreshPages( force ) 1110 end
1079 local nPages = self.barConfig.nPages 1111
1080 if nPages and (nPages ~= self.nPages or force) then 1112 function Button:SetKeybindMode( mode )
1081 local f = self:GetFrame() 1113 if mode then
1082 local c = self.config.pageactions 1114 KBAttach( self )
1083 if nPages > 1 and not c then 1115 -- set the border for all buttons to the keybind-enable color
1084 c = { } 1116 self.border:SetVertexColor(KB:GetColorKeyBoundMode())
1085 self.config.pageactions = c 1117 self.border:Show()
1086 end 1118 elseif IsEquippedAction(self:GetActionID()) then
1087 for i = 1, nPages do 1119 self.border:SetVertexColor(0, 1.0, 0, 0.35) -- from ActionButton.lua
1088 if i > 1 then 1120 else
1089 c[i] = IDAlloc:Acquire(c[i], self.config.actionID + (i-1)*self.bar:GetNumButtons()) 1121 self.border:Hide()
1090 else 1122 end
1091 c[i] = self.config.actionID -- page 1 is the same as the base actionID 1123 end
1092 end
1093 f:SetAttribute(("action-page%d"):format(i),c[i])
1094 end
1095 for i = nPages+1, #c do
1096 IDAlloc:Release(c[i])
1097 c[i] = nil
1098 f:SetAttribute(("action-page%d"):format(i),nil)
1099 end
1100 self.nPages = nPages
1101 end
1102 end
1103
1104 function Button:ShowGrid( show )
1105 if not InCombatLockdown() then
1106 local f = self.frame
1107 local count = f:GetAttribute("showgrid")
1108 if show then
1109 count = count + 1
1110 else
1111 count = count - 1
1112 end
1113 if count < 0 then
1114 count = 0
1115 end
1116 f:SetAttribute("showgrid",count)
1117
1118 if count >= 1 and not f:GetAttribute("statehidden") then
1119 if LBF then
1120 LBF:SetNormalVertexColor(self.frame, 1.0, 1.0, 1.0, 0.5)
1121 else
1122 self.frame:GetNormalTexture():SetVertexColor(1.0, 1.0, 1.0, 0.5);
1123 end
1124 f:Show()
1125 elseif count < 1 and not HasAction(self:GetActionID()) then
1126 f:Hide()
1127 end
1128 end
1129 end
1130
1131 function Button:ShowActionIDLabel( show )
1132 local f = self:GetFrame()
1133 if show then
1134 local id = self:GetActionID()
1135 if not f.actionIDLabel then
1136 local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
1137 label:SetAllPoints()
1138 label:SetJustifyH("CENTER")
1139 label:SetShadowColor(0,0,0,1)
1140 label:SetShadowOffset(2,-2)
1141 f.actionIDLabel = label -- store the label with the frame for recycling
1142
1143 f:HookScript("OnAttributeChanged",
1144 function(frame, attr, value)
1145 if label:IsVisible() and attr:match("action") then
1146 label:SetText(tostring(frame.action))
1147 end
1148 end)
1149 end
1150 f.actionIDLabel:SetText(tostring(id))
1151 f.actionIDLabel:Show()
1152 elseif f.actionIDLabel then
1153 f.actionIDLabel:Hide()
1154 end
1155 end
1156
1157 function Button:DisplayHotkey( key )
1158 self.hotkey:SetText(key or "")
1159 end
1160 end