Saving addon position

Back with another question that’s probably got an obvious answer but I’m not seeing it. Trying to get my addon to remember where the user positioned it and it’s not working properly.

Saving top and left values and then reapplying them on load as follows;

In ADDON_LOADED:

		if CarnSettings == nil then
			CarnSettings = {
			Left = 0,
			Top = 0,

In PLAYER_LOGOUT:

		CarnSettings = {
			Top = CarnMainFrame:GetTop(),
			Left = CarnMainFrame:GetLeft(),

In the main frame creation:

CarnMainFrame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", CarnSettings.Left, CarnSettings.Top)

Firstly, I’ll say that the “Left” or “X” value is never affected in this. It always works properly.

The problems are twofold, firstly when it’s saving postion the “Top” position is getting incremented not replaced. So if it’s at 1000 it becomes 2000 on exit, and next exit it becomes 3000 and so on. I’ve confirmed this by logging out and checking the savedvariables file.

Second, the “Top” (Y) value is positioning the frame offscreen. I’d have assumed saving the offset would save a negative value but it doesn’t appear to. So I tried using CarnSettings.Top*-1 and that helps, but it’s still not positioning properly. The form is flip-flopping between the wrong and right position on alternating reloads. Every second reload it’s in the perfect position. Every other one it’s positioned wrongly on the Y-Axis. I’m guessing that the value in the savedvariables is still being incremented but because I’m applying a negative that offsets it every second load.

So first question: Why is it incrementing the “Top” (Y axis) savedvariable instead of setting it to the current value?

Secondly, from what I understand it should be positioning the top-left corner of the addon frame based on the top-left corner of the UI (basically the whole screen). So why does the X axis work but not the Y? I noticed (https://wowwiki-archive.fandom.com/wiki/API_Region_GetBottom) that GetTop() “is only guaranteed to work after the PLAYER_LOGIN event and then, only if the object in question is being Shown”. Player Login has definitely happened but I can’t guarantee that the addon is visible when logging out (it’s often not).

For now, I’ve clamped the frame to the screen so it’s always appearing now but obviously it’s not in the right place.

frame:GetTop() gets the top relative to the BOTTOMLEFT of UIParent.

Are you saving position per user? Why not let the system handle it naturally? When you StopMovingOrSizing, it will set UserPlaced and remember that position, unless you force a position on login.

Also, you can also set the top and left while you do the StopMovingOrSizing too. You don’t need to wait until PLAYER_LOGOUT.

1 Like

Doh, ok. The Wiki only has an entry for “GetBottom” and that’s what it said. So naturally (incorrectly) I assumed that GetTop would be from the TOPLEFT. Switching my anchorpoint should fix that then.

Not using per user saves at the moment but I may in the future. I found that relying on the default positioning like you suggest just sometimes doesn’t work. It’d load in the right place most of the time, but then it’d (seemingly randomly) load in the default position and I hadn’t cleared saved variables to reset it to defaults.

edit: Ok, changed to:

CarnMainFrame:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", CarnSettings.Left, CarnSettings.Top)

And it’s positioning properly now. The value it was incrementing by was (in hindsight) obviously the height of the frame. And now that I’ve got it saving correctly I’ll also update the variable on stop moving (didn’t want to muddy the waters by adding more changes to the variable).

Thanks again for your help.

edit2: Just another thought related to moving frames around. I open a second frame for my settings and if I drag my main frame the settings frame gets dragged around too. However if I move the settings frame then drag the main frame around the settings frame is no longer moved as well. I’m guessing this is because the settings frame’s UserPlaced value gets set by manually moving it so it no longer attached to the main frame when that is moved? Is it possible to override that?

This is super dependent on implementation and what you want. If you want your settings to appear in the same position relative to its parent window, you can record the difference and reanchor to the parent based on the difference.

Fair enough. I might just leave it as it is. Its not like it’s hard to move the frame around manually.