Thread Tools Display Modes
07-27-13, 11:35 AM   #1
Mayron
A Frostmaul Preserver
 
Mayron's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2010
Posts: 275
Move the Watch Frame onLoad?

Hi guys,

I am using this following script on the OnUpdate window in kgPanels to move the Watch Frame:
WatchFrame:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 50, -20)

However I usually hate having things on the OnUpdate and try to always avoid it when ever possible. In this case I want to change it to the OnLoad script window because then I can use other Lua scripts in the future to move it when ever needed.

My issue is that if I use the same script on Load instead it does not work. This is because of the loading order I think as it is too quick and Blizzard moves this to its original location so my script does not do anything.

I really do not know where to begin with this, can anyone help or point me in the right direction? Thank you!
  Reply With Quote
07-27-13, 12:29 PM   #2
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
You could try WatchFrame:SetUserPlaced(true) to prevent Blizzard code from repositioning the frame. You also normally have to call ClearAllPoints() before setting your points. You could also try using OnShow or OnSizeChanged instead of OnLoad.
  Reply With Quote
07-27-13, 12:34 PM   #3
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Yes, avoid OnUpdate scripts whenever possible.

1. When moving frames, always call :ClearAllPoints() first. (Multiple :SetPoint() calls can be used for one frame to alter its size and anchoring)

2. In my Who Framed Watcher Wabbit addon, I move the WatchFrame after the PLAYER_ENTERING_WORLD event fires. In your OnLoad script put self:RegisterEvent("PLAYER_ENTERING_WORLD" then in your OnEvent script put your code for moving it.

3. As mentioned in #1 above, multiple :SetPoint() calls can influence the anchoring and size of a frame - this is what the WatchFrame does. Once you move it, you may find that it is smaller than you would like (only showing one or two quests, due to it being 40px tall, iirc). You'll then need to call :SetHeight() on the frame with the size you wish it to be.
__________________
"You'd be surprised how many people violate this simple principle every day of their lives and try to fit square pegs into round holes, ignoring the clear reality that Things Are As They Are." -Benjamin Hoff, The Tao of Pooh

  Reply With Quote
07-27-13, 02:13 PM   #4
Mayron
A Frostmaul Preserver
 
Mayron's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2010
Posts: 275
No still no use, I think it is just because kgPanels load quicker. Only OnUpdate has any effect

Last edited by Mayron : 07-27-13 at 02:23 PM.
  Reply With Quote
07-27-13, 08:23 PM   #5
pelf
Sentient Plasmoid
 
pelf's Avatar
Premium Member
Join Date: May 2008
Posts: 133
You could register for the ADDON_LOADED event and look for "Blizzard_QuestChoice" (which is the one that has the Watch Frame in it). Once that addon loads, then try moving the frame, and unregister the event.
  Reply With Quote
07-27-13, 08:37 PM   #6
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
Originally Posted by pelf View Post
You could register for the ADDON_LOADED event and look for "Blizzard_QuestChoice" (which is the one that has the Watch Frame in it). Once that addon loads, then try moving the frame, and unregister the event.
That is untrue. The watch frame is handled by WatchFrame.lua/xml.
  Reply With Quote
07-27-13, 08:54 PM   #7
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Mayron View Post
No still no use, I think it is just because kgPanels load quicker. Only OnUpdate has any effect
It has nothing to do with the load order of anything. The WatchFrame moves because the default UI moves it (see UIParent.lua, lines 2190-2210). Based on the current state of that code, you should be able to prevent the default UI from moving the WatchFrame by calling this, once:

Code:
WatchFrame:SetUserPlaced(true)
If that doesn't work, you can always use a simple post-hook:

Code:
hooksecurefunc("UIParent_ManageFramePositions", function()
	WatchFrame:ClearAllPoints()
	WatchFrame:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 50, -20)
end)
Personally, I avoid the whole problem by just nuking the WatchFrame's ClearAllPoints and SetPoints methods:

Code:
local noop = function() end
WatchFrame.ClearAllPoints = noop
WatchFrame.SetPoint = noop
...but that would make it more difficult to move the frame via scripts later.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
07-27-13, 09:39 PM   #8
pelf
Sentient Plasmoid
 
pelf's Avatar
Premium Member
Join Date: May 2008
Posts: 133
I see what I did... well, that's the last time I use wowprogramming's FrameXML browser . GitHub is prettier, anyway.

EDIT: What in the world is go-hero.net? I've never seen that one.

Last edited by pelf : 07-27-13 at 09:42 PM.
  Reply With Quote
07-27-13, 10:00 PM   #9
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
In order to use SetUserPlaced(true) you have to call WatchFrame:SetMovable(true). To sum it up:

OnLoad script:
Code:
self:RegisterEvent("PLAYER_ENTERING_WORLD")
OnEvent script:
Code:
WatchFrame:SetMovable(true)
WatchFrame:SetUserPlaced(true)
WatchFrame:SetPoint("TOPRIGHT", Minimap, "BOTTOMLEFT", 50, -20)
You don't have to call ClearAllPoints() as long as you use "TOPRIGHT" as your anchor point, because that's the only anchor point used by Blizzard to position the WatchFrame and the SetPoint call overwrites it.
  Reply With Quote
07-27-13, 11:50 PM   #10
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
You shouldn't need to delay until PLAYER_ENTERING_WORLD to call that code, since by the time kgPanels is loaded and running your custom scripts, all the default UI code has already been loaded.

Originally Posted by Rainrider View Post
You don't have to call ClearAllPoints() as long as you use "TOPRIGHT" as your anchor point, because that's the only anchor point used by Blizzard to position the WatchFrame and the SetPoint call overwrites it.
See the code in UIParent.lua I linked to in my previous post; if that code has run before your code runs, then the BOTTOMRIGHT point will also have been set. Calling ClearAllPoints costs basically nothing, but avoids any problems that might cause.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
07-28-13, 01:09 AM   #11
Mayron
A Frostmaul Preserver
 
Mayron's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2010
Posts: 275
Originally Posted by Phanx View Post
Code:
hooksecurefunc("UIParent_ManageFramePositions", function()
	WatchFrame:ClearAllPoints()
	WatchFrame:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 50, -20)
end)
Thank you Phanx. The "WatchFrame:SetUserPlaced(true)" did not work since it said the WatchFrame is not moveable or something like that however the hooksecurefunc was what I needed and works perfectly!

I then read from Rainrider that I could have used "WatchFrame:SetMovable(true)" so thank you for that but I tried out hooksecurefunc() first.

Appreciate it and to all others who have helped as well!

Also thank you for making this very clear to me as that should help me in the future:

Originally Posted by Phanx View Post
You shouldn't need to delay until PLAYER_ENTERING_WORLD to call that code, since by the time kgPanels is loaded and running your custom scripts, all the default UI code has already been loaded.

Last edited by Mayron : 07-28-13 at 01:13 AM.
  Reply With Quote
07-29-13, 12:31 PM   #12
Mayron
A Frostmaul Preserver
 
Mayron's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2010
Posts: 275
Hi guys,

In the end the only script that would work is the following:

Code:
local WatchEvent = CreateFrame("Frame")
WatchEvent:RegisterEvent("PLAYER_ENTERING_WORLD") 
WatchEvent:SetScript("OnEvent", function()
	WatchFrame:SetMovable(true)
	WatchFrame:SetUserPlaced(true)
	WatchFrame:SetHeight(300)
	if MBar3:IsVisible() and not MBar4:IsVisible() then
		WatchFrame:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 80, -20)
	elseif MBar4:IsVisible() then
		WatchFrame:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 40, -20)
	else
		WatchFrame:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 120, -20)
	end
end)
I have another issue though. The "WatchFrame:SetHeight(300)" line does not work as it appears to not have any limit. I can track any number of quests and it all shows up and its too long. Does anyone know why this might be?
  Reply With Quote
07-29-13, 03:18 PM   #13
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
As Phanx stated before, FrameXML is loaded before addons, meaning WatchFrame.lua/.xml and UIParent.lua were ran before your code was evaluated. Thus UIParent.lua ran this line:
Code:
WatchFrame:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT", -CONTAINER_OFFSET_X, CONTAINER_OFFSET_Y);
(see the link from Phanx above)

So, you either call WatchFrame:ClearAllPoints() and then use WatchFrame:SetHeight(300) or you overwrite the BOTTOMRIGHT anchor and do the math for the height you want (WatchFrame:GetTop() - WatchFrame:GetBottom())

Apart from that, as Phanx said, and you quoted, you don't need your WatchEvent frame and wait for PLAYER_ENTERING_WORLD.

I'm sorry that my previous explanations proved misleading or wrong, I didn't take all aspects into account and just aimed at minimal code. Please accept my apologies.
  Reply With Quote
07-29-13, 04:50 PM   #14
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Mayron View Post
I have another issue though. The "WatchFrame:SetHeight(300)" line does not work as it appears to not have any limit. I can track any number of quests and it all shows up and its too long. Does anyone know why this might be?
I don't know why, but I avoid the issue by setting the height implicitly instead of explicitly:

Code:
WatchFrame:ClearAllPoints()
WatchFrame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 30, 10)
WatchFrame:SetPoint("BOTTOMLEFT", UIParent, "LEFT", 30, -100)
Also, if you want a custom width:

