Skip to content

Instantly share code, notes, and snippets.

@Meorawr
Last active August 31, 2020 12:27
Show Gist options
  • Save Meorawr/b729f731aa1029ed46974b5b1e8e1390 to your computer and use it in GitHub Desktop.
Save Meorawr/b729f731aa1029ed46974b5b1e8e1390 to your computer and use it in GitHub Desktop.
SelectionPopoutButtonTemplate Demo
local function CreateSelectionModel(entries)
local selections = {};
for i = 1, entries do
selections[i] = {
-- `name` is the only required key. There is color swatch support too, but that's
-- probably not needed.
name = "Item " .. i,
-- Other keys can be created as needed and made available to OnEntryClick.
id = i,
foo = fastrandom(),
};
end
return selections;
end
-- AddOn_SelectionPopoutMixin
-- This mixin is intended to be used by a frame that contains a Blizzard
-- SelectionPopoutButton.
--
-- The SelectionPopoutButton template/mixin require specific behaviours be
-- provided by a parent frame in order to respond to selection changes,
-- user interaction, etc.
AddOn_SelectionPopoutMixin = {};
function AddOn_SelectionPopoutMixin:OnLoad()
-- If you decide to initialize a selection model in OnLoad logic, note that the selected index
-- passed as the second parameter to SetupSelections must be a valid index in the model.
local model = CreateSelectionModel(self.initialEntryCount or 1);
self:SetupSelections(model, 1);
end
function AddOn_SelectionPopoutMixin:HidePopout()
self.SelectionPopoutButton:HidePopout();
end
function AddOn_SelectionPopoutMixin:SetupSelections(selections, selectedIndex)
assert(type(selections) == "table", "selections must be a table");
assert(#selections > 0, "selections must not be an empty table");
assert(type(selectedIndex) == "number", "selectedIndex must be a number");
assert(selectedIndex > 0 and selectedIndex <= #selections, "selectedIndex must be within the range 1..#selections");
self.selections = selections;
self.selectedIndex = selectedIndex;
self.SelectionPopoutButton:SetupSelections(self.selections, self.selectedIndex);
end
function AddOn_SelectionPopoutMixin:GetMaxPopoutHeight()
-- No-op; required by the child SelectionPopoutButton or you'll get errors.
end
function AddOn_SelectionPopoutMixin:OnEnter()
-- No-op; required by the child SelectionPopoutButton or you'll get errors.
end
function AddOn_SelectionPopoutMixin:OnLeave()
-- No-op; required by the child SelectionPopoutButton or you'll get errors.
end
function AddOn_SelectionPopoutMixin:OnPopoutShown()
-- No-op; this _isn't_ required by the child SelectionPopoutButton.
CallMethodOnNearestAncestor(self, "HidePopouts", self);
end
function AddOn_SelectionPopoutMixin:OnEntryClick(item)
-- `item` will be the selected items' table ref from from our model.
print("Selected item:", item.id, item.name, item.foo);
-- Setting up selections again lets us change the selected index to reflect the users' choice.
self:SetupSelections(self.selections, tIndexOf(self.selections, item));
-- The default behaviour when an entry is clicked doesn't hide the popout; this needs to be
-- done manually.
self:HidePopout();
end
-- AddOn_SelectionHostMixin
--
-- This mixin is intended to be used by any frame that contains a set of
-- popout frames to provide support for hiding all popout widgets except
-- the actively shown one based upon user input (such as opening another,
-- or clicking in the game world).
AddOn_SelectionHostMixin = {};
function AddOn_SelectionHostMixin:OnLoad()
self:RegisterEvent("GLOBAL_MOUSE_DOWN");
self:RegisterEvent("GLOBAL_MOUSE_UP");
end
function AddOn_SelectionHostMixin:OnEvent(event, ...)
if event == "GLOBAL_MOUSE_DOWN" or event == "GLOBAL_MOUSE_UP" then
local buttonID = ...;
local frame = GetMouseFocus();
if frame and frame.HandlesGlobalMouseEvent and frame:HandlesGlobalMouseEvent(buttonID, event) then
return;
end
self:HidePopouts();
end
end
function AddOn_SelectionHostMixin:HidePopouts(exemptPopout)
-- This assumes that `self.popouts` contains all child popout frames.
for _, frame in ipairs(self.popouts) do
if frame ~= exemptPopout then
frame:HidePopout();
end
end
end
<Ui>
<Script file="AddOn_SelectionPopoutDemo.lua"/>
<Frame name="AddOn_SelectionPopoutTemplate" virtual="true" mixin="AddOn_SelectionPopoutMixin">
<Frames>
<Button parentKey="SelectionPopoutButton" inherits="SelectionPopoutButtonTemplate" setAllPoints="true"/>
</Frames>
<Scripts>
<OnLoad method="OnLoad"/>
</Scripts>
</Frame>
<Frame name="AddOn_SelectionHostFrame" parent="UIParent" mixin="AddOn_SelectionHostMixin" toplevel="true">
<Size x="150" y="156"/>
<Anchors>
<Anchor point="CENTER"/>
</Anchors>
<Frames>
<Frame parentKey="PopoutFrameSmall" parentArray="popouts" inherits="AddOn_SelectionPopoutTemplate">
<KeyValues>
<KeyValue key="initialEntryCount" value="10" type="number"/>
</KeyValues>
<Size x="150" y="38"/>
<Anchors>
<Anchor point="CENTER" y="76"/>
</Anchors>
</Frame>
<Frame parentKey="PopoutFrameMedium" parentArray="popouts" inherits="AddOn_SelectionPopoutTemplate">
<KeyValues>
<KeyValue key="initialEntryCount" value="20" type="number"/>
</KeyValues>
<Size x="150" y="38"/>
<Anchors>
<Anchor point="CENTER" y="38"/>
</Anchors>
</Frame>
<Frame parentKey="PopoutFrameLarge" parentArray="popouts" inherits="AddOn_SelectionPopoutTemplate">
<KeyValues>
<KeyValue key="initialEntryCount" value="30" type="number"/>
</KeyValues>
<Size x="150" y="38"/>
<Anchors>
<Anchor point="CENTER" y="0"/>
</Anchors>
</Frame>
<Frame parentKey="PopoutFrameHuge" parentArray="popouts" inherits="AddOn_SelectionPopoutTemplate">
<KeyValues>
<KeyValue key="initialEntryCount" value="40" type="number"/>
</KeyValues>
<Size x="150" y="38"/>
<Anchors>
<Anchor point="CENTER" y="-38"/>
</Anchors>
</Frame>
</Frames>
<Scripts>
<OnLoad method="OnLoad"/>
<OnEvent method="OnEvent"/>
</Scripts>
</Frame>
</Ui>
@Meorawr
Copy link
Author

Meorawr commented Aug 29, 2020

WowB_2020-08-29_23-03-29
WowB_2020-08-29_23-03-40

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment