Thread Tools Display Modes
02-10-13, 05:34 AM   #1
gmarco
An Onyxian Warder
 
gmarco's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 362
Help on ScrollFrame with LUA

Hi all,

I'd like to add a simple scrollframe to my addons to show a list of items (names).
The two book I have explain the scrollframe with the use of xml to build the frames.
And the web links I found usually follow this method.

I prefer if possible to avoid this approach and so I am trying to find some links, addons, code to check how this can be implemented with the plain LUA api interface.

I have tried to convert the xml approach to lua code but I didn't succeded.


Thanks very much for any inputs.
__________________
This is Unix-Land. In quiet nights, you can hear the Windows machines reboot.
  Reply With Quote
02-10-13, 03:20 PM   #2
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
Scroll frames are pretty annoying before you know their workings (well even after you know, too), but here is the simplest implementation I can come up with of a mostly working example. (you probably need to create a font string for the buttons and, of course, fill the list with something)
Code:
local NUM_BUTTONS = 8
local BUTTON_HEIGHT = 20

local list = {} -- put contents of the scroll frame here, for example item names
local buttons = {}

local function update(self)
	local numItems = #list
	FauxScrollFrame_Update(self, numItems, NUM_BUTTONS, BUTTON_HEIGHT)
	local offset = FauxScrollFrame_GetOffset(self)
	for line = 1, NUM_BUTTONS do
		local lineplusoffset = line + offset
		local button = buttons[line]
		if lineplusoffset > numItems then
			button:Hide()
		else
			button:SetText(list[lineplusoffset])
			button:Show()
		end
	end
end

local scrollFrame = CreateFrame("ScrollFrame", "MyFirstNotReallyScrollFrame", UIParent, "FauxScrollFrameTemplate")
scrollFrame:SetScript("OnVerticalScroll", function(self, offset)
	FauxScrollFrame_OnVerticalScroll(self, offset, BUTTON_HEIGHT, update)
end)

for i = 1, NUM_BUTTONS do
	local button = CreateFrame("Button", nil, scrollFrame:GetParent())
	if i == 1 then
		button:SetPoint("TOP", scrollFrame)
	else
		button:SetPoint("TOP", buttons[i - 1], "BOTTOM")
	end
	button:SetSize(96, BUTTON_HEIGHT)
	buttons[i] = button
end
This is a "faux" scroll frame, named so because it doesn't actually scroll. The scroll bar merely gives you an offset value, telling you which part of your list you should display in the "view area". It is intended to be used for simple lists, where the content is visually consistent. (such as the scroll frame where you select which battleground to queue for)

NUM_BUTTONS is the max amount of buttons/frames that will be visible at any one time in the view area, and BUTTON_HEIGHT is the height of these frames. These help deterrmine the position of the scroll bar and more.

The update function will be called everytime you actually scroll, and will reflect the new "view area". The corrent button height and the update function must always be passed to FauxScrollFrame_OnVerticalScroll in the "OnVerticalScroll" handler, as shown.

In the update function you will want to call FauxScrollFrame_Update(self, numItems, NUM_BUTTONS, BUTTON_HEIGHT) to set the scroll bar position. numItems is the total amount of items the scroll frame should represent. In your case, the number of items. You then need to get the offset, which represents the number of frames you have scrolled past. After this we can iterate over all the frame and set them up. The lineplusoffset variable here represents the effective index of your list of items. Assuming 8 buttons; when at the top of the list, offset will be 0, and so items 1 through 8 will be shown. If you scroll past 4 buttons, offset will be 4 and items 5 through 12 will be shown ((1 through 8) + 4). Frames will need to be hidden if the total amount of items is less than the number of items the frame can display at any one time. (< 8, in this case)

Make sure you don't create the subframes as children of the scroll frame itself; then they will be hidden if the size of your list does not exceed the number of items the frame can show.

Maybe this was more than you needed, but there you go. Feel free to ask for more info.
__________________
Grab your sword and fight the Horde!
  Reply With Quote
02-10-13, 04:57 PM   #3
gmarco
An Onyxian Warder
 
