WoWInterface (
-   Lua/XML Help (
-   -   How to build UI in order to present a table? (

FranekW 04-02-21 05:58 AM

How to build UI in order to present a table?

It is possible I am asking about Mixins but I am a total beginner regarding UI and frames in WoW.

I have a small addon, which I use to gather some information about my runs in mythc+ dungeons. It's structured in a table and I simply use default chat to list everything if I am looking for something.

I want to present all this information in a frame. I looked at a few add-ons as well as a couple of frames by Blizzard. For instance, SaveInstances has a list of details about payers saved for dungeons/raids or current state on currencies etc.; it is presented in a frame/table whose background alternates from row to row as well as highlights a row on mouseover. Another example is Blizzard's Guilds and Communities, and particularly a list of members; it looks clean because each name is on the same background repeated per line.

I was wondering if I can do that for my addon. When I searched Google, I came across Mixins, which I am not familiar with but seems to be what I am looking for. If I am correct, it is a way of "presenting" tables. Is it possible to use one of Blizzard's templates for myself? Also, if I know what I want to use, how can I find a particular Mixin?


kurapica.igas 04-02-21 06:55 AM

Since you already use the default chat to display, You can just use the SimpleHTML widget, I use it to show details of the table/frames like :

The green text are links, you can click you can move it to show tips.

It's simple to concat string than create fontstring arrays.

FranekW 04-02-21 08:11 AM

Thanks. I have also considered SimpleHTML. I even made a function converting the said table > HTML but somehow it doesn't render HTML but shows the full HTML code in it. Would you mind sharing your code? That frame would be a good start :) but, eventually, I would like to make something with a custom frame :) Just for the sake of learning. i am not very good at UI and would like to learn it, as well.

kurapica.igas 04-02-21 09:15 AM

1 Attachment(s)
The html used by the SimpleHtml has many limits. If you get the whole html, it means the widget reject to render it.

You should check the Well-formed HTML in the Also concat string directly is a real pain.

Create custom UI is a big topic to be discussed here. You may discuss it in the [email protected]

And for the code to create such a frame, if you don't mind using other libs:

Attachment 9606

Lua Code:
  1. Scorpio "SimpleHtmlTest" ""  -- A Module based on my Scorpio Lib
  3. -- Create a dialog to contains the viewer
  4. Browser                         = Dialog("SimpleHtmlTestBrowser")
  6. -- Create the html view from a template class based on the SimpleHtml
  7. viewer                          = HtmlViewer  ("Viewer", Browser)
  9. -- Handle the link click
  10. function viewer:OnHyperlinkClick(path)
  11.     if path then
  12.         -- Click the link and send to the chat box for copy
  13.         ChatEdit_ActivateChat(ChatFrame1EditBox)
  14.         ChatFrame1EditBox:SetText(path)
  15.         ChatFrame1EditBox:HighlightText(0, #path)
  16.     end
  17. end
  19. -- The style of those ui, just like xml with properties.
  20. Style[Browser]                  = {
  21.     Header                      = { Text = "Table Viewer" },
  22.     Size                        = Size(800, 600),
  23.     clampedToScreen             = true,
  24.     minResize                   = Size(600, 400),
  26.     Viewer                      = {
  27.         location                = { Anchor("TOPLEFT", 24, -32), Anchor("BOTTOMRIGHT", -48, 48) },
  28.     },
  29. }
  32. -- A template string used to generate the target string with data
  33. -- @xxx is the directives for lua codes, so here `name` and `target`
  34. -- are the special variables to generate the final string
  35. TEMPLATE_TABLE                  = System.Text.TemplateString[[
  36.     <html>
  37.         <body>
  38.             <h1>@name</h1>
  39.             <br/>
  40.             @for k, v in pairs(target) do
  41.             <p><a href="@k">@k</a></p>
  42.             @end
  43.         </body>
  44.     </html>
  45. ]]
  47. -- A test
  48. viewer:SetText(TEMPLATE_TABLE{
  49.     name = "C_AuctionHouse",
  50.     target = C_AuctionHouse,
  51. })

It'd could be more longer to create this without a lib.

So this is an ADs :cool:

The Scorpio is a power addon dev platform, you can find my post at

I don't really like blz's mixin system, but you still can find me in the discord.

Gello 04-02-21 10:59 AM

Very often, displaying information in table form generally means creating a frame/button for each row where each row is broken up into sections (columns), and then positioning each row one below the next so they form a table. Then you loop through the rows and update the columns.

It's very common to do this with a scrollframe too, which allows your table to be scrollable.

The code that follows adds a /showme slash command to summon a scrollable table of random data. (You can repeat /showme to generate new random data.)

When the number of rows has the potential to far exceed the displayable area, it's common to use a HybridScrollFrameTemplate or FauxScrollFrameTemplate. Then you only have as many rows that can be displayed and you update the content based on the scrollbar offset. In the example below I've doing a basic scrollframe where every row is defined so you don't need to worry about offsets. (This is not suggested for long lists, but probably easier to pick apart.)

Lua Code:
  1. local CELL_WIDTH = 100
  2. local CELL_HEIGHT = 20
  3. local NUM_CELLS = 3 -- cells per row
  5. -- we'll use an ordered table of arbitrary data: {{fruit,number,alphabet},{fruit,number,alphabet},etc}
  6. local fruits = {"apple","banana","orange","pear","tomato","pineapple"}
  7. local numbers = {"one","two","three","four","five","six"}
  8. local alphabet = {"abc","def","ghij","klmn","op","qrstuv","wx","yz"}
  9. local data = {}
  11. -- just generates a random bunch of data in the data table
  12. local function updateData()
  13.     wipe(data)
  14.     for i=1,10+random(40) do
  15.         tinsert(data,{fruits[random(#fruits)], numbers[random(#numbers)], alphabet[random(#alphabet)]})
  16.     end
  17. end
  19. -- creating a basic dialog frame (if you name this frame and define basic bits during the load (not after PLAYER_LOGIN), then
  20. -- the client will restore the window position on login to wherever it was last moved by the user)
  21. local f = CreateFrame("Frame","SimpleScrollFrameTableDemo",UIParent,"BasicFrameTemplateWithInset")
  22. f:SetSize(CELL_WIDTH*NUM_CELLS+40,300)
  23. f:SetPoint("CENTER")
  24. f:Hide()
  25. f:SetMovable(true)
  26. f:SetScript("OnMouseDown",f.StartMoving)
  27. f:SetScript("OnMouseUp",f.StopMovingOrSizing)
  29. -- adding a scrollframe (includes basic scrollbar thumb/buttons and functionality)
  30. f.scrollFrame = CreateFrame("ScrollFrame",nil,f,"UIPanelScrollFrameTemplate")
  31. f.scrollFrame:SetPoint("TOPLEFT",12,-32)
  32. f.scrollFrame:SetPoint("BOTTOMRIGHT",-34,8)
  34. -- creating a scrollChild to contain the content
  35. f.scrollFrame.scrollChild = CreateFrame("Frame",nil,f.scrollFrame)
  36. f.scrollFrame.scrollChild:SetSize(100,100)
  37. f.scrollFrame.scrollChild:SetPoint("TOPLEFT",5,-5)
  38. f.scrollFrame:SetScrollChild(f.scrollFrame.scrollChild)
  40. -- adding content to the scrollChild
  41. local content = f.scrollFrame.scrollChild
  42. content.rows = {} -- each row of data is one wide button stored here
  44. local function updateList()
  45.     for i=1,#data do
  46.         -- create a row if not created yet (buttons[i] is a whole row; buttons[i].columns[j] are columns)
  47.         if not content.rows[i] then
  48.             local button = CreateFrame("Button",nil,content)
  49.             button:SetSize(CELL_WIDTH*NUM_CELLS,CELL_HEIGHT)
  50.             button:SetPoint("TOPLEFT",0,-(i-1)*CELL_HEIGHT)
  51.             button.columns = {} -- creating columns for the row
  52.             for j=1,3 do
  53.                 button.columns[j] = button:CreateFontString(nil,"ARTWORK","GameFontHighlight")
  54.                 button.columns[j]:SetPoint("LEFT",(j-1)*CELL_WIDTH,0)
  55.             end
  56.             content.rows[i] = button
  57.         end
  58.         -- now actually update the contents of the row
  59.         for j=1,3 do
  60.             content.rows[i].columns[j]:SetText(data[i][j])
  61.         end
  62.         -- show the row that has data
  63.         content.rows[i]:Show()
  64.     end
  65.     -- hide all extra rows (if list shrunk, hiding leftover)
  66.     for i=#data+1,#content.rows do
  67.         content.rows[i]:Hide()
  68.     end
  69. end
  71. -- create /showme slash command to make up data and summon window
  72. SLASH_SHOWME1 = "/showme"
  73. SlashCmdList["SHOWME"] = function(msg)
  74.     updateData()
  75.     updateList()
  76.     f:Show()
  77. end

FranekW 04-03-21 03:57 AM

Thank you for the example codes and the idea of adding buttons as cells. I think I can follow from here and start trying something :) Thanks

All times are GMT -6. The time now is 10:46 PM.

vBulletin © 2022, Jelsoft Enterprises Ltd
© 2004 - 2021 MMOUI