Thread Tools Display Modes
03-02-14, 08:50 AM   #1
MoonWitch
A Firelord
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 455
font size

Hello,

Me again :P

Phanx, I think this one is ideal for you :P

For a friend of mine, I'm writing a "clock" add-on. He's had one for many years, recently picked up played but can't find it. So he described it and I am trying to recreate it.
I am stumped on 2 things:
- FontSize. Wow doesn't take anything over 32; this seems to be a client limitation? Anyone know a way around?
- UI Interface Options ... This is simply driving me mad, completely bonkers. I finally got checkboxes and buttons working, now I need to add a slider, drop down and colorpicker. Might I add : They show up, but do NOT function. That's the part where I fall into an abyss of doom. How do I get that checkbox going?
"OnValueChanged" seemed logical, turns out that that's only for sliders then?

I've looked at Phanx' add ons, Tekkubs, zorks, p3lims... But everyone does it differently, and it's just not making sense.
__________________
  Reply With Quote
03-02-14, 01:40 PM   #2
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
To get anything larger than 32 for your fonts, you need to either a) find a larger font, or b) use textures instead of a font.

To get a checkbox working... In the OnClick script:
Lua Code:
  1. savedvars.myVar = true
  2. checkbox:SetHandler("OnClick", function(self,btn)
  3.           savedvars.myVar = not savedvars.myVar
  4.           self:SetChecked(savedvars.myVar)
  5.           -- do stuff here
  6.      end)

Read here for dropdowns if you haven't already: http://forums.wowace.com/showthread.php?t=15763

For a slider, use a template to actually create it - this should be easiest. Set your min/max values using slider:SetMinMaxValues(min, max) and then in the OnValueChanged handler do whatever you need to do with that value.
__________________
"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
03-02-14, 10:42 PM   #3
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by MoonWitch View Post
- FontSize. Wow doesn't take anything over 32; this seems to be a client limitation? Anyone know a way around?
Yes, it is a client limitation. The actual maximum size is more like 36, but it really depends on the individual font file. It makes more sense if you think of each character in the font as being contained in a box, and a word as a string of boxes all lined up next to each other. When you set the font string to 36px, it makes the boxes 36px tall, not the letters. In some fonts, the letter takes up most of the box, while in others it takes up less (maybe to leave room for diacritics, for example, or longer ascenders and decenders for a fancier appearance), making the font seem smaller.

As Seerah said, you can look for a "bigger" font (one where the letters take up more of the box) or you can make an image of each number/letter/whatever you want to use at the desired size in Photoshop, and then use the images in-game instead of actual text. To actually implement that, you'd need to first make the string, and then iterate over each character and map it to an image texture:

Lua Code:
  1. -- Remap some characters that can't be used in file paths:
  2. local filenames = {
  3.     [":"] = "colon",
  4.     [","] = "comma",
  5.     ["."] = "period",
  6.     [" "] = "space",
  7. }
  8.  
  9. -- Here's your string:
  10. local text = "7:52 PM"
  11.  
  12. -- Identify each individual character in the string:
  13. for i = 1, strlen(text) do
  14.     local char = strsub(text, i, i)
  15.     -- Map it to a texture file path:
  16.     local path = "Interface\\AddOns\\MyAddon\\textures\\" .. (filenames[char] or char)
  17.     -- And set it to a texture object:
  18.     myTextures[i]:SetTexture(path)
  19. end

Originally Posted by MoonWitch View Post
- UI Interface Options ... This is simply driving me mad, completely bonkers. I finally got checkboxes and buttons working, now I need to add a slider, drop down and colorpicker. Might I add : They show up, but do NOT function. That's the part where I fall into an abyss of doom. How do I get that checkbox going?
"OnValueChanged" seemed logical, turns out that that's only for sliders then?
Sliders have OnValueChanged. Buttons, checkboxes, and colorpickers have OnClick. See also the widget script handlers listing on wowprogramming.

