Last active
December 12, 2022 15:37
-
-
Save Meorawr/e06fd7371bc76647bac7417961c67135 to your computer and use it in GitHub Desktop.
Scrollable Auto-Resizing Layout Frame
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local ContentFrameMixin = CreateFromMixins(ResizeLayoutMixin); | |
function ContentFrameMixin:OnLoad() | |
self.texturePool = CreateTexturePool(self, "OVERLAY"); | |
end | |
function ContentFrameMixin:GeneratePage() | |
self.texturePool:ReleaseAll(); | |
local MIN_TEXTURE_HEIGHT = 20; | |
local MAX_TEXTURE_HEIGHT = 40; | |
local MIN_TEXTURE_WIDTH = 200; | |
local MAX_TEXTURE_WIDTH = 400; | |
for i = 1, fastrandom(10, 30) do | |
local width = fastrandom(MIN_TEXTURE_WIDTH, MAX_TEXTURE_WIDTH); | |
local height = fastrandom(MIN_TEXTURE_HEIGHT, MAX_TEXTURE_HEIGHT); | |
local r, g, b = fastrandom(), fastrandom(), fastrandom(); | |
local texture = self.texturePool:Acquire(); | |
texture:SetColorTexture(r, g, b); | |
texture:SetSize(width, height); | |
texture:SetPoint("TOP", 0, -((i - 1) * MAX_TEXTURE_HEIGHT)); | |
texture:Show(); | |
end | |
-- This is required after you're done laying out your contents; on the | |
-- end of the current game tick (OnUpdate) the Layout method provided | |
-- by ResizeLayoutMixin will be called which will resize this frame to | |
-- the total extents of all child regions. | |
self:MarkDirty(); | |
end | |
--- | |
local ScrollableContentFrameMixin = {}; | |
function ScrollableContentFrameMixin:OnLoad() | |
self.ScrollBar = CreateFrame("EventFrame", nil, self, "WowTrimScrollBar"); | |
self.ScrollBar:SetPoint("TOPRIGHT"); | |
self.ScrollBar:SetPoint("BOTTOMRIGHT"); | |
self.ScrollBox = CreateFrame("Frame", nil, self, "WowScrollBox"); | |
self.ScrollBox:SetPoint("TOPLEFT"); | |
self.ScrollBox:SetPoint("BOTTOMRIGHT", self.ScrollBar, "BOTTOMLEFT"); | |
self.ScrollBox:FullUpdate(ScrollBoxConstants.UpdateQueued); | |
self.ScrollView = CreateScrollBoxLinearView(); | |
self.ScrollView:SetPanExtent(50); -- Controls the distance scrolled. | |
-- Note that the content frame must, either directly or indirectly, inherit | |
-- ResizeLayoutFrame. It must additionally be parented to the scrollbox | |
-- and needs the ".scrollable" field set to true. | |
self.ContentFrame = Mixin(CreateFrame("Frame", nil, self.ScrollBox, "ResizeLayoutFrame"), ContentFrameMixin); | |
self.ContentFrame.scrollable = true; | |
self.ContentFrame:OnLoad(); | |
self.ContentFrame:SetPoint("TOPLEFT", self.ScrollBox); | |
self.ContentFrame:SetPoint("TOPRIGHT", self.ScrollBox); | |
self.ContentFrame:SetScript("OnSizeChanged", GenerateClosure(self.OnContentSizeChanged, self)); | |
self.ContentFrame:GeneratePage(); | |
-- This generally needs to be called after all scrollable children of the | |
-- scrollbox have been created; this will reparent any of its children | |
-- with the ".scrollable" field set to that of the inner scroll target | |
-- frame. | |
-- | |
-- You can call this _before_ creating all scrollable children, but you'll | |
-- need to ensure that instead of being parented to the scrollbox that | |
-- they're instead parented to the scroll target - which is accessible from | |
-- "self.ScrollBox:GetScrollTarget()". | |
ScrollUtil.InitScrollBoxWithScrollBar(self.ScrollBox, self.ScrollBar, self.ScrollView); | |
self.GeneratePageButton = CreateFrame("Button", nil, self, "UIPanelButtonTemplate"); | |
self.GeneratePageButton:SetPoint("TOP", self, "BOTTOM", 0, -20); | |
self.GeneratePageButton:SetText("Generate"); | |
self.GeneratePageButton:SetWidth(150); | |
self.GeneratePageButton:SetScript("OnClick", GenerateClosure(self.OnGeneratePageButtonClicked, self)); | |
end | |
function ScrollableContentFrameMixin:OnContentSizeChanged() | |
-- It's expected that OnSizeChanged is only fired when the content layout | |
-- frame has recalulated in a deferred manner via OnUpdate, so we can | |
-- update the scrollbox immediately without delaying it until the next | |
-- game tick. | |
self.ScrollBox:FullUpdate(ScrollBoxConstants.UpdateImmediately); | |
end | |
function ScrollableContentFrameMixin:OnGeneratePageButtonClicked() | |
self:GeneratePage(); | |
end | |
function ScrollableContentFrameMixin:GeneratePage() | |
self.ContentFrame:GeneratePage(); | |
end | |
--- | |
ScrollableContentFrame = Mixin(CreateFrame("Frame", nil, UIParent), ScrollableContentFrameMixin); | |
ScrollableContentFrame:SetPoint("CENTER"); | |
ScrollableContentFrame:SetSize(640, 480); | |
ScrollableContentFrame:OnLoad(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment