Thread Tools Display Modes
03/29/15, 05:19 PM   #1
lightz39
AddOn Author - Click to view addons
Join Date: Mar 2015
Posts: 21
Dynamic Anchors?

Hey everyone, I am currently trying to figure anchors out. I was wondering if its possible to dynamically anchor one item to the next.

I can anchor two things beside each other but the issue is if one changes size (example a clock ranging from 12:00 to 1:00 shrinks) there becomes a larger gap than wanted. Is it possible to always maintain a certain padding no matter what size the string is?
  Reply With Quote
03/29/15, 05:38 PM   #2
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
Originally Posted by lightz39 View Post
Hey everyone, I am currently trying to figure anchors out. I was wondering if its possible to dynamically anchor one item to the next.

I can anchor two things beside each other but the issue is if one changes size (example a clock ranging from 12:00 to 1:00 shrinks) there becomes a larger gap than wanted. Is it possible to always maintain a certain padding no matter what size the string is?
Maybe I missunderstand, but it already does what "I think" your asking. In fact that is the entire point of anchoring controls together.
If one control changes position, size, exc...the controls still stay anchored to each other, at the same point, the gap would not change. The other control just follows it staying attached at the same point.


It sounds more to me like your not resizing the control when the "text" shrinks from 12:00 to 1:00. The control is still exactly the same size, but the text is smaller. So the gap that you see is actually between the text & the other control...its not really between the two controls, that gap would not change (if they were anchored together).

Like in the example picture above, in the bottom picture the words: "Control A" and "Control B" are closer together, the gap between them has shrunk...but the gap (or lack of a gap) between the two controls has not changed at all. They are still connected by their TOPLEFT/BOTTOMRIGHT corners. There is still no gap between the controls, they are still touching.

Last edited by circonian : 03/29/15 at 05:43 PM.
  Reply With Quote
03/29/15, 05:51 PM   #3
lightz39
AddOn Author - Click to view addons
Join Date: Mar 2015
Posts: 21
Ok so my problem is definitely the controls size not shrinking with the string. Is there a way to dynamically do that?

Something like

X = GetStringWidth()
X = X
  Reply With Quote
03/29/15, 06:37 PM   #4
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
Well its kind of hard to say without knowing exactly what your doing & what all controls are involved, but this will give you a start & some ideas. Do keep in mind if there are other controls involved or anchored to/around these controls it could cause other problems changing the sizes of these controls.
Lua Code:
  1. -- labelControl -- the control that holds the clock text 12:00
  2.  
  3. local textWidth = labelControl:GetTextWidth()
  4. labelControl:SetWidth(textWidth+somePadding)
I put + somePadding, which may not be necessary...again to many unknown factors, but for example in a clock that I wrote due to the font & size I choose for my clock the TextWidth alone was not large enough and the text touched the clock border. You may or may not need padding.

Do note, there are several unknown factors here. For example if the lableControl is inside of other controls, resizing the labelControl alone would not (probably not) solve the problem. Because its parent or top level control would still remain the same size...and so anything anchored to its parent or top level control would still "appear" to be farther away or closer (look like the gaps size is changing).

I could make a better suggestion if you post some of the code for the controls your talking about so i can see how they are laid out.
  Reply With Quote
03/29/15, 06:57 PM   #5
lightz39
AddOn Author - Click to view addons
Join Date: Mar 2015
Posts: 21
Sure thanks for the help I do appreciate it.

Here is my XML:

