UI Resizing Repositioning - meldavy/ipf-documentation GitHub Wiki
I've been working on an addon that modifies an existing frame, in this case an addon that modifies the Card Info frame and injects a button, and resizes and existing one.
extractAllButton:SetPos(needSilverText:GetX(), needSilverText:GetY() + needSilverText:GetHeight() + 5);
extractAllButton:Resize(needSilverText:GetWidth(), needSilverText:GetHeight());
Basically, SetPos(x, y) can be used to modify location, and Resize(width, height) can be used to modify size.
Additionally, you might run into the situation where a position of a control was set using margins rather than absolute position. In this case, it might also be easier to just modify margin:
needSilverText:SetGravity(ui.LEFT, ui.BOTTOM);
needSilverText:SetMargin(25, 0, 0, 150);
In the above example, we set the gravity so that the control's location is relative to the bottom-left of the parent frame, and by setting the bottom margin to 150, this control is 150 pixels above.
Invalidate
Now this is the real reason why I wanted to write this. Problem with pure LUA based UI code is that multiple position changes, multiple resizing, or chained text changes actually cause a ton of UI related issues.
For instance, the following code will cause many UI issues:
button:Resize(needSilverText:GetWidth(), needSilverText:GetHeight());
button:Resize(needSilverText:GetWidth(), needSilverText:GetHeight() - 5);
button:Resize(needSilverText:GetWidth(), needSilverText:GetHeight() - 10);
button:SetText("hello");
button:SetText("world");
In the above scenario, the button might be stuck with "hello" as the text and drop the "world" update request.
In most UI frameworks such as winforms, android, etc, Invalidate() is our friend. It forces all ui to be redrawn. But in TOS, even Invalidate() runs into the same issue:
button:Resize(needSilverText:GetWidth(), needSilverText:GetHeight());
button:Resize(needSilverText:GetWidth(), needSilverText:GetHeight() - 5);
button:Resize(needSilverText:GetWidth(), needSilverText:GetHeight() - 10);
button:SetText("hello");
button:SetText("world");
button:Invalidate(); -- this won't do anything!!!
To fix this, we want a delayed invalidate:
function DRAW_UI()
... ui code stuff
ReserveScript("INVALIDATE_BUTTON()", 0.01);
....
end
function INVALIDATE_BUTTON()
ui.GetFrame('myframe'):GetChildRecursively('button'):Invalidate();
end