Thread Tools Display Modes
08/16/14, 06:29 AM   #1
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
Set Width to Text Length

What I'm trying to do:
I'm creating a variable sized window, with a variable amount of buttons inside of it, which have text of varied lengths. I was just curious if there is an easy way to get the width of the text inside of a button. So that if the width of the text changes, due to font/size changes the button text changes, I can reset the width of ALL of the buttons.

Right now I'm just grabbing the string length of every buttons text & 'roughly estimating' the width needed for the buttons, but it seemed like there should be an easier way for something like this.

If it helps, this is what I'm doing:
Lua Code:
  1. -- Create the parent window --
  2. local function CreateQuickClickWindow()
  3.     if not Click4Info.QuickClickWindow then
  4.         Click4Info.QuickClickWindow = WINDOW_MANAGER:CreateTopLevelWindow("Click4InfoQuickClickWindow")
  5.         local qcWin = Click4Info.QuickClickWindow
  6.         qcWin:SetDimensions(windowWidth, ((#QuickClickCommands+1) * Click4Info.QuickClickButtonHeight))
  7.         qcWin:ClearAnchors()
  8.         qcWin:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, Click4Info.QuickClickOffsetX, Click4Info.QuickClickOffsetY)
  9.         qcWin:SetHidden(false)    
  10.         qcWin:SetMovable(true)
  11.         qcWin:SetMouseEnabled(true)
  12.         qcWin:SetClampedToScreen(true)    
  13.  
  14.         qcWinBG = WINDOW_MANAGER:CreateControlFromVirtual("Click4InfoQuickClickWindowBG", qcWin, "ZO_DefaultBackdrop")
  15.         qcWinBG:ClearAnchors()
  16.         qcWinBG:SetAnchorFill(qcWin)
  17.     end
  18. end

and create buttons like this:
Lua Code:
  1. -- Create the Buttons --
  2. local function CreateQuickClickButtons()
  3.     for i = 1, #QuickClickCommands do
  4.         local button = CreateControlFromVirtual("Click4InfoQuickClickButton", Click4Info.QuickClickWindow, "ZO_BladeHeader", i)
  5.         button:SetHidden(false)    
  6.         button:ClearAnchors()
  7.         button:SetDimensions(windowWidth, Click4Info.QuickClickButtonHeight)
  8.         button:SetAnchor(TOPLEFT, Click4Info.QuickClickWindow, TOPLEFT, 0, Click4Info.QuickClickButtonHeight * (i-1))
  9.         button:SetText("    "..QuickClickCommands[i])
  10.         if i == 1 then
  11.             button:SetHandler("OnClicked", function() Click4Info.freeMouse = (not Click4Info.freeMouse) end)
  12.         else
  13.             button:SetHandler("OnClicked", function() QuickClickBtnClick(i) end)
  14.         end
  15.         button:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
  16.     end
  17. end

XML:
xml Code:
  1. <GuiXml>
  2.     <Controls>
  3.         <Button name="MY_BladeHeader" font="ZoFontGame" endCapWidth="22" verticalAlignment="LEFT" virtual="true">
  4.        
  5.             <Dimensions x="200" y="28"/>
  6.             <PressedOffset x="2" y="2" />
  7.  
  8.             <OnInitialized>
  9.                 ZO_ToggleButton_Initialize(self, TOGGLE_BUTTON_TYPE_BLADE)
  10.             </OnInitialized>
  11.            
  12.             <OnClicked>
  13.                 ZO_CheckButton_OnClicked(self, button)
  14.             </OnClicked>
  15.                    
  16.             <FontColors
  17.                 normalColor="INTERFACE_COLOR_TYPE_TEXT_COLORS:INTERFACE_TEXT_COLOR_NORMAL"
  18.                 pressedColor="INTERFACE_COLOR_TYPE_TEXT_COLORS:INTERFACE_TEXT_COLOR_SELECTED"
  19.                 mouseOverColor="INTERFACE_COLOR_TYPE_TEXT_COLORS:INTERFACE_TEXT_COLOR_HIGHLIGHT"
  20.                 disabledColor="INTERFACE_COLOR_TYPE_TEXT_COLORS:INTERFACE_TEXT_COLOR_DISABLED"
  21.             />
  22.         </Button>
  23.                
  24.     </Controls>
  25. </GuiXml>

Last edited by circonian : 08/16/14 at 07:50 AM.
  Reply With Quote
08/16/14, 07:28 AM   #2
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
I have not tried this, just thinking. It depends on the button template you use.

If it's a <Control> with the text as a child <Label>, you could try setting resizeToFitDescendents="true" on the parent, and resize all labels to the width of the widest.

If it's a <Button>, it should have GetDesiredWidth methods. From the name I'd expect GetDesiredWidth to give me how wide the button wants to be to fit the text, then I'd set all buttons' width to the maximum value. Or if that fails, GetLabelControl and use the first method on that.

edit: just noticed the template is <Button name="ZO_BladeHeader" ... nvm I'll go try that

Last edited by merlight : 08/16/14 at 07:30 AM.
  Reply With Quote
08/16/14, 07:51 AM   #3
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
Originally Posted by merlight View Post
I have not tried this, just thinking. It depends on the button template you use.

If it's a <Control> with the text as a child <Label>, you could try setting resizeToFitDescendents="true" on the parent, and resize all labels to the width of the widest.

If it's a <Button>, it should have GetDesiredWidth methods. From the name I'd expect GetDesiredWidth to give me how wide the button wants to be to fit the text, then I'd set all buttons' width to the maximum value. Or if that fails, GetLabelControl and use the first method on that.

edit: just noticed the template is <Button name="ZO_BladeHeader" ... nvm I'll go try that
I added the xml code above in case it helps.
I tried the desired width. Even if I take the SetDimensions out and the dimension tag from the xml it comes back with a desired width of 200 regardless of the text inside the button.

P.S.
I've seen people do posts where they had code hidden & you had to click a button to view it...how do you do that, anyone know?
  Reply With Quote
08/16/14, 08:32 AM   #4
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Originally Posted by circonian View Post
I added the xml code above in case it helps.
I tried the desired width. Even if I take the SetDimensions out and the dimension tag from the xml it comes back with a desired width of 200 regardless of the text inside the button.
Yea I've learned that now, too

Originally Posted by circonian View Post
P.S.
I've seen people do posts where they had code hidden & you had to click a button to view it...how do you do that, anyone know?
[ spoiler ]

I tried GetLabelControl:GetTextWidth(). I created two buttons under FPS window, and a "/qlick index text" slash command to change the text. They seem to resize correctly. Another option would be to anchor TOPRIGHT of each button to the previous button's BOTTOMRIGHT, and then only resize the first button.
Warning: Spoiler
  Reply With Quote
08/17/14, 06:18 AM   #5
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
Originally Posted by merlight View Post
Yea I've learned that now, too


[ spoiler ]

I tried GetLabelControl:GetTextWidth(). I created two buttons under FPS window, and a "/qlick index text" slash command to change the text. They seem to resize correctly. Another option would be to anchor TOPRIGHT of each button to the previous button's BOTTOMRIGHT, and then only resize the first button.
Warning: Spoiler
Thanks for your help. I still can't get it to work though.
I think I narrowed it down. (in the above discussion we mentioned that) We found out if we did not set a button dimension it defaulted to a width of 200...and it seems that the GetLabelControl():GetTextWidth() only works if the text actually fits in the button (so without a dimension that constrains it to a text width < 200).

I even tried copy & pasting your work, and if button text is longer than 200 it seems to not work when loading up. Even if I run the resizer manually after the game loads (through /znb) I have to run it 3-4 times before the buttons get to the proper size.

It appears that even the GetTextWidth() is limited by the button size? ...if any of that makes any sense to you.

I removed the calls on initialize & ran the create buttons after the game loaded to see what values the GetTextWidth() function was getting when the function ran, heres what the code looked like:
Warning: Spoiler


and heres the output:


Which would be why the resize isn't working when it starts up. Those are not the correct text widths. Since you added +40 to the text width in your resize function is the only reason resize worked (after 3-4 times) because it kept increasing the button width by 40 until it got to where it was supposed to be. If I remove the +40 I can run the resize over & over and the width of the buttons never change.
  Reply With Quote
08/17/14, 07:43 AM   #6
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
I added +40 as padding (using SetNormalOffsets(20, 0) I set left padding to 20; so another 20 for the right). Now I found another text width function, try this:
Lua Code:
  1. local label = button:GetLabelControl()
  2. maxWidth = math.max(maxWidth, label:GetStringWidth(label:GetText()))
  Reply With Quote
08/17/14, 04:40 PM   #7
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
Originally Posted by merlight View Post
I added +40 as padding (using SetNormalOffsets(20, 0) I set left padding to 20; so another 20 for the right). Now I found another text width function, try this:
Lua Code:
  1. local label = button:GetLabelControl()
  2. maxWidth = math.max(maxWidth, label:GetStringWidth(label:GetText()))
Nope they came out even smaller. Thats ok though, It was more of a curiousity thing I thought there was an easy/obvious way I didn't know. I just took the easy route & cheated. I resized the button to an extremely large width & then read the string length to find the maxWidth:

Lua Code:
  1. local function ResizeQuickClickButtons()  
  2.     local maxWidth = 0
  3.     for i, button in ipairs(QuickClickButtons) do
  4.  
  5. -- Make sure its big enough for the entire string --
  6.         button:SetWidth(2000)
  7.  
  8. -- and then read the textWidth --
  9.         local textWidth = button:GetLabelControl():GetTextWidth()
  10.  
  11.         maxWidth = math.max(maxWidth, textWidth)
  12.     end
  13.  
  14. -- Then resize then to the proper size --
  15.     for i, button in ipairs(QuickClickButtons) do
  16.         button:SetWidth(maxWidth+20)
  17.     end
  18. end

Thanks for your help.
  Reply With Quote
08/17/14, 05:27 PM   #8
merlight
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 671
Originally Posted by circonian View Post
Nope they came out even smaller.
No way! Really I tried that and for me c:GetStringWidth(c:GetText()) returned 307 with some long text, when c:GetTextWidth() returned 193. I added the padding and that was it.
  Reply With Quote
08/18/14, 05:47 AM   #9
circonian
AddOn Author - Click to view addons
Join Date: May 2014
Posts: 613
Originally Posted by merlight View Post
No way! Really I tried that and for me c:GetStringWidth(c:GetText()) returned 307 with some long text, when c:GetTextWidth() returned 193. I added the padding and that was it.
I'm glad you responded...and you were right. I don't know what happened last time, but I tried it again & it worked this time. Now I know how to handle it for later cases..thank you very much for the help.
  Reply With Quote

ESOUI » Developer Discussions » Lua/XML Help » Set Width to Text Length


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