logo
back Back to Downloads

Pkg-GridPanels

A MayronObjects package that allows you to create UI panels using a grid of cells. The package also supports responsive scroll frames that dynamically shift child elements when the panel is resized.

downloaddownloaddownloadDownload from WoWInterfacedownloaddownloaddownloadDownload from CurseForge
1

About

Pkg-GridPanels is a MayronObjects package consisting of 4 classes to build responsive, grid-like UI panels in World of Warcraft. This package was used to build the responsive MayronUI configuration menu. By responsive, we refer to the ability for elements to dynamically shift to fit inside a resizable frame. However, this responsiveness feature is optional. The package also lets you easily assign frames to multiple grid regions, similar to how CSS-Grid works in web development.

There is a Test.lua file included in the downloaded addon folder to see other working examples of how to use this library.

The package includes the following classes:

  • Grid: Allows you to define a grid of rows and columns.
  • Region: Controls how a frame fits across one or more cells inside a grid.
  • Group: Allows you to select an entire row or column of cells to change their characteristics, such as their width and height.
  • ResponsiveScrollFrame: Creates a scroll frame whose child elements dynamically shift position if the panel is resized. The scroll bar hides and shows only when needed. It is supposed to be used inside a region on the grid instead of a standard frame.

To summarise, a Grid consists of many cells organised into rows and columns. A Region can be placed onto a cell, or span multiple cells. A Group represents all of the cells found inside a row or column and allows you to set a fixed width (or scale) of a column, or fixed height (or scale) of a row. A region contains a Blizzard widget, such as a Frame. It can also contain a scroll frame created by the ResponsiveScrollFrame class contained in this package for dynamic/responsive behaviour.

2

Grid API

A Grid consists of multiple cells organised into rows and columns.

First, import the Grid class from MayronObjects. You can do this by importing it directly, or if you need access to other classes inside Pkg-GridPanels then it is easier to import the full package and take what you need from it:

-- get the MayronObjects framework using: local obj = MayronObjects:GetFramework(); ---@type MayronObjects -- Import the entire package and get the classes from it: local C_GridPanels = obj:Import("GridPanels.Main"); ---@type Package local C_Grid = GridPanels:Get("Grid"); -- or, you can import it directly: -- local C_Grid = obj:Import("GridPanels.Main.Grid");

When using MayronObjects, it is conventional to include the C_ prefix for class variables.

2.1 Grid Constructor

The constructor takes 3 optional arguments:

  • @param frame (a blizzard widget): you can supply your own frame if you need to, otherwise Pkg-GridPanels will create a default one (that uses the new BackdropTemplateMixin to support WoW patch 9.0.1+).
  • @param globalName: If frame is nil, the default frame created by Pkg-GridPanels will be assigned the value of globalName as its global name.
  • @param parent: If frame is nil, the default frame created by Pkg-GridPanels will be assigned the value of parent as its parent frame. If parent and frame are both nil, the default frame will be assigned UIParent as its default parent frame.

Example:

local grid1 = C_Grid(); ---@type Grid -- creating a grid with a global name and different parent: local grid2 = C_Grid(nil, "MyFrame", SomeGlobalFrame); ---@type Grid -- or, with a custom frame: local frame = CreateFrame("Frame", nil, UIParent); local grid3 = C_Grid(frame); ---@type Grid

The grid instance inherits all of the methods contained in Blizzard's base Frame widget. The Grid class inherits from MayronObject's FrameWrapper class to pass all Frame function calls to the underlining frame. For example, calling grid1:SetPoint("CENTER") will call this on the frame widget managed by the grid object.

2.2 Grid Methods

Below is the full list of methods accessible from an instance of the Grid class, which together form the Grid API:

CreateRegion(frame, globalName, parent)

A helper function to call the Region constructor without needing to import the Region object. The constructor signature is identical to the Grid constructor previously mentioned (see section 2.1).

SetDimensions(width, height)

  • @param width (number or "auto"): Sets the number of grid columns. If set to "auto", adding more regions will automatically increase the number of columns to fit the content. When set to "auto", you will only be able to have at most one row.
  • @param height (number or "auto"): Sets the number of grid rows. If set to "auto", adding more regions will automatically increase the number of rows to fit the content. However, if width is also set to "auto" then the height will always be one and this value will be ignored.

Sets the number of rows and columns for the grid. If specifying a number, it should be a positive integer value.

GetDimensions()

  • @return: The width and height values, representing the number of columns and rows respectively. Each value is either a positive integer or "auto", as described above for the Grid:SetDimensions(width, height) documentation.

SetDevMode(devMode)

  • @param devMode (boolean): Enables or disable development mode.

If set to true, each cell is highlighted with a random background color and is given a fontstring to visually identify each cell. Regions placed over the top of cells are given a basic Blizzard UI border to show how they are spanning over the top of cells.

Region and Cell highlighting with devMode enabled

AddRegions(...)

  • @vararg: A variable argument list of Region Objects to add to the grid.

Adds one or more regions to the grid and handles the anchoring of their frames using the SetPoint Blizzard function. It also calls region:SetGrid(self) to assign the Grid object to each region provided. This function call should be done after setting the span sizes for each region (see section 3).

GetRegions(n)

  • @param n (optional number): Similary to select(n, ...). This unpacks all regions and returns them starting from the nth region. If not provided, all region objects will be returned.

Unpacks and returns all region objects as a list of return values.

Example:

local regionA, regionB, regionC = myGrid:GetRegions(); -- or, if you only need regionC: local regionC = myGrid:GetRegions(3);

GetRow(rowID)

  • @param rowID (number): The nth row to appear on the grid. The first row will have a row ID of 1.
  • @return (Group or nil): If that row exists, a Group object will be returned containing all cells that together form the specified row.

Returns a Group object if that row exists, allowing you to perform operations on a group of cells where each cell is part of the specified row.

GetColumn(columnID)

  • @param columnID (number): The nth column to appear on the grid. The first column will have a column ID of 1.
  • @return (Group or nil): If that column exists, a Group object will be returned containing all cells that together form the specified column.

Returns a Group object if that column exists, allowing you to perform operations on a group of cells where each cell is part of the specified column.

MakeResizable(dragger)

  • @param dragger (an optional Frame or other Widget): If supplied, this will be used by the user to drag and resize the grid frame. If missing, the entire frame will be draggable.

When called, the grid frame will become resizable by dragging it. If a custom dragger widget is provided then you will only be able to resize the frame by dragging the dragger frame. Ideally, you would anchor this dragger frame onto the grid frame, such as placing it in the bottom right corner.

3

Region API

A Region contains and manages a Frame, or other Blizzard widget, to be placed onto a Grid frame using the AddRegions Grid function (see section 2). A region can be placed on a grid cell, or can span across multiple cells vertically and horizontally.

3.1 Region Constructor

The region's constructor takes the same optional arguments as the Grid constructor mentioned in section 2. The CreateRegion Grid method can also takes these same arguments:

  • @param frame (a blizzard widget): you can supply your own frame if you need to, otherwise Pkg-GridPanels will create a default one (that uses the new BackdropTemplateMixin to support WoW patch 9.0.1+).
  • @param globalName: If frame is nil, the default frame created by Pkg-GridPanels will be assigned the value of globalName as its global name.
  • @param parent: If frame is nil, the default frame created by Pkg-GridPanels will be assigned the value of parent as its parent frame. If parent and frame are both nil, the default frame will be assigned UIParent as its default parent frame.

You can either import the Region class directly to be instantiated (i.e. create an instance of it):

-- get the MayronObjects framework using: local obj = MayronObjects:GetFramework(); ---@type MayronObjects -- import the GridPanels package: local GridPanels = obj:Import("GridPanels.Main"); ---@type Package -- get the Grid and Region classes from the package: local C_Grid = GridPanels:Get("Grid"); local C_Region = GridPanels:Get("Region"); -- create a region: local region = C_Region(); ---@type Region -- creating a region with a global name and different parent: local region2 = C_Region(nil, "MyRegion", SomeGlobalFrame); ---@type Region -- or, with a custom frame: local frame = CreateFrame("Frame", nil, UIParent); local region3 = C_Region(frame); ---@type Region

When using MayronObjects, it is conventional to include the C_ prefix for class variables.

Or, you can call the CreateRegion function from an instance of the Grid class:

-- get the MayronObjects framework using: local obj = MayronObjects:GetFramework(); ---@type MayronObjects -- import the Grid class local Grid = obj:Import("GridPanels.Main.Grid"); -- create a grid: local grid = C_Grid(); -- create a region from the grid instance: local region = grid:CreateRegion(); -- creating a region with a global name and different parent: local region2 = grid:CreateRegion(nil, "MyRegion", SomeGlobalFrame); ---@type Region -- or, with a custom frame: local frame = CreateFrame("Frame", nil, UIParent); local region3 = grid:CreateRegion(frame); ---@type Region