XML Code:
  1. <GuiXml>
  2.     <Controls>
  3.         <TopLevelControl name="NM_SystemBarWin" movable="true" mouseEnabled="true" clampedToScreen="true" hidden="false">
  4.             <Dimensions x="350" y="68"/>
  5.             <ClampedToScreenInsets top="20" bottom="-20" left="20" right="-20"/>
  6.             <Anchor point="TOPLEFT"/>
  7.             <Controls>
  8.                 <Backdrop name="$(parent)Backdrop" integralWrapping="true">
  9.                     <Anchor point="TOPLEFT"/>
  10.                     <Anchor point="BOTTOMRIGHT"/>
  11.                     <Edge file="EsoUI/Art/ChatWindow/chat_BG_edge.dds" edgeFileWidth="256" edgeFileHeight="256" edgeSize="32"/>
  12.                     <Center file="EsoUI/Art/ChatWindow/chat_BG_center.dds"/>
  13.                     <Insets top="32" bottom="-32" left="32" right="-32"/>
  14.                 </Backdrop>
  15.                 <Control name="$(parent)Clock" mouseEnabled="true">
  16.                     <Dimensions x="80" y="40"/>
  17.                     <Anchor point="RIGHT" relativeTo="$(parent)" relativePoint="CENTER" offsetX="-60"/>
  18.                     <Controls>
  19.                         <Label name="$(parent)Label" font="ZoFontWinT2" horizontalAlignment="CENTER" verticalAlignment="CENTER">
  20.                             <AnchorFill/>
  21.                         </Label>
  22.                     </Controls>
  23.                     <OnMouseDown>
  24.                         self:GetParent():StartMoving()
  25.                     </OnMouseDown>
  26.                     <OnMouseUp>
  27.                         self:GetParent():StopMovingOrResizing()
  28.                     </OnMouseUp>
  29.                 </Control>
  30.                 <Control name="$(parent)Fps" mouseEnabled="true">
  31.                     <Dimensions x="80" y="40"/>
  32.                     <Anchor point="LEFT" relativeTo="$(parent)Clock" relativePoint="RIGHT" offsetX="-5"/>
  33.                     <Controls>
  34.                         <Label name="$(parent)Label" font="ZoFontWinT2" color="c5c29e" horizontalAlignment="CENTER" verticalAlignment="CENTER">
  35.                             <AnchorFill/>
  36.                         </Label>
  37.                     </Controls>
  38.                     <OnMouseDown>
  39.                         self:GetParent():StartMoving()
  40.                     </OnMouseDown>
  41.                     <OnMouseUp>
  42.                         self:GetParent():StopMovingOrResizing()
  43.                     </OnMouseUp>
  44.                 </Control>
  45.                 <Control name="$(parent)Latency" mouseEnabled="true">
  46.                     <Dimensions x="80" y="40"/>
  47.                     <Anchor point="LEFT" relativeTo="$(parent)Fps" relativePoint="RIGHT"/>
  48.                     <Controls>
  49.                         <Texture name="$(parent)Icon" textureFile="EsoUI/Art/Campaign/campaignbrowser_hipop.dds">
  50.                             <Dimensions x="26" y="26"/>
  51.                             <Anchor point="LEFT" relativeTo="$(parent)" relativePoint="LEFT"/>
  52.                         </Texture>
  53.                         <Label name="$(parent)Label" font="ZoFontWinT2" horizontalAlignment="LEFT" verticalAlignment="CENTER">
  54.                             <Anchor point="LEFT" relativeTo="$(parent)Icon" relativePoint="RIGHT"/>
  55.                         </Label>
  56.                     </Controls>
  57.                     <OnMouseDown>
  58.                         self:GetParent():StartMoving()
  59.                     </OnMouseDown>
  60.                     <OnMouseUp>
  61.                         self:GetParent():StopMovingOrResizing()
  62.                     </OnMouseUp>
  63.                 </Control>
  64.                 <Control name="$(parent)Gold" mouseEnabled="true">
  65.                     <Dimensions x="80" y="40"/>
  66.                     <Anchor point="LEFT" relativeTo="$(parent)Latency" relativePoint="RIGHT" offsetX="-34"/>
  67.                     <Controls>
  68.                         <Label name="$(parent)Label" font="ZoFontWinT2" horizontalAlignment="CENTER" verticalAlignment="CENTER">
  69.                             <AnchorFill/>
  70.                         </Label>
  71.                         <Texture name="$(parent)Icon" textureFile="/EsoUI/Art/Currency/currency_gold.dds">
  72.                             <Dimensions x="16" y="16"/>
  73.                             <Anchor point="LEFT" relativeTo="$(parent)Label" relativePoint="RIGHT" offsetX="-20"/>
  74.                         </Texture>
  75.                     </Controls>
  76.                     <OnMouseDown>
  77.                         self:GetParent():StartMoving()
  78.                     </OnMouseDown>
  79.                     <OnMouseUp>
  80.                         self:GetParent():StopMovingOrResizing()
  81.                     </OnMouseUp>
  82.                 </Control>
  83.             </Controls>
  84.             <OnMoveStop>
  85.                 NM_SystemBar.OnMoveStop()
  86.             </OnMoveStop>
  87.         </TopLevelControl>
  88.     </Controls>
  89. </GuiXml>

Anchors are still a bit of an issue for me. Maybe I'm just not wrapping my head around it.



Here is what I currently have. Basically what I'm going for is all the "modules" to be evenly spaced at all times no matter the situation.
  Reply With Quote
03/29/15, 08:31 PM   #6
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
It looks like you need something like this:

Whenever you update the clock, you could adjust the width of the control:
Lua Code:
  1. -- Grab the text width of the clock label & set the clock controls width with it
  2. -- (since the label autofills to the size of the clock, your also adjusting the
  3. -- size of the label control at the same time)
  4. local clockWidth = NM_SystemBarWinClockLabel:GetTextWidth()
  5. NM_SystemBarWinClock:SetWidth(clockWidth)


Whenever you update the fps, you could adjust the width of the control:
Lua Code:
  1. -- Grab the text width of the fps label & set the fps controls width with it
  2. -- (since the label autofills to the size of the fps control, your also adjusting
  3. -- the size of the label control at the same time)
  4. local fpsWidth = NM_SystemBarWinFpsLabel:GetTextWidth()
  5. NM_SystemBarWinFps:SetWidth(fpsWidth)

Whenever you update the latency, you could adjust the width of the control:
Lua Code:
  1. -- Grab the text width of the latency label & set the latency controls width with it,
  2. -- But you also have to include the width of the icon, since the latency control includes
  3. -- the latency icon and the latency label.
  4. -- In this one since the latency label does NOT autofill to the size of the latency
  5. -- control, so we should also update the latency labels width.
  6. local latencyWidth = NM_SystemBarWinLatencyLabel:GetTextWidth()
  7. NM_SystemBarWinLatencyLabel:SetWidth(latencyWidth)
  8. NM_SystemBarWinLatency:SetWidth(latencyWidth+latencyIconWidth)
Whenever you update the gold amount, you could adjust the width of the control:
Lua Code:
  1. -- Grab the text width of the gold label & set the gold controls width with it,
  2. -- But you also have to include the width of the gold icon, since the gold control includes
  3. -- the gold icon and the gold label.
  4. -- In this one since the gold label does NOT autofill to the size of the gold
  5. -- control, so we should also update the gold labels width.
  6. local goldWidth = NM_SystemBarWinGoldLabel:GetTextWidth()
  7. NM_SystemBarWinGoldLabel:SetWidth(goldWidth)
  8. NM_SystemBarWinGold:SetWidth(goldWidth+goldIconWidth)

Do note that since were resizing the controls to the exact width of the text, this means they wont have any space in between each of the controls. You will probably need to add some padding in between them somehow. We could do it by adding padding to the width of the control (like I wrote in my last reply), but then the labels would not be centered inside of its parent control and we would have to mess with the xml anchors offsetX to center it.

So instead I would just handle the padding in the xml acnhors using offsetX.
Before you had some negative values for your offsetX, but that was because you were keeping a static width for the controls (which was probably to big) so you were using a negative offsetX to overlap the controls to remove some of that gap. Since were resizing our controls to the exact size of its contents that would cause the icons/text to overlap. We need positive values now, probably somewhere between 10-20 for the offsetX value would be my guess.
xml Code:
  1. <Control name="$(parent)Fps" mouseEnabled="true">
  2.     <Dimensions x="80" y="40"/>
  3.     -- Add an offsetX value to create space in between the controls
  4.     <Anchor point="LEFT" relativeTo="$(parent)Clock" relativePoint="RIGHT" offsetX="10"/>
  5. ...
  6.  
  7.  
  8. <Control name="$(parent)Latency" mouseEnabled="true">
  9.     <Dimensions x="80" y="40"/>
  10.     -- Add an offsetX value to create space in between the controls
  11.     <Anchor point="LEFT" relativeTo="$(parent)Fps" relativePoint="RIGHT" offsetX="10"/>
  12. ...
  13.  
  14. <Control name="$(parent)Gold" mouseEnabled="true">
  15.     <Dimensions x="80" y="40"/>
  16.     -- Add an offsetX value to create space in between the controls
  17.     <Anchor point="LEFT" relativeTo="$(parent)Latency" relativePoint="RIGHT" offsetX="10"/>
  18. ...

Lastly....although I said I would handle the padding (space for in between the controls) in the anchors offsetX. From writing my own clock I know that there are some other factors that can affect the width of the text, like the font. I "don't think" that GetTextWidth() takes that into account when calculating the width, because when I wrote my clock, with adjustable fonts/sizes, I had to actually vary the size of the control by adding padding based on what font/sizes I was using. The point is, you may still have to add a small amount of padding to those control widths, but it shouldn't take very much.

Last edited by circonian : 03/29/15 at 08:41 PM.
  Reply With Quote
03/29/15, 08:40 PM   #7
Sasky
AddOn Author - Click to view addons
Join Date: Apr 2014
Posts: 231
Also, you should be able to put the resize functions inside the top level control instead of each sub control.
  Reply With Quote