Color pickers are slightly more annoying. Here's a "native" color picker based on the ones in the chat config frame:
Lua Code:
  1. local picker = CreateFrame("Button", nil, UIParent) -- change this to your own frame!
  2. picker:SetSize(16, 16)
  3. picker:SetHitRectInsets(0, -145, 0, 0)
  4.  
  5. local bg = picker:CreateTexture(nil, "BACKGROUND")
  6. bg:SetSize(14, 14)
  7. bg:SetPoint("CENTER")
  8. bg:SetTexture(1, 1, 1)
  9. picker.bg = bg
  10.  
  11. picker:SetNormalTexture("Interface\\ChatFrame\\ChatFrameColorSwatch")
  12. picker.swatch = picker:GetNormalTexture()
  13.  
  14. local text = picker:CreateFontString(nil, "ARTWORK", "GameFontHighlight")
  15. text:SetPoint("LEFT", picker, "RIGHT", 2, 0)
  16. picker:SetFontString(text) -- so you can do picker:SetText(...)
  17. picker.text = text
  18.  
  19. picker:SetPoint("LEFT", UIParent, "CENTER") -- Set your own point!
  20. picker.swatch:SetVertexColor(1, 1, 0) -- and color!
  21. picker:SetText("Pick a color!") -- and text!
  22.  
  23. picker.swatchFunc = function()
  24.     -- Called when the color changes or the user clicks Okay
  25.     -- Used to apply the new color
  26.     -- Does not receive a self!
  27.     -- If you want to limit it to run only when clicking Okay, and not
  28.     -- potentially hundreds of times per second while the color is being
  29.     -- changed, uncomment this next line:
  30.     -- if ColorPickerFrame:IsShown() then return end
  31.     local r, g, b = ColorPickerFrame:GetColorRGB()
  32.     picker:GetNormalTexture():SetVertexColor(r, g, b)
  33.     -- set your DB values and change any displayed things here
  34. end
  35.  
  36. picker.cancelFunc = function(r, g, b)
  37.     -- Called when the user clicks Cancel
  38.     -- Used to revert to the previous color
  39.     -- Does not receive a self!
  40.     -- r, g, b are the values you set in the OnClick script below
  41.     picker.swatch:SetVertexColor(r, g, b)
  42.     -- set your DB values and change any displayed things here
  43. end
  44.  
  45. picker:SetScript("OnClick", function(self)
  46.     -- Set the current values to revert to in case of cancellation:
  47.     self.r, self.g, self.b = 1, 1, 0 -- pull from your DB
  48.     -- Open the color picker:
  49.     OpenColorPicker(self)
  50. end)

Other than that, you should know better, but... show your code!
__________________
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
03-03-14, 01:35 PM   #4
MoonWitch
A Firelord
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 455
Originally Posted by Phanx View Post
Other than that, you should know better, but... show your code!
I know better, but shame prevents me from doing that I kinda fear someone (not you though) might mock me for life.

It's the simplest of add ons, and writing it was a breeze... It's the options that's causing me the grief (and the savedvars). It's been a long time since I did this, and having never dabbled with UI Options like this... I felt utterly lost. I read so much, looked through so much code, I literally felt overwhelmed and well - lost.

Also : https://github.com/moonwitch-wow/BobTheClock
__________________
  Reply With Quote
03-03-14, 03:11 PM   #5
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by MoonWitch View Post
I know better, but shame prevents me from doing that I kinda fear someone (not you though) might mock me for life.
I will mock you for life for not showing it.

Originally Posted by MoonWitch View Post
A couple quick notes before the important parts:

(1) While it's true that Blizzard designed the options panel API so that the "cancel" function is supposed to revert all changes made since the panel was opened... addons generally do not do this, since pressing Esc triggers the "cancel" function instead of the "okay" function and it's just confusing for users to close the window and lose all their changes. Just apply settings changes immediately, and don't set "okay" or "cancel" functions.

(2) The "defaults" function is likewise pretty useless; almost no addon implements it, and I'm not sure any user has ever pressed that button with the intention of resetting every single UI and addon setting. If it only applied to the current panel, that would be more useful, but that's not the case.

(3) Your current "cancel" function references a "temporary" table that's not defined anywhere. Fortunately this is not a real issue since you should just get rid of that whole function.

(4) Your widget API is fine, but you should use a consistent naming pattern. Either use "CreateX" or "AddX" but don't mix them; that's just confusing!

(6) Your "AddCheckbox" method is receiving a "parent" as its first (named) argument. However, none of the other widget constructor methods receive this argument, and since it's a method, it already gets the "self" argument, which in your use-case is the same as what you're passing as "parent", so you don't need to explicitly pass that.

(7) Most Blizzard frame templates require global names. You (probably) won't get errors from most of them, but you will end up with some weird overlapping global names for their regions and children. The name doesn't actually matter, so you can just randomize it.

(8) The UICheckButtonTemplate template already includes a fontstring, so you don't need to create one yourself. Also, I'd use the InterfaceOptionsCheckButtonTemplate template instead, since it also includes predefinted tooltip behavior for additional description text.

(9) Since you're going the API route for widgets, I'd go a little further and do something like this in the constructor function:

Lua Code:
  1. function Panel:CreateCheckbox(text, tooltipText)
  2.     -- Use random name. Template includes a fontstring and tooltip behavior.
  3.     local checkButton = CreateFrame("Button", "BobCheckbox" .. random(1000000), self, "InterfaceOptionsCheckButtonTemplate")
  4.     -- Override the default OnClick script since it includes unwanted Blizz-specific behaviors.
  5.     checkButton:SetScript("OnClick", function(self)
  6.         local checked = not not self:GetChecked() -- convert 1/nil to true/false
  7.         PlaySound(checked and "igMainMenuOptionCheckBoxOn" or "igMainMenuOptionCheckBoxOff")
  8.         if self.func then
  9.             self:func(checked)
  10.         end
  11.     end)
  12.     -- Customize it
  13.     checkButton.text:SetText(text)
  14.     checkButton.tooltipText = tooltipText
  15.     -- Return it
  16.     return checkButton
  17. end

This way your constructor doesn't need to know anything about which setting the checkbox is changing, or how to apply that setting to your addon. You can do that separately for each individual checkbox:

Lua Code:
  1. local timeFormat = self:CreateCheckbox("Use 24-hour time format", "Give a longer description of the option here if you want, or remove this argument.")
  2. -- set a poitn here
  3. timeFormat.func = function(self, value)
  4.     BobTheClockDB.timeform24 = value
  5.     -- apply the setting to your UI
  6. end
__________________
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.

Last edited by Phanx : 03-03-14 at 03:29 PM.
  Reply With Quote
03-03-14, 03:28 PM   #6
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Here's a fixed version of your slider constructor that uses a single instance of each script function instead of creating a new one for each slider, and works around the Blizzard bug that ignores the step value while dragging the slider.

Lua Code:
  1. do
  2.     local function Slider_OnMouseWheel(self, delta)
  3.         local step = self:GetValueStep() * delta
  4.         local minValue, maxValue = self:GetMinMaxValues()
  5.         if step > 0 then
  6.             self:SetValue(min(self:GetValue() + step, maxValue))
  7.         else
  8.             self:SetValue(max(self:GetValue() + step, minValue))
  9.         end
  10.     end
  11.  
  12.     local function Slider_OnValueChanged(self)
  13.         local value = self:GetValue()
  14.  
  15.         -- Work around for Blizzard bug that ignores the step value while dragging:
  16.         local valueStep, minValue = self:GetValueStep(), self:GetMinMaxValues()
  17.         if valueStep and valueStep > 0 then
  18.             value = floor((value - minValue) / valueStep + 0.5) * valueStep + minValue
  19.         end
  20.  
  21.         self.value:SetText(value)
  22.  
  23.         if self.func then
  24.             self:func(value)
  25.         end
  26.     end
  27.  
  28.     function Panel:CreateSlider(text, tooltipText, minValue, maxValue, stepValue)
  29.         local slider = CreateFrame("Slider", "BobSlider" .. random(1000000), self, "OptionsSliderTemplate")
  30.         slider.text = _G[slider:GetName() .. "Text"]
  31.         slider.lowText = _G[slider:GetName() .. "Low"]
  32.         slider.highText = _G[slider:GetName() .. "High"]
  33.  
  34.         slider:EnableMouseWheel(true)
  35.         slider:SetScript("OnMouseWheel", Slider_OnMouseWheel)
  36.         slider:SetScript("OnValueChanged", Slider_OnValueChanged)
  37.  
  38.         local value = slider:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
  39.         value:SetPoint("LEFT", slider, "RIGHT", 7, 0)
  40.         slider.value = value
  41.  
  42.         slider.lowText:Hide()
  43.         slider.highText:Hide()
  44.  
  45.         slider.text:SetText(text)
  46.         slider.tooltipText = tooltipText
  47.         slider:SetMinMaxValues(minValue or 0, maxValue or 100)
  48.         slider:SetStepValue(stepValue or 1)
  49.  
  50.         return slider
  51.     end
  52. end

Same thing as the checkbox constructor in my last post; just set a "func" property on the slider to tell it what to do when the value changes:

Lua Code:
  1. local clocksizeSlider = self:CreateSlider("Clock size", "Adjust the size of the clock text.", 8, 32, 1)
  2. -- set a point here
  3. clocksizeSlider.func = function(self, value)
  4.     BobTheClockDB.clocksize = value
  5.     -- apply the new value to your display fontstring(s)
  6. end

Edit: Writing these makes me realize I need to clean up my config widget mini-libs.
__________________
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.

Last edited by Phanx : 03-03-14 at 04:32 PM.
  Reply With Quote
03-03-14, 03:34 PM   #7
MoonWitch
A Firelord
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 455
Originally Posted by Phanx View Post

Edit: Writing these makes me realize I need to clean up my config widget mini-libs.
Sweet sweet Phanx... You made me cry there... And I did look at your code, I just couldn't get my head around them. I was so hoping to figure this out myself, write a mini-lib for it, so I don't have to go through this emotional state again (yes, emo. I am VERY bad with forgiving myself for not understanding something, you don't want know how my arms currently look.)
__________________
  Reply With Quote
03-03-14, 03:59 PM   #8
MoonWitch
A Firelord
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 455
Checkboxes working, though the initial load (whether the checkbox is true or not doesn't seem to work.)

Thanks Phanx.

__________________

Last edited by MoonWitch : 03-03-14 at 04:22 PM.
  Reply With Quote
03-03-14, 04:33 PM   #9
Seerah
Fishing Trainer
 
Seerah's Avatar
WoWInterface Super Mod
Featured
Join Date: Oct 2006
Posts: 10,860
Are you checking your sv's and setting the checked state upon creation of the checkbox?
__________________
"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
03-03-14, 04:34 PM   #10
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Cat.

Originally Posted by MoonWitch View Post
Checkboxes working, though the initial load (whether the checkbox is true or not doesn't seem to work.)
Well, you need to do that part yourself after creating the checkbox:

Lua Code:
  1. timeFormat:SetChecked(BobTheClockDB.timeform24)

Actually, you may want to use a "refresh" function for your panel, and set all the values there; that will make sure the widgets are all updated with current values each time the panel is shown, in case they've somehow changed:

Lua Code:
  1. function Panel:refresh()
  2.     timeFormat:SetChecked(BobTheClockDB.timeform24)
  3.     -- etc
  4. end

Also, I adjusted the slider stuff in my last post, as I realized I'd misunderstood what you were creating the fontstring for.

Originally Posted by MoonWitch View Post
I am VERY bad with forgiving myself for not understanding something, you don't want know how my arms currently look.
Hör auf damit!
__________________
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.

Last edited by Phanx : 03-03-14 at 04:39 PM.
  Reply With Quote
03-03-14, 04:45 PM   #11
MoonWitch
A Firelord
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 455
I do have a question though.

How do you know eg slider.Text etc... I can't find which sub widgets exist per template (Hell, can't even find the templates on frameXML)

SV's now fine. It's becoming this raging huge file. I may end up with separating the creation funcs into their own file
__________________

Last edited by MoonWitch : 03-03-14 at 05:09 PM.
  Reply With Quote
03-03-14, 06:44 PM   #12
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
The templates are scattered across a number of files.

Checkbox
http://www.townlong-yak.com/framexml...sPanels.xml#19

Slider
http://www.townlong-yak.com/framexml...mplates.xml#76

Dropdown
http://www.townlong-yak.com/framexml...uTemplates.xml
Tutorial here: http://forums.wowace.com/showthread.php?t=15763

EditBox
http://www.townlong-yak.com/framexml...plates.xml#645

Lua Code:
  1. local box = CreateFrame("EditBox", "MyEditBox", parent, "InputBoxTemplate")
  2. -- set points
  3. -- add a label text if you want one
  4. box:SetAltArrowKeyMode(false) -- annoying
  5. box:SetAutoFocus(false) -- annoying
  6. box:SetScript("OnEnterPressed", function(self)
  7.     local text = self:GetText()
  8.     -- do your thing here
  9. end)

Button
http://www.townlong-yak.com/framexml...plates.xml#301

Lua Code:
  1. local button = CreateFrame("Button", "MyButton", parent, "UIPanelButtonTemplate")
  2. -- set points
  3. button:SetText(OKAY)
  4. button:SetScript("OnClick", function()
  5.     PlaySound("UChatScrollButton")
  6.     -- do your thing here
  7. end)

There isn't a good template for color pickers, so just use the one I posted earlier.

Edit:
Also remembered Zork posted some info/examples for these templates here:
http://www.wowinterface.com/forums/s...ad.php?t=40444
__________________
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.

Last edited by Phanx : 03-03-14 at 06:46 PM.
  Reply With Quote

WoWInterface » AddOns, Compilations, Macros » AddOn Help/Support » font size


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