Code:
hooksecurefunc("WatchFrame_SetWidth", function(width)
	WATCHFRAME_EXPANDEDWIDTH = 406 -- adjust as desired
	WATCHFRAME_MAXLINEWIDTH = 394 -- needs to be about 12px narrower than above
	if WatchFrame:IsShown() and not WatchFrame.collapsed then
		WatchFrame:SetWidth(WATCHFRAME_EXPANDEDWIDTH)
		WatchFrame_Update()
	end
end)

-- do this with the rest of your initialization stuff:
WatchFrame_SetWidth(1)
WatchFrame_Update(WatchFrame)
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
07-30-13, 04:02 AM   #15
Mayron
A Frostmaul Preserver
 
Mayron's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2010
Posts: 275
I managed to get it working with this:

Code:
local WatchEvent = CreateFrame("Frame")
WatchEvent:RegisterEvent("PLAYER_ENTERING_WORLD") 
WatchEvent:SetScript("OnEvent", function()
	WatchFrame:ClearAllPoints()
	WatchFrame:SetHeight(400)
	if MBar3:IsVisible() and not MBar4:IsVisible() then
		WatchFrame:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 80, -20)
	elseif MBar4:IsVisible() then
		WatchFrame:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 40, -20)
	else
		WatchFrame:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 120, -20)
	end
end)
However it only works when I login. When I reload the UI with the command then it resets itself back to its default look. Do you know why this is or how to fix it? Also I tried running it without the "PLAYER_ENTERING_WORLD" and it does not take effect by changing anything.
  Reply With Quote
07-30-13, 07:22 AM   #16
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
That's why you need SetUserPlaced(true), else the default ui will reposition the frame. What should work is this:

Lua Code:
  1. local wf = WatchFrame
  2. wf:SetMovable(true)
  3. wf:SetUserPlaced(true)
  4. wf:ClearAllPoints()
  5. if MBar3:IsVisible() and not MBar4:IsVisible() then
  6.     wf:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 80, -20)
  7. elseif MBar4:IsVisible() then
  8.     wf:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 40, -20)
  9. else
  10.     wf:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 120, -20)
  11. end
  12. wf:SetHeight(400)

You should be able to place the whole code in the OnLoad script for your kgPanels frame.
  Reply With Quote
07-30-13, 10:26 AM   #17
Mayron
A Frostmaul Preserver
 
Mayron's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2010
Posts: 275
Originally Posted by Rainrider View Post
That's why you need SetUserPlaced(true), else the default ui will reposition the frame. What should work is this:

Lua Code:
  1. local wf = WatchFrame
  2. wf:SetMovable(true)
  3. wf:SetUserPlaced(true)
  4. wf:ClearAllPoints()
  5. if MBar3:IsVisible() and not MBar4:IsVisible() then
  6.     wf:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 80, -20)
  7. elseif MBar4:IsVisible() then
  8.     wf:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 40, -20)
  9. else
  10.     wf:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 120, -20)
  11. end
  12. wf:SetHeight(400)

You should be able to place the whole code in the OnLoad script for your kgPanels frame.
Thank you! This works at the same time as does not work. It is very strange but if I use this code in the OnLoad kgPanel script on its own then it does not work when I ReloadUI. However if I use the script below on its own:

Code:
local WatchEvent = CreateFrame("Frame")
WatchEvent:RegisterEvent("PLAYER_ENTERING_WORLD") 
WatchEvent:SetScript("OnEvent", function()
	WatchFrame:ClearAllPoints()
	WatchFrame:SetHeight(600)
	if MBar3:IsVisible() and not MBar4:IsVisible() then
		WatchFrame:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 80, -20)
	elseif MBar4:IsVisible() then
		WatchFrame:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 40, -20)
	else
		WatchFrame:SetPoint("TOPRIGHT", "Minimap", "BOTTOMLEFT", 120, -20)
	end
end)
Inside an addon it does not work either. HOWEVER it does work only when I use your code and that code together! I have no idea why though. I got what I want but need to use both of them together, one inside the Onload script in KgPanels and the other in an addon..

Very Confusing!
  Reply With Quote
07-30-13, 03:38 PM   #18
Rainrider
A Firelord
AddOn Author - Click to view addons
Join Date: Nov 2008
Posts: 454
I actually tested my script in-game and it works (apart from that MBar stuff, because I can't test this). You probably have some action bars addon that creates the bars, whose visibility you check. If you use an addon for this and not kgPanels, you can just add WatchFrame:SetMovable(true) and WatchFrame:SetUserPlaced(true) in your code and it should work without the kgPanels OnLoad script.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Move the Watch Frame onLoad?


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off