03/29/15, 08:51 PM   #8
lightz39
AddOn Author - Click to view addons
Join Date: Mar 2015
Posts: 21
Thanks a lot circonian. That's a big help. My goal with this addon is to learn so when you take the time to explain it helps greatly.
  Reply With Quote
03/30/15, 05:20 PM   #9
lightz39
AddOn Author - Click to view addons
Join Date: Mar 2015
Posts: 21
Worked wonderfully. I have another quick question though. I want to have it so I set the backdrop size based on the size of all the modules added up. When I try this it returns them as nil. This is because I set them as local functions. How does this work? Do I have to redefine them in another function, make them not local or am I just ordering things incorrectly?

EDIT: Just a thought is it because I'm defining the local variables inside of local functions?

Last edited by lightz39 : 03/30/15 at 05:46 PM.
  Reply With Quote
03/30/15, 05:53 PM   #10
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,912
Local variables inside local functions are only known to this function!
If you want to have the value of some variable inside your addon you need to define it local in your addon, outside functions.
Otherwise you need to define it global inside or outside a function, and it will be known outside your addon as well then.

To change the backdrop size you'll need to react on "when a module is added/removed":
-Your backdrop control got a name so use it with WINDOW_MANAGER:GetControlByName("your backdrop's name", "")
-Store this in a vraible like myBackdrop
-use myBackdrop:SetWidth(myNewWidth)
myNewWidth should be changed by the width of all the modules you have added
  Reply With Quote
03/30/15, 05:58 PM   #11
lightz39
AddOn Author - Click to view addons
Join Date: Mar 2015
Posts: 21
Ok I had a hunch that was the issue. Thank you. Question about that Get control name you have "" for the suffix. What exactly is that?
  Reply With Quote
03/30/15, 08:07 PM   #12
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,912
This is a good question I've never used it so far. Maybe it is for controls where the start is always the same and the suffix is the name of a child.
Like the first part is the parent and the suffic is the child.

The way that :GetChildByName("sChild") is working for a control where let's say the parent name is "ThisIsAParent" and a childs name is "ThisIsAParentsChild"

But I'm not sure, this is only a guess
  Reply With Quote
03/30/15, 09:29 PM   #13
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
Originally Posted by lightz39 View Post
Ok I had a hunch that was the issue. Thank you. Question about that Get control name you have "" for the suffix. What exactly is that?
Lua Code:
  1. WINDOW_MANAGER:GetControlByName(name, suffix)
It is for the suffix name of the control.

If you needed to get the child of a child of a parent control....
Lets use this as an example, I want to get the control: ZO_PlayerInventoryTabsButton6
"ZO_PlayerInventoryTabs" is a child control of ZO_PlayerInventory
and
"ZO_PlayerInventoryTabsButton6" is a child control of ZO_PlayerInventoryTabs
You could do something like:
Lua Code:
  1. local tabControl = ZO_PlayerInventory:GetNamedChild("Tabs")
  2. local btn6Control = tabControl:GetNamedChild("Button6")
  3. or
  4. local btn6Control = ZO_PlayerInventory:GetNamedChild("Tabs"):GetNamedChild("Button6")

But instead of making the intermediate call to get: ZO_PlayerInventoryTabs control...even though you don't care about it & are only going to use it to grab the: ZO_PlayerInventoryTabsButton6 control. Instead you can just use:
Lua Code:
  1. WINDOW_MANAGER:GetControlByName("ZO_PlayerInventory", "TabsButton6")
and skip over grabbing the ZO_PlayerInventoryTabs control since you don't need it anyhow.


Note: The control your trying to get doesn't have to be the Child of a child of the parent...it was just a decent example of use for the function. You could grab a parents child by doing:
Lua Code:
  1. WINDOW_MANAGER:GetControlByName("ZO_PlayerInventory", "Tabs")

But since "Tabs" is a child of ZO_PlayerInventory, we could also just call:
Lua Code:
  1. local tabControl = ZO_PlayerInventory:GetNamedChild("Tabs")

Last edited by circonian : 03/30/15 at 09:37 PM.
  Reply With Quote
03/31/15, 01:57 AM   #14
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,912
Thanks for the explanation circonian. Again I've learned something :-) (And I wasn#t that wrong with my guess above )
  Reply With Quote
03/31/15, 06:07 AM   #15
lightz39
AddOn Author - Click to view addons
Join Date: Mar 2015
Posts: 21
Thanks again as always very helpful.
  Reply With Quote

ESOUI » Developer Discussions » Lua/XML Help » Dynamic Anchors?

Thread Tools
Display Modes

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