gmarco's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 362
Thanks so much for your reply.
I'll begin to study your code now ... :-)

Thanks again.
__________________
This is Unix-Land. In quiet nights, you can hear the Windows machines reboot.
  Reply With Quote
02-11-13, 03:04 AM   #4
gmarco
An Onyxian Warder
 
gmarco's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 362
After a little bit of coding I am not able to display anything inside , probably because I think I miss something more :-/

I have in my addon a defined config frame in this way:

Lua Code:
  1. local options = CreateFrame("Frame", ADDON.."Options", InterfaceOptionsFramePanelContainer)
  2. [...]

and so I changed your code in this way:

Lua Code:
  1. local scrollFrame = CreateFrame("ScrollFrame", "MyFirstNotReallyScrollFrame", options, "FauxScrollFrameTemplate")

Then I begin to populate the list array:

Lua Code:
  1. local list = {"aaa", "bbb", "ccc" }

But I don't get any output (nor errors).

I think I miss the frame to be displayed if I understand well what you wrote to me.

Thanks for attention.
__________________
This is Unix-Land. In quiet nights, you can hear the Windows machines reboot.
  Reply With Quote
02-11-13, 06:24 AM   #5
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
You need to call the update function manually once to "initialize" it. Might be it.
__________________
Grab your sword and fight the Horde!
  Reply With Quote
02-11-13, 08:40 AM   #6
gmarco
An Onyxian Warder
 
gmarco's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 362
It doesn't work either.

I have double checked everything again and again but I am not able to see any outputs even if I add a :

Lua Code:
  1. update(scrollFrame)

to manually initialize the frame as you suggest.

If I have understood your post, the scrollframe should be the parent frame that will contain the inner scroll child... And so I need another frame to contain all the other things I wanna to be scrolled ...

But here I really don't understand where is this second frame, where I could add, in example, the buttons.

I am sorry if it is a silly question, but I am really lost now :-)

Thanks again for you replies.
__________________
This is Unix-Land. In quiet nights, you can hear the Windows machines reboot.
  Reply With Quote
02-11-13, 10:39 AM   #7
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
No, there is no scroll child [that you need worry about]. That's the thing with the FauxScrollFrameTemplate; it's solely based on the value of the scroll bar. Did you create font strings for the buttons? I can't think of anything else, so if you could post your code we can have a look.
__________________
Grab your sword and fight the Horde!
  Reply With Quote
02-11-13, 12:25 PM   #8
gmarco
An Onyxian Warder
 
gmarco's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 362
Thanks again for you replies.

I think I have added the Settext ...
I packed your code in a simple addon so we can test better.

The code is:

Lua Code:
  1. local NUM_BUTTONS = 8
  2. local BUTTON_HEIGHT = 20
  3.  
  4. local list = {"aaaa","bbbbb","cccccc","ddddddd","eeeeee","ffffff","gggggg","hhhhh"}
  5. local buttons = {}
  6.  
  7. local function update(self)
  8.     local numItems = #list
  9.     print ("DEBUG: nr. items " .. numItems)
  10.     FauxScrollFrame_Update(self, numItems, NUM_BUTTONS, BUTTON_HEIGHT)
  11.     local offset = FauxScrollFrame_GetOffset(self)
  12.     for line = 1, NUM_BUTTONS do
  13.         local lineplusoffset = line + offset
  14.         local button = buttons[line]
  15.         if lineplusoffset > numItems then
  16.             button:Hide()
  17.         else
  18.             button:SetText(list[lineplusoffset])
  19.             button:Show()
  20.         end
  21.     end
  22. end
  23.  
  24. local scrollFrame = CreateFrame("ScrollFrame", "MyFirstNotReallyScrollFrame", UIParent, "FauxScrollFrameTemplate")
  25. scrollFrame:SetScript("OnVerticalScroll", function(self, offset)
  26.     FauxScrollFrame_OnVerticalScroll(self, offset, BUTTON_HEIGHT, update)
  27. end)
  28.  
  29. for i = 1, NUM_BUTTONS do
  30.     local button = CreateFrame("Button", nil, scrollFrame:GetParent())
  31.     if i == 1 then
  32.         button:SetPoint("TOP", scrollFrame)
  33.     else
  34.         button:SetPoint("TOP", buttons[i - 1], "BOTTOM")
  35.     end
  36.     button:SetSize(96, BUTTON_HEIGHT)
  37.     button:SetText(list[i])
  38.     buttons[i] = button
  39. end
  40.  
  41. print ("DEBUG: Force updating")
  42. update(scrollFrame)

I attach also the zip file of the addon directory.

Thanks again.
Attached Files
File Type: zip MyModScrollBar.zip (1.1 KB, 510 views)
__________________
This is Unix-Land. In quiet nights, you can hear the Windows machines reboot.
  Reply With Quote
02-12-13, 01:52 AM   #9
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
Interesting. I'm currently in the same boat. Setting up my first config panel atm.

http://www.wowinterface.com/forums/s...75&postcount=6

Currently into getting my classes up and running. Never created my own classes.

I need a scrollframe aswell. My ScrollFrame should fit right into the huge yellow space:
http://imgur.com/a/ecy2H

It should containt a bunc of Sliders/DropDownMenus/Buttons. I hope this is possible because I read ScrollFrame just hide frames while scrolling while showing others.

The thread will be a big help anyway. Thanks.
Maybe I need to create a sort of "lineFrame" first that I can show/hide.

gmarco if you need help on uipanel template stuff you check out:
http://code.google.com/p/rothui/sour.../wow5.0/rTest/
http://code.google.com/p/rothui/sour....0/rTestPanel/

Those are my test addons.
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

Last edited by zork : 02-12-13 at 01:58 AM.
  Reply With Quote
02-12-13, 06:49 AM   #10
gmarco
An Onyxian Warder
 
gmarco's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 362
Hi Zork,
thanks for your reply . I surely check your code and study it.
Let's see if finally I succeded in learning the use of all these frames even if I really don't understand why lombra code will not work for me.
__________________
This is Unix-Land. In quiet nights, you can hear the Windows machines reboot.
  Reply With Quote
02-12-13, 07:16 AM   #11
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
SetText is there yes, but the button needs a font string to display any text. (or maybe it has one by default, can't actually remember)

Either way, the scroll frame needs dimensions and a position before it'll show up.

@ Zork:
Since FauxScrollFrameTemplate is best suited for items with identical height, you might be better off using a real scroll frame. Or it could work if you created identical frames for each widget, as you said.
__________________
Grab your sword and fight the Horde!
  Reply With Quote
02-12-13, 09:25 AM   #12
gmarco
An Onyxian Warder
 
gmarco's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 362
I am doing good progress

The code finally is displaying something :-)

Lua Code:
  1. local NUM_BUTTONS = 8
  2. local BUTTON_HEIGHT = 20
  3. local BUTTON_WIDTH = 96
  4.  
  5. local list = {"aaaa","bbbbb","cccccc","ddddddd","eeeeee","ffffff","gggggg","hhhhh"}
  6. local buttons = {}
  7.  
  8. local function update(self)
  9.     local numItems = #list
  10.     print ("DEBUG: nr. items " .. numItems)
  11.     FauxScrollFrame_Update(self, numItems, NUM_BUTTONS, BUTTON_HEIGHT)
  12.     local offset = FauxScrollFrame_GetOffset(self)
  13.     for line = 1, NUM_BUTTONS do
  14.         local lineplusoffset = line + offset
  15.         local button = buttons[line]
  16.         if lineplusoffset > numItems then
  17.             button:Hide()
  18.         else
  19.             button:SetText(list[lineplusoffset])
  20.             button:Show()
  21.         end
  22.     end
  23. end
  24.  
  25. local scrollFrame = CreateFrame("ScrollFrame", "MyFirstNotReallyScrollFrame", UIParent, "FauxScrollFrameTemplate")
  26. scrollFrame:SetWidth(BUTTON_WIDTH)
  27. scrollFrame:SetHeight(BUTTON_HEIGHT*6)
  28. scrollFrame:SetPoint("CENTER",UIParent)
  29. scrollFrame:EnableMouse(true)
  30. scrollFrame:SetMovable(true)
  31. scrollFrame:RegisterForDrag("LeftButton")
  32. scrollFrame:SetScript("OnDragStart", function(self) self:StartMoving() end)
  33. scrollFrame:SetScript("OnDragStop", function(self) self:StopMovingOrSizing() end)
  34. scrollFrame:Show()
  35. scrollFrame:SetClampedToScreen(true)
  36. scrollFrame:SetScript("OnVerticalScroll", function(self, offset)
  37.     FauxScrollFrame_OnVerticalScroll(self, offset, BUTTON_HEIGHT, update)
  38. end)
  39.  
  40. for i = 1, NUM_BUTTONS do
  41.     local button = CreateFrame("Button", nil, scrollFrame:GetParent())
  42.     if i == 1 then
  43.         button:SetPoint("TOP", scrollFrame)
  44.     else
  45.         button:SetPoint("TOP", buttons[i - 1], "BOTTOM")
  46.     end
  47.     button:SetNormalFontObject("GameFontNormal")
  48.     button:SetSize(BUTTON_WIDTH, BUTTON_HEIGHT)
  49.     button:SetText(list[i])
  50.     buttons[i] = button
  51. end
  52.  
  53.  
  54.  
  55. -- enabling the last line will make the slidebar disappears.
  56. -- print ("DEBUG: Force updating")
  57. -- update(scrollFrame)

