I wrote a little addon for myself that adds a button to the macro UI that allows you to run the selected macro, without putting it on your bars or having a keybind for it. With certain macros that I'm using that feature just seemed handy.
Anyway, while doing that I encountered a little problem:
I wanted to position the Run button between the Save and Cancel buttons, so I moved them a few more pixels apart and tried to anchor the new button to one of the two. As you can guess from the title it didn't work.
For now, I'm positioning the button where I want it by using the whole MacroFrame as point of reference.
Here's my code for you to review and perhaps you can tell me why anchoring the button didn't work:
local f = CreateFrame("Frame")
local function CreateRunButton()
MacroCancelButton:ClearAllPoints()
MacroCancelButton:SetPoint("BOTTOMRIGHT", "MacroFrameScrollFrame", "TOPRIGHT", 25, 6)
MacroSaveButton:ClearAllPoints()
MacroSaveButton:SetPoint("BOTTOM", "MacroCancelButton", "TOP", 0, 23)
local btn = CreateFrame("Button", "MacroRunButton", MacroFrame, "UIPanelButtonTemplate, SecureActionButtonTemplate")
btn:SetText("Run")
btn:SetSize(80, 22)
--btn:SetPoint("BOTTOM", "MacroCancelButton", "TOP", 0, 2) --TODO: find out why this doesn't work
btn:SetPoint("RIGHT", "MacroFrame", "RIGHT", -11, -43)
btn:SetFrameStrata("HIGH")
btn:SetAttribute("type1", "macro")
btn:SetAttribute("macro", -1)
for i = 1, 36 do
_G["MacroButton"..i]:HookScript("OnClick", function(self) btn:SetAttribute("macro",MacroFrame.selectedMacro) end)
end
f:UnregisterEvent("ADDON_LOADED")
end
if not IsAddOnLoaded("Blizzard_MacroUI") then
f:RegisterEvent("ADDON_LOADED")
f:SetScript("OnEvent", function(self, event, addon)
if addon == "Blizzard_MacroUI" then
CreateRunButton()
end
end)
else
CreateRunButton()
end
What, exactly, "doesn't work"? Is your button in the wrong place, or does it not show up at all, or the wrong size, or...?
The only things I can think of without knowing the symptoms are: (1) if the name "MacroRunButton" is already in use somewhere, weirdness will happen. You might want to prefix your addon name to that string. And (2) instead of hanging both your button and the Save button off the edge of the Cancel button, what happens when you hang Save off of yours, in a chain of references?
(Not a bug but a suggestion for futureproofing: instead of hardcoding the "36", you could do the same as the macro frame's own code does:
for i = 1, max (MAX_ACCOUNT_MACROS, MAX_CHARACTER_MACROS) do
Some thoughts.
a)
You are giving the relative point as a string. I never do that. I suppose it works, though wowprogramming does not lists string as allowed arguments. However I suggest using a reference instead.
Replace
I thought (and used) always "type", maybe I am missing something.
d) Delayed loading.
It seems your frame is only used for receiving the "ADDON_LOADED" event.
In that case I would suggest only creating the frame when you need it. You will need to move the f:UnregisterEvent(...) out of the CreateRunButton method.
e) Framestrata
You might want to have the run buttons framestrata the same as the others.
I suggest
@Farmbuyer:
Thanks for your post and yeah, I should have mentioned that the button doesn't even show up if I try to anchor it to the save or cancel button. Must have slipped my mind, I was kinda sleepy already at the time of posting...
In response to the other points:
(1) The name MacroRunButton isn't used by anything else, neither default interface nor addon, and as it's for private use only atm I didn't bother with a unique name for it. Perhaps I really should change it...
(2) The relative positioning for the save button is the same as it's by default except for a few more pixels distance. That's why I used the cancel button as an anchor. I'll try and see if chaining them would help, though it would surprise me... Why wouldn't you be able to anchor two interface elements to one and the same anchor?
As for your suggestion, certainly not a bad idea. I'l probably do that later.
@Graveeater:
a) It really doesn't matter if you use the reference or name, it didn't matter for my problem.
b) As I don't want to use it in Combat it didn't matter until now, I'll have to test if that's a problem later.
c) Left click only ;-)
d) Yeah, the code above was just a really fast writeup, so stuff like that wasn't really of high priority. But I'll certainly change it.
e) High is the same framestrata as the other buttons use afaik, though for future proofing the change certainly wouldn't be bad.
will become a global variable, i.e, these names should be unique.
Of course it is possible to anchor more than one frame (buttons are frames) to the same frame. That happens all the time. In fact in your scenario they are all anchored to MacroFrame.
An of course you can use the same relative point in a frame more than once.
Yeah, as I mentioned in my reply, I wouldn't know why anchoring like that would be a problem.
And, as I said as well, the global name isn't used by anything else. Though I probably will prefix it with something unique.
I can verify that anchoring to any of the child buttons doesn't work, I have no idea why.
In order not to make this an entirely useless post however I think this is a simpler way to do what you want that avoids all those hooks.
local f = CreateFrame("Frame")
local function CreateRunButton()
MacroSaveButton:ClearAllPoints()
MacroSaveButton:SetPoint("BOTTOM",MacroCancelButton,"TOP",0,28)
local btn = CreateFrame("Button","MacroRunButton",MacroFrame,"UIPanelButtonTemplate, SecureActionButtonTemplate")
btn:SetSize(80,22)
btn:SetText("Run")
btn:SetPoint("BOTTOMRIGHT",MacroFrame,"BOTTOMRIGHT",-33,165)
btn:SetFrameStrata("HIGH")
btn:SetAttribute("type1","macro")
btn:SetScript("PreClick",function(self,mb,d) if not InCombatLockdown() then self:SetAttribute("macro1",MacroFrame.selectedMacro or nil) end end)
btn:Show()
f:UnregisterEvent("ADDON_LOADED")
end
if not IsAddOnLoaded("Blizzard_MacroUI") then
f:RegisterEvent("ADDON_LOADED")
f:SetScript("OnEvent", function(self, event, addon)
if addon == "Blizzard_MacroUI" then
CreateRunButton()
end
end)
else
CreateRunButton()
end
Thanks for that suggestion Dridzt, it certainly looks more elegant than my sleepyly coded attempt.
I still wonder why anchoring doesn't work right, but whatever, it wasn't that important anyway.
Rollback Post to RevisionRollBack
To post a comment, please login or register a new account.
I wrote a little addon for myself that adds a button to the macro UI that allows you to run the selected macro, without putting it on your bars or having a keybind for it. With certain macros that I'm using that feature just seemed handy.
Anyway, while doing that I encountered a little problem:
I wanted to position the Run button between the Save and Cancel buttons, so I moved them a few more pixels apart and tried to anchor the new button to one of the two. As you can guess from the title it didn't work.
For now, I'm positioning the button where I want it by using the whole MacroFrame as point of reference.
Here's my code for you to review and perhaps you can tell me why anchoring the button didn't work:
Thanks in advance!
The only things I can think of without knowing the symptoms are: (1) if the name "MacroRunButton" is already in use somewhere, weirdness will happen. You might want to prefix your addon name to that string. And (2) instead of hanging both your button and the Save button off the edge of the Cancel button, what happens when you hang Save off of yours, in a chain of references?
(Not a bug but a suggestion for futureproofing: instead of hardcoding the "36", you could do the same as the macro frame's own code does:
to make it self-adjusting.)
a)
You are giving the relative point as a string. I never do that. I suppose it works, though wowprogramming does not lists string as allowed arguments. However I suggest using a reference instead.
Replace
by
b) Taint.
I suppose clicking on a macro with your addon enabled will create taint.
You might want to rewrite your
At least you should add a InCombatLockdown check.
c) Typo?
I thought (and used) always "type", maybe I am missing something.
d) Delayed loading.
It seems your frame is only used for receiving the "ADDON_LOADED" event.
In that case I would suggest only creating the frame when you need it. You will need to move the f:UnregisterEvent(...) out of the CreateRunButton method.
e) Framestrata
You might want to have the run buttons framestrata the same as the others.
I suggest
Answering your original question would be easier if you stated the exact problem. Maybe a Screenshot can help.
Thanks for your post and yeah, I should have mentioned that the button doesn't even show up if I try to anchor it to the save or cancel button. Must have slipped my mind, I was kinda sleepy already at the time of posting...
In response to the other points:
(1) The name MacroRunButton isn't used by anything else, neither default interface nor addon, and as it's for private use only atm I didn't bother with a unique name for it. Perhaps I really should change it...
(2) The relative positioning for the save button is the same as it's by default except for a few more pixels distance. That's why I used the cancel button as an anchor. I'll try and see if chaining them would help, though it would surprise me... Why wouldn't you be able to anchor two interface elements to one and the same anchor?
As for your suggestion, certainly not a bad idea. I'l probably do that later.
@Graveeater:
a) It really doesn't matter if you use the reference or name, it didn't matter for my problem.
b) As I don't want to use it in Combat it didn't matter until now, I'll have to test if that's a problem later.
c) Left click only ;-)
d) Yeah, the code above was just a really fast writeup, so stuff like that wasn't really of high priority. But I'll certainly change it.
e) High is the same framestrata as the other buttons use afaik, though for future proofing the change certainly wouldn't be bad.
Of course it is possible to anchor more than one frame (buttons are frames) to the same frame. That happens all the time. In fact in your scenario they are all anchored to MacroFrame.
An of course you can use the same relative point in a frame more than once.
And, as I said as well, the global name isn't used by anything else. Though I probably will prefix it with something unique.
In order not to make this an entirely useless post however I think this is a simpler way to do what you want that avoids all those hooks.
Why would they do that...
If you're worried you could even hide your button by not putting it in the global namespace.
But I don't understand the question tbh :)
I still wonder why anchoring doesn't work right, but whatever, it wasn't that important anyway.