+ elseif stype == "macro" then
+ local _, _, macroid = GetMacroSpell(id);
+ if macroid and (spell and macroid == spell or IsSpellOverlayed(macroid)) then
+ if hide then
+ button.glow:Hide();
+ else
+ button.glow:Show();
+ end
+ else
+ button.glow:Hide();
+ end
+ else -- TODO FlyoutHasSpell glow
+ button.glow:Hide();
+ end
+end
+
+local function updateButton(button, slot)
+ if HasAction(slot) then
+ activeButtons[slot] = button;
+ button.base:Show();
+ button.icon:SetTexture(GetActionTexture(slot));
+ updateCooldown(button, slot);
+ updateUsable(button, slot);
+ updateState(button, slot);
+ updateCount(button, slot);
+ updateGlow(button, slot);
+ if not IsConsumableAction(slot) and not IsStackableAction(slot) then
+ button.text:SetText(ssub(GetActionText(slot) or "", 1, 4));
+ button.text:Show();
+ end
+ if button.hotkey.shown then button.hotkey:Show() end
+ else
+ activeButtons[slot] = nil;
+ if not button.grid then button.base:Hide() end
+ button.icon:SetTexture(nil);
+ button.cd:Hide();
+ button.count:Hide();
+ button.hotkey:Hide();
+ button.text:Hide();
+ button.glow:Hide();
+ button:SetChecked(false);
+ end
+end
+
+local function updateHotkeys(button)
+ local key = GetBindingKey(format("CLICK %s:LeftButton", button:GetName()));
+ if key and key ~= "" then
+ -- from LibKeyBound-1.0
+ key = key:upper();
+ key = key:gsub(" ", "");
+ key = key:gsub("ALT%-", "a");
+ key = key:gsub("CTRL%-", "c");
+ key = key:gsub("SHIFT%-", "s");
+ key = key:gsub("NUMPAD", "n");
+ button.hotkey:SetText(key);
+ button.hotkey.shown = true;
+ button.hotkey:Show();
+ else
+ button.hotkey.shown = nil;
+ button.hotkey:Hide();
+ end
+end
+
+local mainbartoggle = "[overridebar][possessbar][shapeshift]possess;";
+mainbartoggle = mainbartoggle.."[bonusbar:1,stealth:1]bonusbar2;"; -- prowl
+mainbartoggle = mainbartoggle.."[bonusbar:1]bonusbar1;[bonusbar:2]bonusbar2;"; -- cat form, unused
+mainbartoggle = mainbartoggle.."[bonusbar:3]bonusbar3;[bonusbar:4]bonusbar4;"; -- bear form, moonkin form
+mainbartoggle = mainbartoggle.."normal";
+local function setupSnippets(secure, slot)
+ -- FrameXML/SecureHandlers.lua has arguments and return value
+ -- args: self, button, kind, value, ... (kind, value, ... from GetCursorInfo())
+ -- returns: kind, target, detail
+ -- or: "clear", kind, target, detail
+ -- used for Pickup* functions
+ -- some of these snippets based on LibActionButton-1.0
+ secure:SetAttribute("_ondragstart", [=[
+ return "action", self:GetAttribute("action");
+ ]=]);
+ secure:SetAttribute("_onreceivedrag", [=[
+ if not kind or not value then return nil end
+ return "action", self:GetAttribute("action");
+ ]=]);
+ -- pre-wrapper can pass a message to post-wrapper
+ secure:WrapScript(secure, "OnDragStart", [=[
+ local kind, value = GetActionInfo(self:GetAttribute("action"));
+ return "message", format("%s|%s", tostring(kind), tostring(value));
+ ]=], [=[
+ local kind, value = GetActionInfo(self:GetAttribute("action"));
+ if message ~= format("%s|%s", tostring(kind), tostring(value)) then
+ self:CallMethod("ActionChanged");
+ end
+ ]=]);
+ secure:WrapScript(secure, "OnReceiveDrag", [=[
+ local kind, value = GetActionInfo(self:GetAttribute("action"));
+ return "message", format("%s|%s", tostring(kind), tostring(value));
+ ]=], [=[
+ local kind, value = GetActionInfo(self:GetAttribute("action"));
+ if message ~= format("%s|%s", tostring(kind), tostring(value)) then
+ self:CallMethod("ActionChanged");
+ end
+ ]=]);
+ function secure:UpdateState()
+ return updateState(self, self.slot);
+ end
+ secure:WrapScript(secure, "OnClick", [=[
+ local kind, value = GetActionInfo(self:GetAttribute("action"));
+ return nil, format("%s|%s", tostring(kind), tostring(value));
+ ]=], [=[
+ local kind, value = GetActionInfo(self:GetAttribute("action"));
+ if message ~= format("%s|%s", tostring(kind), tostring(value)) then
+ self:CallMethod("ActionChanged");
+ else
+ self:CallMethod("UpdateState");
+ end
+ ]=]);
+ if slot < 13 then
+ -- first action bar has possible states based on vehicle/possess etc.
+ secure:SetAttribute("origaction", slot);
+ secure:SetAttribute("_onstate-possess", [=[
+ local oldslot = self:GetAttribute("action");
+ if newstate == "possess" then
+ local slot;
+ if HasVehicleActionBar() then
+ slot = (GetVehicleBarIndex()-1)*12+self:GetAttribute("origaction");
+ elseif HasOverrideActionBar() then
+ slot = (GetOverrideBarIndex()-1)*12+self:GetAttribute("origaction");
+ elseif HasTempShapeshiftActionBar() then
+ slot = (GetTempShapeshiftBarIndex()-1)*12+self:GetAttribute("origaction");
+ else
+ -- something wrong, just revert to normal
+ print("Possess bar index not found");
+ slot = self:GetAttribute("origaction");
+ end
+ self:SetAttribute("action", slot);
+ elseif newstate == "bonusbar1" then
+ self:SetAttribute("action", 72+self:GetAttribute("origaction"));
+ elseif newstate == "bonusbar2" then
+ self:SetAttribute("action", 84+self:GetAttribute("origaction"));
+ elseif newstate == "bonusbar3" then
+ self:SetAttribute("action", 96+self:GetAttribute("origaction"));
+ elseif newstate == "bonusbar4" then
+ --self:SetAttribute("action", 108+self:GetAttribute("origaction"));
+ -- moonkin form, don't change actionbar
+ self:SetAttribute("action", self:GetAttribute("origaction"));
+ else
+ self:SetAttribute("action", self:GetAttribute("origaction"));
+ end
+ self:CallMethod("ActionChanged", oldslot);
+ ]=]);
+ RegisterStateDriver(secure, "possess", mainbartoggle);
+ else
+ function secure:ShowButton() if HasAction(slot) then activeButtons[slot] = self end end
+ function secure:HideButton() activeButtons[slot] = nil end
+ -- all other action bar are hidden if with overridebar or vehicleui (not shapeshift, possessbar)
+ -- default Bartender4 options
+ secure:SetAttribute("_onstate-possess", [=[
+ if newstate == "possess" then
+ self:Hide();
+ self:CallMethod("HideButton");
+ else
+ self:Show();
+ self:CallMethod("ShowButton");
+ end
+ ]=]);
+ RegisterStateDriver(secure, "possess", "[overridebar][vehicleui] possess; normal");
+ end
+end
+
+local function createActionBar(parent, config)
+ local prev;
+ local i = 0;
+ local bar = CreateFrame("Frame", "OmaBTBar"..config.bar, parent, "SecureFrameTemplate");
+ bar:SetPoint("TOPLEFT", parent, "BOTTOMLEFT", config.x, config.y);
+ bar:SetWidth(1);
+ bar:SetHeight(1);
+ if config.hidden then
+ bar:Hide();
+ end
+ for slot = config.start, config.start+config.length-1 do
+ local secure = CreateFrame("CheckButton", "OmaBT"..slot, bar, inheritedFrames);
+ secure.slot = slot;
+ if slot == config.start then
+ secure:SetPoint("TOPLEFT");
+ elseif config.columns and i % config.columns == 0 then
+ secure:SetPoint("TOPLEFT", _G["OmaBT"..(slot-config.columns)], "BOTTOMLEFT");
+ else
+ secure:SetPoint("TOPLEFT", prev, "TOPRIGHT");
+ end
+ secure:RegisterForClicks("AnyUp");
+ if not BUTTONLOCK then
+ secure:RegisterForDrag("LeftButton", "RightButton");
+ end
+ if config.nomouse then
+ secure:EnableMouse(false);
+ end
+ secure:SetWidth(config.size or 32);
+ secure:SetHeight(config.size or 32);
+ secure.base = secure:CreateTexture(nil, "BACKGROUND");
+ secure.base:SetAllPoints();
+ secure.base:SetColorTexture(0, 0, 0, 0.5);
+ secure.iconbase = secure:CreateTexture(nil, "BORDER");
+ secure.iconbase:SetPoint("TOPLEFT", secure.base, "TOPLEFT", 1, -1);
+ secure.iconbase:SetPoint("BOTTOMRIGHT", secure.base, "BOTTOMRIGHT", -1, 1);
+ secure.iconbase:SetColorTexture(0, 0, 0, 0.5);
+ secure.iconbase:Hide();
+ secure.icon = secure:CreateTexture(nil, "ARTWORK");
+ secure.icon:SetPoint("TOPLEFT", secure.iconbase, "TOPLEFT");
+ secure.icon:SetPoint("BOTTOMRIGHT", secure.iconbase, "BOTTOMRIGHT");
+ secure.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93);
+ secure:SetCheckedTexture("Interface\\Buttons\\CheckButtonHilight");
+ secure.autocastable = secure:CreateTexture(nil, "OVERLAY");
+ secure.autocastable:SetPoint("CENTER");
+ secure.autocastable:SetWidth(58);
+ secure.autocastable:SetHeight(58);
+ secure.autocastable:SetTexture("Interface\\Buttons\\UI-AutoCastableOverlay");
+ secure.autocastable:Hide();
+ secure.glow = secure:CreateTexture(nil, "OVERLAY", nil, 1);
+ secure.glow:SetPoint("CENTER");
+ secure.glow:SetWidth(config.size and config.size+20 or 52);
+ secure.glow:SetHeight(config.size and config.size+20 or 52);
+ secure.glow:SetTexture("Interface\\SpellActivationOverlay\\IconAlert");
+ secure.glow:SetTexCoord(0.00781250, 0.50781250, 0.27734375, 0.52634375);
+ secure.glow:Hide();
+ secure.hotkey = secure:CreateFontString(nil, "OVERLAY", "NumberFontNormalGray");
+ secure.hotkey:SetPoint("TOPRIGHT", secure, "TOPRIGHT", 2, -1);
+ secure.count = secure:CreateFontString(nil, "OVERLAY", "NumberFontNormal");
+ secure.count:SetPoint("BOTTOMRIGHT", secure, "BOTTOMRIGHT", 2, -1);
+ secure.text = secure:CreateFontString(nil, "OVERLAY", "NumberFontNormal");
+ secure.text:SetPoint("BOTTOMLEFT", secure, "BOTTOMLEFT", 2, -1);
+ secure.text:Hide();
+ secure.cd = CreateFrame("Cooldown", "OmaBTCD"..slot, secure, "CooldownFrameTemplate");
+ secure.cd:SetAllPoints();
+ secure:SetAttribute("type", "action");
+ secure:SetAttribute("action", slot);
+ if config.flyout then
+ secure:SetAttribute("flyoutDirection", config.flyout);
+ end
+ function secure:ActionChanged(oldslot)
+ if oldslot then activeButtons[oldslot] = nil end
+ self.slot = self:GetAttribute("action");
+ return updateButton(self, self.slot);
+ end
+ secure:ActionChanged(); -- initial update
+ setupSnippets(secure, slot);
+ updateHotkeys(secure);
+ buttons[slot] = secure;
+ prev = secure;
+ i = i + 1;
+ end