Now I get the scrollframe with sliders but it is wrong. You can check the picture to see...
It doesn't cover the out of scrollframe part nor it scrolls using the slide.

Other thing: If I enable the manual update of the frame (last line) the sliders will disappears (!??!) :-)

Thanks again for any inputs/clues/tips :-)
Attached Thumbnails
Click image for larger version

Name:	img-001.png
Views:	959
Size:	49.1 KB
ID:	7563  
__________________
This is Unix-Land. In quiet nights, you can hear the Windows machines reboot.
  Reply With Quote
02-12-13, 10:00 AM   #13
Lombra
A Molten Giant
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 554
Good to hear.

This is all expected. The buttons are actually completely independant of the scroll frame and vice versa. They just happen to be anchored to it. For all the scroll frame knows, you could be simply printing different numbers in the update function instead of doing something with the buttons.

You have decided that 8 buttons be created (as per NUM_BUTTONS), and the size of the scroll frame is smaller than the total height of these. That's all there is to it. Again, the scroll frame is completely independent of the buttons, and has no idea how much screen space they take up. If you're using constants for the number of buttons and their height a simple solution would be:
Code:
scrollFrame:SetHeight(NUM_BUTTONS * BUTTON_HEIGHT)
which I just noticed you were nearly already doing, you just used 6 instead of 8 which NUM_BUTTONS was set to. This way the appropriate height will always be calculated when you change the amount and height of the buttons via the constants. At least, as long as the offset between each button is 0.

The scroll bar will always remain in its original state (visible and inactive) until you first call FauxScrollFrame_Update, which you do in the update function. The reason it disappears when you do so is that you have enough buttons that the entire list can be displayed without scrolling (you have 8 buttons and 8 items in the list). If you add one more item or remove one button, you will see that it works!
__________________
Grab your sword and fight the Horde!
  Reply With Quote
02-12-13, 10:00 AM   #14
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
Try this example
http://wowprogramming.com/snippets/W...roll_frames_22

It does not make use of templates yet but it shows how to handle the ScrollChild.

Of course...using FauxTemplate is handling the ScrollChild quite differently I think.

*edit*

Got exactly what I was looking for.



Code will be coming soon.

I'm using a ScrollFrame with this template: "UIPanelScrollFrameTemplate" with a twist.

To bad I wanted a ScrollBar with this template: "UIPanelScrollBarTrimTemplate". The UIPanelScrollFrameTemplate only uses UIPanelScrollBarTemplate. So I just looked up the SetTexCoord for the scrollbar border and added it manually.

*edit*

Ok here is the code that does it:
http://code.google.com/p/rothui/sour...estScrollFrame

Thanks to templates there is actually veeery few code to write.
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

