WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   Frame custom function (https://www.wowinterface.com/forums/showthread.php?t=59521)

Benalish 03-01-23 09:46 AM

Frame custom function
 
I created a template like this

Code:

<Frame name="My_GroupBox" toplevel="true" virtual="true">
                <Backdrop bgFile="Interface\ChatFrame\ChatFrameBackground" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
                        <BackgroundInsets>
                                <AbsInset left="3" right="3" top="5" bottom="3" />
                        </BackgroundInsets>
                        <TileSize>
                                <AbsValue val="16" />
                        </TileSize>
                        <EdgeSize>
                                <AbsValue val="16" />
                        </EdgeSize>
                        <Color r="0.1" g="0.1" b="0.1" a="0.5"/>
                        <BorderColor r="0.4" g="0.4" b="0.4"/>
                </Backdrop>
                <Layers>
                        <Layer level="OVERLAY">
                                <FontString parentKey="label" inherits="GameFontNormal" text="" justifyH="LEFT">
                                        <Anchors>
                                                <Anchor point="TOPLEFT" relativeTo="$parent" relativePoint="TOPLEFT">
                                                        <Offset>
                                                                <AbsDimension x="10" y="15"/>
                                                        </Offset>
                                                </Anchor>
                                        </Anchors>
                                </FontString>
                        </Layer>
                </Layers>
        </Frame>

Is it possible to assign functions to this template in this form?

Lua Code:
  1. My_GroupBox:myfunction(
  2.     -- do stuffs
  3. )

EDIT: Maybe this can be a solution?

Lua Code:
  1. local mt = {
  2.     myfunction = function(self)
  3.         -- do stuffs
  4.     end
  5. }
  6.  
  7. setmetatable(My_GroupBox, { __index = setmetatable(mt, getmetatable(My_GroupBox)) })

Fizzlemizz 03-01-23 12:23 PM

These days it would be done using a Mixin eg.
XML
Code:

<Button name="AchievementFullSearchResultsButtonTemplate" mixin="AchievementFullSearchResultsButtonMixin" virtual="true">
Lua

Lua Code:
  1. AchievementFullSearchResultsButtonMixin = {};
  2. function AchievementFullSearchResultsButtonMixin:Init(elementData)
  3.     -- ...
  4. end

This would "apply" any function defined in the AchievementFullSearchResultsButtonMixin table as a method of the button when the frame using the template is created.

Benalish 03-03-23 07:02 AM

Widget handlers instead, in a virtual template can be set in lua or only via xml?

Fizzlemizz 03-03-23 08:21 AM

I'm not sure I really understand the question but maybe the answer is, if you have just an OnLoad script in XML then you can set anything in that using lua including other SetScripts.

Benalish 03-03-23 09:53 AM

For the sake of clean code, I loaded the Lua scripts like this
Code:

<OnLoad>
    <Script file="luascript.lua"/>
    self:CreateList(self,total)
</OnLoad>

In this file I have set the custom methods but it keeps giving me this error:

attempt to call method 'CreateList' (a nil value)

Fizzlemizz 03-03-23 10:35 AM

the <Script file="luascript.lua"/> goes in the XML file before you add any <Frame .. tags etc.

self:CreateList wont exists unless the frame has a Mixin defined in lua, most likely in luascript.lua

luascript.lua
Code:

BenalishListSomethingFrameMixin = {}
function BenalishListSomethingFrameMixin:CreateList(total)
        print(self:GetName(), "Let's create a list of", total, "Entries!")
end

XML
Code:

<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\FrameXML\UI.xsd">
        <Script file="luascript.lua"/>
        <Frame name="BenalishListFrame", mixin="BenalishListSomethingFrameMixin", virtual="true">
                <Scripts>
                        <OnLoad>
                                self:CreateList(total)
                                -- I don't know where total comes from? You might want to retrieve that in the CreateList function instead!
                        </OnLoad>
                </Scripts>
        </Frame>
</Ui>


Benalish 03-03-23 12:26 PM

Works also in WotLK classic?

Fizzlemizz 03-03-23 12:39 PM

Should work in all versions.

SDPhantom 03-03-23 02:13 PM

You can use function or method attributes to refer to a Lua function.


This calls MyFrame_OnLoad() from the global environment.
Code:

<Scripts>
        <OnLoad function="MyFrame_OnLoad"/>
<Scripts>


This calls :OnLoad() from the frame's table. Useful for calling functions from inherited mixins.
Code:

<Scripts>
        <OnLoad method="OnLoad"/>
<Scripts>


For more information on handler tags, see WoWPedia: XML/Scripts.


PS: <Backdrop> tags are depreciated and no longer work. You need to inherit BackdropTemplate and call :SetBackdrop() with your custom backdrop.

Benalish 03-03-23 03:16 PM

Is it possible to do the same thing the old-fashioned way, using metatables?

Fizzlemizz 03-04-23 08:36 AM

I'm not sure what you mean by "the old-fashioned way" but I'm pretty sure it didn't use metatables. More likely, anything that needed to be run from XML or actioned the frame was defined as a global function.

SDPhantom 03-04-23 09:11 PM

The problem of templates is the template "class" you create doesn't exist as an object accessible by Lua. You need to create an OnLoad handler and register it for your template to call when instantiated. At that time, your handler is passed a reference to the instanced frame to act on.

What a mixin does is take an existing table and copy its contents into the instantiated frame's table, making every function defined by the mixin available immediately as a method of the frame.

Lua Code:
  1. MyTemplateMixin={};
  2.  
  3. function MyTemplateMixin:Init()
  4.     print(self:GetName());
  5. end

Code:

<Frame name="MyTemplate" mixin="MyTemplateMixin" virtual="true">
        <Scripts>
                <OnLoad method="Init"/>
        </Scripts>
</Frame>

<Frame name="MyTemplateFrame1" inherits="MyTemplate"/>

In this example, MyTemplate is defined as a template that loads MyTemplateMixin when instantiated. This function just prints the frame's name in chat as a test. A frame is then created using the template and is named MyTemplateFrame1. :Init() is then called as defined in the template with a reference to the newly created frame. This causes :Init() to print "MyTemplateFrame1" as that is this new frame's name.



Using metatables for templates has never been a thing. Historically, people have defined global functions and had frames call them. Even that was short-lived once the ability to create frames from Lua was implemented. XML has always been a pain for debugging and is rarely used anymore.


All times are GMT -6. The time now is 09:18 AM.

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