The region instance inherits all of the methods contained in Blizzard's base Frame widget. The Region class inherits from MayronObjects FrameWrapper class to pass all Frame function calls to the underlining frame. For example, calling region:SetPoint("CENTER") will call this on the frame widget managed by the region object.

Once you have created some regions, and possibly configured how many cells each of them should span, you can add them to the grid frame to be anchored automatically by Pkg-GridPanels:

grid:AddRegions(region, region2, region3);

3.1 Region Methods

Below is the full list of methods accessible from an instance of the Region class, which together form the Region API:

SetSpanSize(width, height)

  • @param width (number): The number of grid cells to span horizontally to the right.
  • @param height (number): The number of grid cells to span vertically down.

By default, a single region will be placed inside of a single cell. However, a region can span across multiple cells. For example, the first region that appears in the top-left of the grid spans 2 cells by specifying a height of 2. You can see this by enabling devMode for the grid (see the SetDevMode documentation in section 2):

Region and Cell highlighting with devMode enabled

SetGrid(grid)

  • @param grid (Grid): The grid to assign to the region.

Assigns a region to a grid.

This should never need to be manually called. When calling the AddRegions function from an instance of the Grid class, this function will be called automatically.

GetGrid()

  • @return: Returns the Grid object assigned to the region (or nil if it has not been asigned one).

SetInsets(...)

This function can be called with any of the following combination of arguments:

  • 1 argument:

    • @param 1 inset (number): The spacing between the edges of the cells to the region.
  • 2 arugments:

    • @param 1 vertical (number): The vertical spacing between the top and bottom edges of the cells to the region.
    • @param 2 horizontal (number): The horizontal spacing between the left and right edges of the cells to the region.
  • 4 arugments (in this exact order):

    • @param 1 top (number): The spacing between the top of the cells to the region.
    • @param 2 right (number): The spacing between the right of the cells to the region.
    • @param 3 bottom (number): The spacing between the bottom of the cells to the region.
    • @param 4 left (number): The spacing between the left of the cells to the region.

Example:

local grid = C_Grid(); ---@type Grid grid:SetDevMode(true); grid:SetPoint("CENTER"); grid:SetSize(800, 500); local regionA = C_Region(); ---@type Region regionA:SetInsets(10) -- all insets should be 10 local regionB = C_Region(); ---@type Region -- vertical insets should be 10 (top and bottom), -- horizontal insets should be 30 (left and right) regionB:SetInsets(10, 30); local regionC = C_Region(); ---@type Region -- top = 10, right = 30, bottom = 50, left = 80 regionC:SetInsets(10, 30, 50, 80); grid:SetDimensions(3, 1); grid:AddRegions(regionA, regionB, regionC);

The above code displays the following grid: Region Insets

4

Group API

A Group represents the group of cells that form either a row or column of the grid. You can use a Group object to set a fixed width or height to a row or column respectively, or set a scaling factor that resizes when the grid frame is resized.

4.1 Group Constructor

Similar to the Region object, you can create this directly or by calling a Grid helper function. If using the latter approach, you should set the Grid's dimensions first, else the function will return nil. This is the safest and recommended way as shown below:

-- get the MayronObjects framework using: local obj = MayronObjects:GetFramework(); ---@type MayronObjects local grid = C_Grid(); ---@type Grid grid:SetDimensions(3, 4); -- 3 columns, 4 rows = 12 cells in total -- row1 is a Group object representing the 1st row local row1 = grid:GetRow(1); -- column3 is a Group object representing the 3rd column (2nd from last) local column3 = grid:GetColumn(3);

4.2 Group Methods

Below is the full list of methods accessible from an instance of the Group class, which together form the Group API:

SetScale(scale)

  • @param scale (a positive number): Unlike a fixed width or height value, a scale takes up a percentage of the grid frame's width.

By default, each row or column has a scale of 1. If a Group representing a row uses this function to set the scale to 2 then each cell in this row will have double the height of any other row (assuming that other rows have not been changed).

The following columns each have a different scaling factor. When resizing the grid frame, the columns increase or decrease in width to take up the same percentage:

Scaling Groups

SetFixed(value)

  • @param value (a positive number): Give the row or column a fixed height or width. If it is a row, this value will represent height and vice-versa.

Unlike setting a row or column by scale, rows or columns marked with a fixed value will not change in height or width when the grid frame changes size.

You can have some rows and columns set to scale and others set to a fixed size inside the same grid.

5

Responsive Scroll Frames

The ResponsiveScrollFrame class contained inside the GridPanels package can be used without any of the other classes, but it might be a good idea to use it inside a Region to be positioned on the grid instead of the default frame created by the region.

A responsive scroll frame will dynamically reposition/re-anchor child elements contained inside it when it changes in width. When changed in height, the scroll bar will dynamically show and hide when the user should scroll to see more. If all the elements fit inside the frames height then the scroll bar does not need to show.

Elements added as children to the responsive scroll frame will be positioned from the top-left corner of the scroll frame and will move to the right until there is not enough room to fit. Once filled, new elements will be appended to a new row below the filled up row to repeat the process. You should never need to position these child elements manually. Elements are basic Blizzard widgets, such as frames and buttons. They can be fully customised before being added to the responsive scroll frame. Below is a preview of what this might look like:

Responsive scroll frame with child elements

The responsive scroll frame inherits all of the functions contained in Blizzard's base Frame widget. The following code sample shows this in action.

-- get the MayronObjects framework using: local obj = MayronObjects:GetFramework(); ---@type MayronObjects -- import the ResponsiveScrollFrame class: local C_ResponsiveScrollFrame = obj:Import("GridPanels.Main.ResponsiveScrollFrame"); -- create an instance of it: ---@type ResponsiveScrollFrame local frame = C_ResponsiveScrollFrame(nil, "ResponsiveScrollFrame_Test1"); -- you can call Blizzard widget functions like you usually would: frame:SetPoint("CENTER"); frame:SetSize(400, 500); -- create some child elements (such as other frames, buttons, etc...) -- then add them to the responsive scroll frame: frame:AddChildren(element1, element2, element3, element4); -- you should then make it draggable to see its potential: frame:MakeResizable();

5.1 ResponsiveScrollFrame Constructor

The constructor consists of 4 optional arguments:

  • @param containerFrame (Frame): The frame that wraps around the scroll frame. The actual scroll frame is created by the constructor but can be accessed later using the GetScrollFrame function. If nil, Pkg-GridPanels will create a default one (that uses the new BackdropTemplateMixin to support WoW patch 9.0.1+).
  • @param globalName: If containerFrame is nil, the default frame created by Pkg-GridPanels will be assigned the value of globalName as its global name.
  • @param parent: If containerFrame is nil, the default frame created by Pkg-GridPanels will be assigned the value of parent as its parent frame. If parent and frame are both nil, the default frame will be assigned UIParent as its default parent frame.
  • @param child (Frame): A custom child frame to be set as the scroll frame's "scroll child" using Blizzard's SetScrollChild function. If nil, a basic frame is created using CreateFrame("Frame").

5.2 ResponsiveScrollFrame Methods

The ResponsiveScrollFrame class is a sub-class of the FrameWrapper class provided by MayronObjects. This allows instance objects to use both the custom ResponsiveScrollFrame class functions, as well as Frame widget functions, which are called on the underlining container frame (the frame that contains the nested scroll frame).

Below is the full list of methods that are accessible from any instance of the ResponsiveScrollFrame class:

SetElementSpacing(spacing)

  • @param spacing (number): The spacing (or inset) around each child element.

SetContainerPadding(padding)

  • @param spacing (number): The padding around the edges of the container frame.

AddChildren(...)

  • @vararg: A variable argument list of elements to append to the responsive scroll frame. These child elements can be basic Blizzard widgets, such as a frame or button.

Do not add a scroll frame as a child to the responsive scroll frame. Nested scroll frames seem to cause strange behaviour even without using Pkg-GridPanels.

GetChildren()

Returns all child elements.

GetScrollFrame()

Returns the scroll frame created inside the ResponsiveScrollFrame constructor.

GetScrollBar()

A helper function to return the scroll bar in a more convenient way.

GetScrollBarButtons()

A helper function to return the up and down buttons (in that order) of the scroll bar in case you want to customise them.

GetScrollBarThumbTexture()

A helper function to return the draggable "thumb" texture of the scroll bar in case you want to customise it.

GetScrollBarThumbTexture()

A helper function to return the draggable "thumb" texture of the scroll bar in case you want to customise it.

MakeResizable(dragger)

  • @param dragger (an optional Frame or other Widget): If supplied, this will be used by the user to drag and resize the responsive scroll frame. If missing, the entire frame will be draggable.

When called, the responsive scroll frame will become resizable by dragging it. If a custom dragger widget is provided then you will only be able to resize it by dragging the dragger frame. Ideally, you would anchor this dragger frame onto the responsive scroll frame, such as placing it in the bottom right corner.

If you add the responsive scroll frame as part of a region on a grid frame then do not use this. Instead, use Grid:MakeResizable() to make the entire grid frame resizable.

back Back to Downloads

© 2021 MayronUI.com, All rights reserved.