Last edited by zork : 02-12-13 at 01:26 PM.
  Reply With Quote
02-12-13, 02:08 PM   #15
gmarco
An Onyxian Warder
 
gmarco's Avatar
AddOn Author - Click to view addons
Join Date: Dec 2009
Posts: 362
Thanks to Lombra !!
Now I have my example ready to be implemented in the addon (remgank :-) .

Zork, I'll give you look to your code too. I am very curious about the template facilities even if the code by Lombra is for my needs the thing I was looking for. :-)

I think this thread should be made sticky or someone should made a little summary sticky :-) because the scrollframes are imho one of the things that a newbie programmer have more problems with.

I'll post the working code later (after the raid if I don't sleep :-) and probably with some more questions ... :-)

Thanks also to Zork, his inputs are really appreciated.
__________________
This is Unix-Land. In quiet nights, you can hear the Windows machines reboot.
  Reply With Quote
02-12-13, 02:46 PM   #16
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
I finshed my test and implemented a first version into my panel.

http://imgur.com/a/4WtBM

You can even freely resize the whole panel and the scrollFrame will be cropped properly. The scrollbar adjusts properly aswell. Very nice.

All what I had to do was:
http://code.google.com/p/rothui/sour.../subFrames.lua

If you are fine with the default template you can even go with

Lua Code:
  1. --create a scrollframe inside
  2.     local scrollFrame = CreateFrame("ScrollFrame", "$parentScrollFrame", frame, "UIPanelScrollFrameTemplate")
  3.     scrollFrame:SetPoint("TOPLEFT")
  4.     scrollFrame:SetPoint("BOTTOMRIGHT",-22,0)
  5.  
  6.     local scrollChild = CreateFrame("Frame",nil,ScrollFrame)
  7.     --scrollChild:SetWidth(scrollFrame:GetWidth()) --optional
  8.     --fill scrollchild with data and adjust size
  9.     genData(scrollChild,100)
  10.     scrollFrame:SetScrollChild(scrollChild)
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)
  Reply With Quote
02-13-13, 09:43 AM   #17
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
...

I just had an "what if"-moment.

Please help me on that.

The scrollFrame crops anything from the ChildFrame that is not visible. That is actually pretty interesting...

I tested only FontStrings...does this work on any frame type? Need to test sth asap.
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

Last edited by zork : 02-13-13 at 10:11 AM.
  Reply With Quote
02-13-13, 10:24 AM   #18
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
The scrollframe will clip any part of the child frame that passes its border, but be aware that it still has to draw everything, even if you can't see it. The only frame type I'm not sure will clip are models, but it would be easy enough to test.

Here are some ways I've used scrollframes:




And this is what happens if you try to rotate the scroll parent..


And yes, you can put scrollframes inside of scrollframes.

Last edited by semlar : 02-13-13 at 10:30 AM.
  Reply With Quote
02-13-13, 11:58 AM   #19
zork
A Pyroguard Emberseer
 
zork's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2008
Posts: 1,740
Holy mother of grail. I'm just testing. Do you know what that means?

I can finally cut animation models depending on orb value state!!!


Lol ... I cannot believe this is for real. But I have a screenshot. It actually does work.



Any kind of animation will be cropped. Models, textures, anything.

No more alpha fading ... HOLY SMOKES!!! This is HUUUGE!!! (at least for me...)
__________________
| Simple is beautiful.
| WoWI AddOns | GitHub | Zork (WoW)

"I wonder what the non-pathetic people are doing tonight?" - Rajesh Koothrappali (The Big Bang Theory)

Last edited by zork : 02-13-13 at 03:24 PM.
  Reply With Quote
02-13-13, 12:28 PM   #20
humfras
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Oct 2009
Posts: 131
I can see clearly now...

This solution is so simple, why didn't someone thought about that before?

Kleiner Tipp: Du solltest die RealIDs unkenntlich machen.
__________________
Author of VuhDo CursorCastBar OptiTaunt Poisoner RaidMobMarker

Last edited by humfras : 02-13-13 at 12:31 PM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Help on ScrollFrame with LUA

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