1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  3. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still haven't received your rank award? Then please contact the administration.
    Dismiss Notice
  4. Let your favorite entries duke it out in the 15th Techtree Contest Poll.
    Dismiss Notice
  5. Weave light to take you to your highest hopes - the 6th Special Effect Contest is here!
    Dismiss Notice
  6. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

TasButtonList

Submitted by Tasyen
This bundle is marked as pending. It has not been reviewed by a staff member yet.

Introduction


TasButtonList is a UI-Frame Resource written in Lua (got a (v)jass version), it displays data to a fixed amount of clickable buttons. The idea was to create a System, you feed with data and behaviour, while the UI-Part one has to do (as mapper) is quite low.

Features

Create any amount of TasButtonList at the same Time.
Builtin in are 3 Variations of a ButtonList (1 per row, 2 and 3 per Row)
The currently displayed content can be scrolled.
With search by text one can change the current relevant fraction of data.
customizeable to adapt to custom data.
one can set a custom filter additional to the search by text

How to Install

First you have to export and import the 2 Files in the demo map (using the export all Files function can bug in older Editor Versions).

war3mapImported\TasButtonList.fdf
war3mapImported\TasButtonList.toc​
Now you copy TasButtonList (trigger editor) into your map
if all worked, you can now use it.

  • Examples


    Creates a ButtonList with 8 Buttons, using Unit-RawCodes as data. Which are on default quite well supported.
    When a player clicks a Button the data currently pointed at by that Button is created for the clicking Player at the map center.
    Code (Lua):
    TimerStart(CreateTimer(), 0.0, false, function()
        xpcall(function()
        -- create an empty Frame that will be the ButtonLists parent. if you want to hide/move the ButtonList hide/move the parent.
        local frame = BlzCreateFrameByType("FRAME", "", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0,0)
        BlzFrameSetSize(frame, 0.23, 0.001)
        BlzFrameSetAbsPoint(frame, FRAMEPOINT_TOP, 0.6, 0.5)
        -- create a new ButtonList with 8 Rows, frame is the parent and define the action when clicking the Button
        local object = CreateTasButtonList(8, frame, function(data, buttonListObject, dataIndex)
            -- create an unit for the clicking player at 0/0 with facing 0
             CreateUnit(GetTriggerPlayer(), data, 0, 0, 0)
        end)

        -- add various data
        TasButtonListAddData(object, FourCC("Hpal"))
        TasButtonListAddData(object, FourCC("Hblm"))
        TasButtonListAddData(object, FourCC("hfoo"))
        TasButtonListAddData(object, FourCC("hkni"))
        TasButtonListAddData(object, FourCC("hdhw"))
        TasButtonListAddData(object, FourCC("hmpr"))
        TasButtonListAddData(object, FourCC("hsor"))
        TasButtonListAddData(object, FourCC("hrif"))
        TasButtonListAddData(object, FourCC("Ofar"))
        TasButtonListAddData(object, FourCC("ogru"))
        TasButtonListAddData(object, FourCC("orai"))
        -- force an update
        UpdateTasButtonList(object)
        print("done")
    end, print)
    end)
    displaying custom Data.
    Code (Lua):

    TimerStart(CreateTimer(), 0.0, false, function()
        xpcall(function()
        -- create an empty Frame that will be the ButtonLists parent. if you want to hide/move the ButtonList hide/move the parent.
        local frame = BlzCreateFrameByType("FRAME", "", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0,0)
        BlzFrameSetSize(frame, 0.23, 0.001)
        BlzFrameSetAbsPoint(frame, FRAMEPOINT_TOP, 0.6, 0.5)
        -- create a new ButtonList with 4 Rows, frame is the parent and define the action when clicking the Button
        local object = CreateTasButtonList(4, frame, function(data, buttonListObject, dataIndex)
            print(data.Icon, data.Text)
        end,
        function(frameObject, data)
            BlzFrameSetTexture(frameObject.Icon, data.Icon, 0, false)
            BlzFrameSetText(frameObject.Text, data.Text)
            BlzFrameSetTexture(frameObject.ToolTipFrameIcon, data.Icon, 0, false)
            BlzFrameSetText(frameObject.ToolTipFrameName, data.Text)
        end)

        -- add various data
        TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNPriest", Text = "Custom A"})
        TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNSlow", Text = "Custom B"})
        TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNInvisibility", Text = "Custom C"})
        TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNBanish", Text = "Custom D"})
        TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNCrystalBall", Text = "Custom E"})
        TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNBoots", Text = "Custom F"})
        TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNTalisman", Text = "Custom G"})
        -- force an update
        UpdateTasButtonList(object)
        print("done")
    end, print)
    end)
    There are more examples but for them you need to download the demo map.

    Source code
    Code (Lua):


    --[[
    TasButtonList7 by Tasyen

    function CreateTasButtonList(buttonCount, parent, buttonAction, updateAction, searchAction, filterAction)
     create a new List
     parent is the container of this Frame it will attach itself to its TOP.
     buttonAction is the function that executes when an option is clicked. args: (clickedData, buttonListObject, dataIndex)
     when your data are unit-RawCodes then you can skip updateAction & searchAction.
     updateAction runs for each Button and is used to set the diplayed content. args:(frameObject, data)
        frameObject.Button
        frameObject.ToolTipFrame
        frameObject.ToolTipFrameIcon
        frameObject.ToolTipFrameName
        frameObject.ToolTipFrameSeperator
        frameObject.ToolTipFrameText

        frameObject.Icon
        frameObject.Text
        frameObject.IconGold
        frameObject.TextGold
        frameObject.IconLumber
        frameObject.TextLumber
        TasButtonList[frameObject] => buttonListObject

        data is one entry of the TasButtonLists Data-Array.

     searchAction is a function that returns true if the current data matches the searchText. Args: (data, searchedText, buttonListObject)
     filterAction is meant to be used when one wants an addtional non text based filtering, with returning true allowing data or false rejecting it. Args: (data, buttonListObject, isTextSearching)
     searchAction , udateAction & filterAction are async this functions should not do anything that alters the game state/flow.

    function CreateTasButtonListV2(rowCount, parent, buttonAction, updateAction, searchAction, filterAction)
        2 Buttons each Row, takes more Height then the other Versions
    function CreateTasButtonListV3(rowCount, parent, buttonAction, updateAction, searchAction, filterAction)
        3 Buttons each Row, only Icon, and Costs

    function TasButtonListClearData(buttonListObject)
        remove all data
    function TasButtonListRemoveData(buttonListObject, data)
        search for data and remove it
    function TasButtonListAddData(buttonListObject, data)
        add data for one Button
    function TasButtonListCopyData(writeObject, readObject)
        writeObject uses the same data as readObject and calls UpdateButtonList.
    function UpdateTasButtonList(buttonListObject)
        update the displayed Content should be done after Data was added or removed was used.
    TasButtonListSearch(buttonListObject[, text])
        The buttonList will search it's data for the given text, if nil is given as text it will search for what the user currently has in its box.
        This will also update the buttonList
    --]]


    BlzLoadTOCFile("war3mapimported\\TasButtonList.toc")
    TasButtonList = {}

    TasButtonList.SyncTrigger = CreateTrigger()
    TasButtonList.SyncTriggerAction = TriggerAddAction(TasButtonList.SyncTrigger, function()
        xpcall(function()
        local buttonListObject = TasButtonList[BlzGetTriggerFrame()]
        local dataIndex = math.tointeger(BlzGetTriggerFrameValue())

        if buttonListObject.ButtonAction then
            -- call the wanted action, 1 the current Data
            buttonListObject.ButtonAction(buttonListObject.Data[dataIndex], buttonListObject, dataIndex)
        end
        UpdateTasButtonList(buttonListObject)
        end,print)
    end)

    -- handles the clicking
    TasButtonList.ButtonTrigger = CreateTrigger()
    TasButtonList.ButtonTriggerAction = TriggerAddAction(TasButtonList.ButtonTrigger, function()
        local buttonIndex = TasButtonList[BlzGetTriggerFrame()].Index
        local buttonListObject = TasButtonList[TasButtonList[BlzGetTriggerFrame()]]
        local dataIndex = buttonListObject.DataFiltered[buttonListObject.ViewPoint + buttonIndex]
        BlzFrameSetEnable(BlzGetTriggerFrame(), false)
        BlzFrameSetEnable(BlzGetTriggerFrame(), true)
        if GetLocalPlayer() == GetTriggerPlayer() then
            BlzFrameSetValue(buttonListObject.SyncFrame, dataIndex)
        end
    end)

    TasButtonList.SearchTrigger = CreateTrigger()
    TasButtonList.SearchTriggerAction = TriggerAddAction(TasButtonList.SearchTrigger, function()
        TasButtonListSearch(TasButtonList[BlzGetTriggerFrame()], BlzFrameGetText(BlzGetTriggerFrame()))
    end)

    -- scrolling while pointing on Buttons
    TasButtonList.ButtonScrollTrigger = CreateTrigger()
    TasButtonList.ButtonScrollTriggerAction = TriggerAddAction(TasButtonList.ButtonScrollTrigger, function()
        local buttonListObject = TasButtonList[TasButtonList[BlzGetTriggerFrame()]]
        local frame = buttonListObject.Slider
        if GetLocalPlayer() == GetTriggerPlayer() then
            if BlzGetTriggerFrameValue() > 0 then
                BlzFrameSetValue(frame, BlzFrameGetValue(frame) + buttonListObject.SliderStep)
            else
                BlzFrameSetValue(frame, BlzFrameGetValue(frame) - buttonListObject.SliderStep)
            end
        end
    end)

    -- scrolling while pointing on slider aswell as calling
    TasButtonList.SliderTrigger = CreateTrigger()
    TasButtonList.SliderTriggerAction = TriggerAddAction(TasButtonList.SliderTrigger, function()
        local buttonListObject = TasButtonList[BlzGetTriggerFrame()]
        local frame = BlzGetTriggerFrame()
        if GetLocalPlayer() == GetTriggerPlayer() then
            if BlzGetTriggerFrameEvent() == FRAMEEVENT_MOUSE_WHEEL then
                if BlzGetTriggerFrameValue() > 0 then
                    BlzFrameSetValue(frame, BlzFrameGetValue(frame) + buttonListObject.SliderStep)
                else
                    BlzFrameSetValue(frame, BlzFrameGetValue(frame) - buttonListObject.SliderStep)
                end
            else
                buttonListObject.ViewPoint = math.tointeger(BlzGetTriggerFrameValue())
                UpdateTasButtonList(buttonListObject)
            end
        end
    end)

    --runs once for each button shown
    function UpdateTasButtonListDefaultObject(frameObject, data)
        BlzFrameSetTexture(frameObject.Icon, BlzGetAbilityIcon(data), 0, false)
        BlzFrameSetText(frameObject.Text, GetObjectName(data))

        BlzFrameSetTexture(frameObject.ToolTipFrameIcon, BlzGetAbilityIcon(data), 0, false)
        BlzFrameSetText(frameObject.ToolTipFrameName, GetObjectName(data))      
    --        frameObject.ToolTipFrameSeperator
        BlzFrameSetText(frameObject.ToolTipFrameText, BlzGetAbilityExtendedTooltip(data, 0))

        if not IsUnitIdType(data, UNIT_TYPE_HERO) then
            local lumber = GetUnitWoodCost(data)
            local gold = GetUnitGoldCost(data)
            if GetPlayerState(GetLocalPlayer(), PLAYER_STATE_RESOURCE_GOLD) >= gold then
                BlzFrameSetText(frameObject.TextGold, GetUnitGoldCost(data))
            else
                BlzFrameSetText(frameObject.TextGold, "|cffff2010"..GetUnitGoldCost(data))
            end    
           
            if GetPlayerState(GetLocalPlayer(), PLAYER_STATE_RESOURCE_LUMBER) >= lumber then
                BlzFrameSetText(frameObject.TextLumber, GetUnitWoodCost(data))
            else
                BlzFrameSetText(frameObject.TextLumber, "|cffff2010"..GetUnitWoodCost(data))
            end
        else
            BlzFrameSetText(frameObject.TextLumber, 0)
            BlzFrameSetText(frameObject.TextGold, 0)
        end
    end

    function SearchTasButtonListDefaultObject(data, searchedText, buttonListObject)
        --return BlzGetAbilityTooltip(data, 0)
        --return GetObjectName(data, 0)
        return string.find(GetObjectName(data), searchedText)
    end

    -- update the shown content
    function UpdateTasButtonList(buttonListObject)
        xpcall(function()
        local data = buttonListObject.Data
        BlzFrameSetVisible(buttonListObject.Slider, #buttonListObject.DataFiltered > #buttonListObject.Frames)
        for int = 1, #buttonListObject.Frames do
            local frameObject = buttonListObject.Frames[int]
            if #buttonListObject.DataFiltered >= int  then
                buttonListObject.UpdateAction(frameObject, data[buttonListObject.DataFiltered[int + buttonListObject.ViewPoint]])
                BlzFrameSetVisible(frameObject.Button, true)
            else
                BlzFrameSetVisible(frameObject.Button, false)
            end
        end
    end, print)
    end

    function InitTasButtonListObject(parent, buttonAction, updateAction, searchAction, filterAction)
        local object = {
            Data = {}, --an array each slot is the user data
            DataFiltered = {}, -- indexes of Data fitting the current search
            ViewPoint = 0,
            Frames = {},
            Parent = parent
        }
        object.ButtonAction = buttonAction --call this inside the SyncAction after a button is clicked
        object.UpdateAction = updateAction --function defining how to display stuff (async)
        object.SearchAction = searchAction --function to return the searched Text (async)
        object.FilterAction = filterAction --
        if not updateAction then object.UpdateAction = UpdateTasButtonListDefaultObject end
        if not searchAction then object.SearchAction = SearchTasButtonListDefaultObject end
        table.insert(TasButtonList, object) --index to TasButtonList
        TasButtonList[object] = #TasButtonList -- TasButtonList to Index

        object.SyncFrame = BlzCreateFrameByType("SLIDER", "", parent, "", 0)
        BlzFrameSetMinMaxValue(object.SyncFrame, 0, 9999999)
        BlzFrameSetStepSize(object.SyncFrame, 1.0)
        BlzTriggerRegisterFrameEvent(TasButtonList.SyncTrigger, object.SyncFrame, FRAMEEVENT_SLIDER_VALUE_CHANGED)
        BlzFrameSetVisible(object.SyncFrame, false)
        TasButtonList[object.SyncFrame] = object

        object.InputFrame = BlzCreateFrame("TasEditBox", parent, 0, 0)
        BlzTriggerRegisterFrameEvent(TasButtonList.SearchTrigger, object.InputFrame, FRAMEEVENT_EDITBOX_TEXT_CHANGED)
        BlzFrameSetPoint(object.InputFrame, FRAMEPOINT_TOPRIGHT, parent, FRAMEPOINT_TOPRIGHT, 0, 0)
        TasButtonList[object.InputFrame] = object

        return object
    end

    function InitTasButtonListSlider(object, stepSize, rowCount)
        object.Slider = BlzCreateFrameByType("SLIDER", "FrameListSlider", object.Parent, "QuestMainListScrollBar", 0)
        TasButtonList[object.Slider] = object -- the slider nows the TasButtonListobject
        object.SliderStep = stepSize
        BlzFrameSetStepSize(object.Slider, stepSize)
        BlzFrameClearAllPoints(object.Slider)
        BlzFrameSetVisible(object.Slider, true)
        BlzFrameSetMinMaxValue(object.Slider, 0, 0)
        BlzFrameSetPoint(object.Slider, FRAMEPOINT_TOPLEFT, object.Frames[1].Button, FRAMEPOINT_TOPRIGHT, 0, 0)
        BlzFrameSetSize(object.Slider, 0.012, BlzFrameGetHeight(object.Frames[1].Button) * rowCount)
        BlzTriggerRegisterFrameEvent(TasButtonList.SliderTrigger, object.Slider , FRAMEEVENT_SLIDER_VALUE_CHANGED)
        BlzTriggerRegisterFrameEvent(TasButtonList.SliderTrigger, object.Slider , FRAMEEVENT_MOUSE_WHEEL)
    end

    function CreateTasButtonList(buttonCount, parent, buttonAction, updateAction, searchAction, filterAction)
        local object = InitTasButtonListObject(parent, buttonAction, updateAction, searchAction, filterAction)  

        for int = 1, buttonCount do
            local frameObject = {}
            frameObject.Index = int
            frameObject.Button = BlzCreateFrame("TasButton", parent, 0, 0)
            frameObject.ToolTipFrame = BlzCreateFrame("TasButtonListTooltipBox", frameObject.Button, 0, 0)
            frameObject.ToolTipFrameIcon = BlzGetFrameByName("TasButtonListTooltipIcon", 0)
            frameObject.ToolTipFrameName = BlzGetFrameByName("TasButtonListTooltipName", 0)
            frameObject.ToolTipFrameSeperator = BlzGetFrameByName("TasButtonListTooltipSeperator", 0)
            frameObject.ToolTipFrameText = BlzGetFrameByName("TasButtonListTooltipText", 0)    
            BlzFrameSetPoint(frameObject.ToolTipFrame, FRAMEPOINT_TOPRIGHT, parent, FRAMEPOINT_TOPLEFT, -0.001, 0)
            BlzFrameSetTooltip(frameObject.Button, frameObject.ToolTipFrame)

            frameObject.Icon = BlzGetFrameByName("TasButtonIcon", 0)
            frameObject.Text = BlzGetFrameByName("TasButtonText", 0)
            frameObject.IconGold = BlzGetFrameByName("TasButtonIconGold", 0)
            frameObject.TextGold = BlzGetFrameByName("TasButtonTextGold", 0)
            frameObject.IconLumber = BlzGetFrameByName("TasButtonIconLumber", 0)
            frameObject.TextLumber = BlzGetFrameByName("TasButtonTextLumber", 0)
            TasButtonList[frameObject.Button] = frameObject
            TasButtonList[frameObject] = object
            table.insert(object.Frames, frameObject)
            BlzTriggerRegisterFrameEvent(TasButtonList.ButtonTrigger, frameObject.Button, FRAMEEVENT_CONTROL_CLICK)
            BlzTriggerRegisterFrameEvent(TasButtonList.ButtonScrollTrigger, frameObject.Button, FRAMEEVENT_MOUSE_WHEEL)
            if int > 1 then
               BlzFrameSetPoint(frameObject.Button, FRAMEPOINT_TOP, object.Frames[int - 1].Button, FRAMEPOINT_BOTTOM, 0, -0)
            else
                BlzFrameSetPoint(frameObject.Button, FRAMEPOINT_TOPRIGHT, object.InputFrame, FRAMEPOINT_BOTTOMRIGHT, 0, 0)
            end
        end
        InitTasButtonListSlider(object, 1, buttonCount)

        return object
    end

    function CreateTasButtonListV2(rowCount, parent, buttonAction, updateAction, searchAction, filterAction)
        local buttonCount = rowCount*2
        local object = InitTasButtonListObject(parent, buttonAction, updateAction, searchAction, filterAction)

        local rowEnd = false
        for int = 1, buttonCount do
            local frameObject = {}
            frameObject.Index = int
            frameObject.Button = BlzCreateFrame("TasButtonSmall", parent, 0, 0)
            frameObject.ToolTipFrame = BlzCreateFrame("TasButtonListTooltipBox", frameObject.Button, 0, 0)
            frameObject.ToolTipFrameIcon = BlzGetFrameByName("TasButtonListTooltipIcon", 0)
            frameObject.ToolTipFrameName = BlzGetFrameByName("TasButtonListTooltipName", 0)
            frameObject.ToolTipFrameSeperator = BlzGetFrameByName("TasButtonListTooltipSeperator", 0)
            frameObject.ToolTipFrameText = BlzGetFrameByName("TasButtonListTooltipText", 0)    
            BlzFrameSetPoint(frameObject.ToolTipFrame, FRAMEPOINT_TOPRIGHT, parent, FRAMEPOINT_TOPLEFT, -0.001, 0)
            BlzFrameSetTooltip(frameObject.Button, frameObject.ToolTipFrame)

            frameObject.Icon = BlzGetFrameByName("TasButtonSmallIcon", 0)
            frameObject.Text = BlzGetFrameByName("TasButtonSmallText", 0)
            frameObject.IconGold = BlzGetFrameByName("TasButtonSmallIconGold", 0)
            frameObject.TextGold = BlzGetFrameByName("TasButtonSmallTextGold", 0)
            frameObject.IconLumber = BlzGetFrameByName("TasButtonSmallIconLumber", 0)
            frameObject.TextLumber = BlzGetFrameByName("TasButtonSmallTextLumber", 0)
            TasButtonList[frameObject.Button] = frameObject
            TasButtonList[frameObject] = object
            table.insert(object.Frames, frameObject)
            BlzTriggerRegisterFrameEvent(TasButtonList.ButtonTrigger, frameObject.Button, FRAMEEVENT_CONTROL_CLICK)
            BlzTriggerRegisterFrameEvent(TasButtonList.ButtonScrollTrigger, frameObject.Button, FRAMEEVENT_MOUSE_WHEEL)
            rowEnd = not rowEnd
            if int > 1 then
                if rowEnd then
                    BlzFrameSetPoint(frameObject.Button, FRAMEPOINT_TOP, object.Frames[int - 2].Button, FRAMEPOINT_BOTTOM, 0, -0)
                else
                    BlzFrameSetPoint(frameObject.Button, FRAMEPOINT_RIGHT, object.Frames[int - 1].Button, FRAMEPOINT_LEFT, 0, -0)
                end
            else
                BlzFrameSetPoint(frameObject.Button, FRAMEPOINT_TOPRIGHT, object.InputFrame, FRAMEPOINT_BOTTOMRIGHT, 0, 0)            
            end
           
        end
        InitTasButtonListSlider(object, 2, rowCount)

        return object
    end

    function CreateTasButtonListV3(rowCount, parent, buttonAction, updateAction, searchAction, filterAction)
        local buttonCount = rowCount*3
        local object = InitTasButtonListObject(parent, buttonAction, updateAction, searchAction, filterAction)

        local rowRemain = 3
        for int = 1, buttonCount do
            local frameObject = {}
            frameObject.Index = int
            frameObject.Button = BlzCreateFrame("TasButtonGrid", parent, 0, 0)
            frameObject.ToolTipFrame = BlzCreateFrame("TasButtonListTooltipBox", frameObject.Button, 0, 0)
            frameObject.ToolTipFrameIcon = BlzGetFrameByName("TasButtonListTooltipIcon", 0)
            frameObject.ToolTipFrameName = BlzGetFrameByName("TasButtonListTooltipName", 0)
            frameObject.ToolTipFrameSeperator = BlzGetFrameByName("TasButtonListTooltipSeperator", 0)
            frameObject.ToolTipFrameText = BlzGetFrameByName("TasButtonListTooltipText", 0)    
            BlzFrameSetPoint(frameObject.ToolTipFrame, FRAMEPOINT_TOPRIGHT, parent, FRAMEPOINT_TOPLEFT, -0.001, 0)
            BlzFrameSetTooltip(frameObject.Button, frameObject.ToolTipFrame)

            frameObject.Icon = BlzGetFrameByName("TasButtonGridIcon", 0)
            frameObject.Text = BlzGetFrameByName("TasButtonGridText", 0)
            frameObject.IconGold = BlzGetFrameByName("TasButtonGridIconGold", 0)
            frameObject.TextGold = BlzGetFrameByName("TasButtonGridTextGold", 0)
            frameObject.IconLumber = BlzGetFrameByName("TasButtonGridIconLumber", 0)
            frameObject.TextLumber = BlzGetFrameByName("TasButtonGridTextLumber", 0)
            TasButtonList[frameObject.Button] = frameObject
            TasButtonList[frameObject] = object
            table.insert(object.Frames, frameObject)
            BlzTriggerRegisterFrameEvent(TasButtonList.ButtonTrigger, frameObject.Button, FRAMEEVENT_CONTROL_CLICK)
            BlzTriggerRegisterFrameEvent(TasButtonList.ButtonScrollTrigger, frameObject.Button, FRAMEEVENT_MOUSE_WHEEL)
           
            if int > 1 then
                if rowRemain == 0 then
                    BlzFrameSetPoint(frameObject.Button, FRAMEPOINT_TOP, object.Frames[int - 3].Button, FRAMEPOINT_BOTTOM, 0, -0)
                    rowRemain = 3
                else
                    BlzFrameSetPoint(frameObject.Button, FRAMEPOINT_RIGHT, object.Frames[int - 1].Button, FRAMEPOINT_LEFT, 0, -0)
                end
            else
                BlzFrameSetPoint(frameObject.Button, FRAMEPOINT_TOPRIGHT, object.InputFrame, FRAMEPOINT_BOTTOMRIGHT, 0, 0)            
            end
            rowRemain = rowRemain - 1
        end
        InitTasButtonListSlider(object, 3, rowCount)

        return object
    end

    function TasButtonListAddData(buttonListObject, data)
        table.insert( buttonListObject.Data, data)
        table.insert( buttonListObject.DataFiltered, #buttonListObject.Data)
        BlzFrameSetMinMaxValue(buttonListObject.Slider, 0, #buttonListObject.Data - (#buttonListObject.Frames + 0))
    end

    function TasButtonListRemoveData(buttonListObject, data)
        local found = false
        for index, value in ipairs(buttonListObject.Data)
        do
            if value == data then
                table.remove(buttonListObject.Data, index)
                found = true
                break
            end
        end
        BlzFrameSetMinMaxValue(buttonListObject.Slider, 0, #buttonListObject.Data - (#buttonListObject.Frames + 0))
    end

    function TasButtonListClearData(buttonListObject)
        repeat until not table.remove(buttonListObject.Data)
        repeat until not table.remove(buttonListObject.DataFiltered)
        BlzFrameSetMinMaxValue(buttonListObject.Slider, 0, 0)
    end

    function TasButtonListCopyData(writeObject, readObject)
        writeObject.Data = readObject.Data
        repeat until not table.remove(writeObject.DataFiltered)
        for index, value in ipairs(readObject.DataFiltered) do table.insert( writeObject.DataFiltered, value) end
        BlzFrameSetMinMaxValue(writeObject.Slider, 0, #writeObject.Data - (#writeObject.Frames + 0))
        UpdateTasButtonList(writeObject)
    end

    function TasButtonListSearch(buttonListObject, text)
        if not text then text = BlzFrameGetText(buttonListObject.InputFrame) end
        local filteredData = buttonListObject.DataFiltered
       
        if GetLocalPlayer() == GetTriggerPlayer() then
            repeat do end until not table.remove(filteredData)
            if text ~= "" then
                for index, value in ipairs(buttonListObject.Data)
                do
                    if buttonListObject.SearchAction(value, text, buttonListObject) and (not buttonListObject.FilterAction or buttonListObject.FilterAction(value, buttonListObject, true)) then
                        table.insert(filteredData, index)
                    end
                end
               
            else
                for index, value in ipairs(buttonListObject.Data)
                do
                    if not buttonListObject.FilterAction or buttonListObject.FilterAction(value, buttonListObject, false) then
                        table.insert(filteredData, index)
                    end
                end
            end
            --table.sort(filteredData, function(a, b) return GetObjectName(buttonListObject.Data[a]) < GetObjectName(buttonListObject.Data[b]) end  )

            --update Slider, with that also update
            BlzFrameSetMinMaxValue(buttonListObject.Slider, 0, math.max(#filteredData - (#buttonListObject.Frames + 0),0))
            BlzFrameSetValue(buttonListObject.Slider, 0)
        end
    end
     

  • The jass version uses library String from MaskedPoptart.

    Example:
    Creates a ButtonList with 8 Buttons, using Unit-RawCodes as data. Which are on default quite well supported.
    When a player clicks a Button the data currently pointed at by that Button is created for the clicking Player at the map center.
    Code (vJASS):

    library SomeTest initializer init_function requires TasButtonList
    private function OnClick takes nothing returns nothing
            // create an unit for the clicking player at 0/0 with facing 0
            call CreateUnit(GetTriggerPlayer(), TasButtonListData, 0, 0, 0)
    endfunction
    private function test takes nothing returns nothing
        // create an empty Frame that will be the ButtonLists parent. if you want to hide/move the ButtonList hide/move the parent.
        local framehandle frame = BlzCreateFrameByType("FRAME", "", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "",0)
        local integer objectIndex = CreateTasButtonList(8, frame, function OnClick, null,null,null)
        call BlzFrameSetSize(frame, 0.23, 0.001)
        call BlzFrameSetAbsPoint(frame, FRAMEPOINT_TOP, 0.6, 0.5)
     
        // add various data
        call TasButtonListAddData(objectIndex, 'Hpal')
        call TasButtonListAddData(objectIndex, 'Hblm')
        call TasButtonListAddData(objectIndex, 'hfoo')
        call TasButtonListAddData(objectIndex, 'hkni')
        call TasButtonListAddData(objectIndex, 'hdhw')
        call TasButtonListAddData(objectIndex, 'hmpr')
        call TasButtonListAddData(objectIndex, 'hsor')
        call TasButtonListAddData(objectIndex, 'hrif')
        call TasButtonListAddData(objectIndex, 'Ofar')
        call TasButtonListAddData(objectIndex, 'ogru')
        call TasButtonListAddData(objectIndex, 'orai')
        // force an update
        call UpdateTasButtonList(objectIndex)
     
        call DestroyTimer(GetExpiredTimer())
    endfunction
        private function init_function takes nothing returns nothing
           call TimerStart(CreateTimer(), 0.0, false, function test)
        endfunction
    endlibrary

    Shows how one could handle custom Data in the (v)jass version. The data is stored in arrays then one adds the indexes of the wanted data into the ButtonList.
    when using custom data one also needs to set the update & search action, additional to the buttonAction.
    Without the update function the buttons will show nonsense and without a search action the user can not search the data.
    Code (vJASS):

    library SomeTest initializer init_function requires TasButtonList
    globals
     
        private string array Icon
        private string array Text
    endglobals
    private function OnClick takes nothing returns nothing
        call BJDebugMsg(I2S(TasButtonListData) + " "+ Text[TasButtonListData])
    endfunction
    private function OnSearch takes nothing returns boolean
        return FindIndex(Text[TasButtonListData], TasButtonListText) >= 0
    endfunction
    private function OnUpdate takes nothing returns nothing
        local integer dataIndex = TasButtonListData
        local integer frameHandle = GetHandleId(TasButtonListFrame)
        call BlzFrameSetTexture(LoadFrameHandle(TasButtonList_Hash, frameHandle, StringHash("Icon")), Icon[dataIndex], 0, false)
        call BlzFrameSetText(LoadFrameHandle(TasButtonList_Hash, frameHandle, StringHash("Text")), Text[dataIndex])
        call BlzFrameSetTexture(LoadFrameHandle(TasButtonList_Hash, frameHandle, StringHash("ToolTipFrameIcon")), Icon[dataIndex], 0, false)
        call BlzFrameSetText(LoadFrameHandle(TasButtonList_Hash, frameHandle, StringHash("ToolTipFrameName")), Text[dataIndex])
    endfunction

    private function test takes nothing returns nothing
        // create an empty Frame that will be the ButtonLists parent. if you want to hide/move the ButtonList hide/move the parent.
     
        local framehandle frame = BlzCreateFrameByType("FRAME", "", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "",0)
     
        local integer objectIndex = CreateTasButtonList(3, frame, function OnClick, function OnUpdate, function OnSearch, null)
        call BlzFrameSetSize(frame, 0.23, 0.001)
        call BlzFrameSetAbsPoint(frame, FRAMEPOINT_TOP, 0.6, 0.5)
            set Icon[1] = "ReplaceableTextures\\CommandButtons\\BTNPriest"
            set Text[1] = "Custom A"
            set Icon[2] = "ReplaceableTextures\\CommandButtons\\BTNSlow"
            set Text[2] = "Custom B"
            set Icon[3] = "ReplaceableTextures\\CommandButtons\\BTNInvisibility"
            set Text[3] = "Custom C"
            set Icon[4] = "ReplaceableTextures\\CommandButtons\\BTNBanish"
            set Text[4] = "Custom D"
            set Icon[5] = "ReplaceableTextures\\CommandButtons\\BTNCrystalBall"
            set Text[5] = "Custom E"
            set Icon[6] = "ReplaceableTextures\\CommandButtons\\BTNBoots"
            set Text[6] = "Custom F"
            set Icon[7] = "ReplaceableTextures\\CommandButtons\\BTNTalisman"
            set Text[7] = "Custom G"
            call TasButtonListAddData(objectIndex, 1)
            call TasButtonListAddData(objectIndex, 2)
            call TasButtonListAddData(objectIndex, 3)
            call TasButtonListAddData(objectIndex, 4)
            call TasButtonListAddData(objectIndex, 5)
            call TasButtonListAddData(objectIndex, 6)
     
        // force an update
        call UpdateTasButtonList(objectIndex)
     
        call DestroyTimer(GetExpiredTimer())
     
    endfunction
        private function init_function takes nothing returns nothing
       
           call TimerStart(CreateTimer(), 0.0, false, function test)
             // this adds an checkbox, when the checkbox is checked only heroes are valid search targets
     
     
        endfunction
    endlibrary
     

    Source Code
    Code (vJASS):

    native GetUnitGoldCost takes integer rawCode returns integer
    native GetUnitWoodCost takes integer rawCode returns integer

    library TasButtonList initializer Init uses String
    // TasButtonList7 by Tasyen

    //function CreateTasButtonList takes integer buttonCount, framehandle parent, code buttonAction, code updateAction, code searchAction, code filterAction returns integer
     //create a new List
     //parent is the container of this Frame it will attach itself to its TOP.
     //the given functions are called over Triggers
     //buttonAction is the function that executes when an option is clicked.
     //when your data are unit-RawCodes then you can skip updateAction & searchAction.
     //updateAction runs for each Button and is used to set the diplayed content.

     //searchAction is a function that returns true if the current data matches the searchText.
     //filterAction is meant to be used when one wants an addtional non text based filtering, with returning true allowing data or false rejecting it.
     //searchAction , udateAction & filterAction are async this functions should not do anything that alters the game state/flow.

    //function CreateTasButtonListV2 takes integer rowCount, framehandle parent, code buttonAction, code updateAction, code searchAction, code filterAction returns integer
      //  2 Buttons each Row, takes more Height then the other Versions
    //function CreateTasButtonListV3 takes integer rowCount, framehandle parent, code buttonAction, code updateAction, code searchAction, code filterAction returns integer
      //  3 Buttons each Row, only Icon, and Costs

    //function TasButtonListClearData takes integer listIndex returns nothing
      //  remove all data
    //function TasButtonListRemoveData takes integer listIndex, integer data returns nothing
      //  search for data and remove it
    //function TasButtonListAddData takes integer listIndex, integer data returns nothing
      //  add data for one Button
    //function TasButtonListCopyData takes integer writeObject, integer readObject returns nothing
      //  writeObject uses the same data as readObject and calls UpdateButtonList.
    //function UpdateTasButtonList takes integer listIndex returns nothing
      //  update the displayed Content should be done after Data was added or removed was used.
    //function TasButtonListSearch takes integer listIndex, string text returns nothing
        // The buttonList will search it's data for the given text, if nil is given as text it will search for what the user currently has in its box.
        // This will also update the buttonList

    globals
        //args for custom user actions
        integer TasButtonListData = 0
        string TasButtonListText = ""
        boolean TasButtonListIsSearching = false
        integer TasButtonListIndex = 0
        framehandle TasButtonListFrame = null

        // System
        public hashtable Hash = InitHashtable()
        private integer Counter = 0 //amount of Lists created, each index is one List
        private trigger SyncTrigger = CreateTrigger()
        private trigger ButtonTrigger = CreateTrigger()
        private trigger SearchTrigger = CreateTrigger()
        private trigger ButtonScrollTrigger = CreateTrigger()
        private trigger SliderTrigger = CreateTrigger()
        private integer HASH_TOOL_TIP = StringHash("ToolTipFrame")
        private integer HASH_TOOL_TIP_ICON = StringHash("ToolTipFrameIcon")
        private integer HASH_TOOL_TIP_NAME = StringHash("ToolTipFrameName")
        private integer HASH_TOOL_TIP_SEP = StringHash("ToolTipFrameSeperator")
        private integer HASH_TOOL_TIP_TEXT = StringHash("ToolTipFrameText")
        private integer HASH_ICON = StringHash("Icon")
        private integer HASH_TEXT = StringHash("Text")
        private integer HASH_ICON_GOLD = StringHash("IconGold")
        private integer HASH_TEXT_GOLD = StringHash("TextGold")
        private integer HASH_ICON_LUMBER = StringHash("IconLumber")
        private integer HASH_TEXT_LUMBER = StringHash("TextLumber")

        // ButtonLists
        framehandle array TasButtonListSlider
        framehandle array TasButtonListParent
        framehandle array TasButtonListInputFrame
        framehandle array TasButtonListSyncFrame
        integer array TasButtonListButtonCount
        integer array TasButtonListStepSize
        trigger array TasButtonListButtonAction
        trigger array TasButtonListUpdateAction
        trigger array TasButtonListSearchAction
        trigger array TasButtonListFilterAction    
        integer array TasButtonListViewPoint
        location array TasButtonListDataList
        location array TasButtonListDataListFiltered
        location array TasButtonListFrameList

       

    endglobals


    // update the shown content
    function UpdateTasButtonList takes integer listIndex returns nothing
        local integer dataHash = GetHandleId(TasButtonListDataList[listIndex])
        local integer frameListHash = GetHandleId(TasButtonListFrameList[listIndex])
        local integer filteredDataHash = GetHandleId(TasButtonListDataListFiltered[listIndex])
        local integer dataFilteredCount = LoadInteger(Hash, filteredDataHash, 0)
       
        local integer i = 1

        call BlzFrameSetVisible(TasButtonListSlider[listIndex], dataFilteredCount > TasButtonListButtonCount[listIndex])
        loop
            exitwhen i > TasButtonListButtonCount[listIndex]
            set TasButtonListFrame = LoadFrameHandle(Hash, frameListHash, i)
           
            if dataFilteredCount >= i  then
                set TasButtonListData = LoadInteger(Hash, dataHash, LoadInteger(Hash, filteredDataHash, i + TasButtonListViewPoint[listIndex]))
                call TriggerEvaluate(TasButtonListUpdateAction[listIndex])
                call BlzFrameSetVisible(TasButtonListFrame, true)
            else
                call BlzFrameSetVisible(TasButtonListFrame, false)
            endif
            set i = i + 1
        endloop

    endfunction

    function TasButtonListSearch takes integer listIndex, string text returns nothing
        local integer filteredDataHash = GetHandleId(TasButtonListDataListFiltered[listIndex])
        local integer dataHash = GetHandleId(TasButtonListDataList[listIndex])
        local integer filteredDataCount
       
        local integer i
        local integer iEnd
        if text == null or text == "" then
            set text = BlzFrameGetText(TasButtonListInputFrame[listIndex])
        endif
        if GetLocalPlayer() == GetTriggerPlayer() then
            set TasButtonListText = text
            set TasButtonListIndex = listIndex
            call FlushChildHashtable(Hash, filteredDataHash)
            set filteredDataCount = 0
            if text != "" then
                set TasButtonListIsSearching = true
                set iEnd = LoadInteger(Hash, dataHash, 0)
                set i = 1
                loop
                    exitwhen i > iEnd
                    set TasButtonListData = LoadInteger(Hash, dataHash, i)
                    if TriggerEvaluate(TasButtonListSearchAction[listIndex]) and TriggerEvaluate(TasButtonListFilterAction[listIndex]) then
                        set filteredDataCount = filteredDataCount + 1
                        call SaveInteger(Hash, filteredDataHash, filteredDataCount, i)
                    endif
                    set i = i + 1
                endloop
                call SaveInteger(Hash, filteredDataHash, 0, filteredDataCount)
            else
                set TasButtonListIsSearching = false
                set iEnd = LoadInteger(Hash, dataHash, 0)
                set i = 1
                loop
                    exitwhen i > iEnd
                    set TasButtonListData = LoadInteger(Hash, dataHash, i)
                    if TriggerEvaluate(TasButtonListFilterAction[listIndex]) then
                        set filteredDataCount = filteredDataCount + 1
                        call SaveInteger(Hash, filteredDataHash, filteredDataCount, i)
                    endif
                    set i = i + 1
                endloop
                call SaveInteger(Hash, filteredDataHash, 0, filteredDataCount)
            endif
           

            //update Slider, with that also update
            call BlzFrameSetMinMaxValue(TasButtonListSlider[listIndex], 0, IMaxBJ(filteredDataCount - (TasButtonListButtonCount[listIndex] + 0),0))
            call BlzFrameSetValue(TasButtonListSlider[listIndex], 0)
        endif
    endfunction

    function TasButtonListTriggerActionSync takes nothing returns nothing
        local integer listIndex = LoadInteger(Hash, GetHandleId(BlzGetTriggerFrame()), 0)
        local integer dataIndex = R2I(BlzGetTriggerFrameValue() + 0.5)
       
        set TasButtonListData = LoadInteger(Hash, GetHandleId(TasButtonListDataList[listIndex]), dataIndex)
        set TasButtonListIndex = listIndex
        call TriggerExecute(TasButtonListButtonAction[listIndex])

        call UpdateTasButtonList(listIndex)
    endfunction

    function TasButtonListTriggerActionButton takes nothing returns nothing
        local integer buttonIndex = LoadInteger(Hash, GetHandleId(BlzGetTriggerFrame()), 1)
        local integer listIndex = LoadInteger(Hash, GetHandleId(BlzGetTriggerFrame()), 0)
        local integer dataIndex = LoadInteger(Hash, GetHandleId(TasButtonListDataListFiltered[listIndex]), buttonIndex + TasButtonListViewPoint[listIndex])
        call BlzFrameSetEnable(BlzGetTriggerFrame(), false)
        call BlzFrameSetEnable(BlzGetTriggerFrame(), true)
        if GetLocalPlayer() == GetTriggerPlayer() then
           call BlzFrameSetValue(TasButtonListSyncFrame[listIndex], dataIndex)
        endif
    endfunction

    function TasButtonListTriggerActionSearch takes nothing returns nothing
        call TasButtonListSearch(LoadInteger(Hash, GetHandleId(BlzGetTriggerFrame()), 0), null)
    endfunction

    // scrolling while pointing on Buttons
    function TasButtonListTriggerActionButtonScroll takes nothing returns nothing
        local integer listIndex = LoadInteger(Hash, GetHandleId(BlzGetTriggerFrame()), 0)
        local framehandle frame = TasButtonListSlider[listIndex]

        if GetLocalPlayer() == GetTriggerPlayer() then
            if BlzGetTriggerFrameValue() > 0 then
                call BlzFrameSetValue(frame, BlzFrameGetValue(frame) + TasButtonListStepSize[listIndex])
            else
                call BlzFrameSetValue(frame, BlzFrameGetValue(frame) - TasButtonListStepSize[listIndex])
            endif
        endif
        set frame = null
    endfunction

    // scrolling while pointing on slider aswell as calling
    function TasButtonListTriggerActionSlider takes nothing returns nothing
        local integer listIndex = LoadInteger(Hash, GetHandleId(BlzGetTriggerFrame()), 0)
        local framehandle frame = BlzGetTriggerFrame()
        if GetLocalPlayer() == GetTriggerPlayer() then
            if BlzGetTriggerFrameEvent() == FRAMEEVENT_MOUSE_WHEEL then
                if BlzGetTriggerFrameValue() > 0 then
                    call BlzFrameSetValue(frame, BlzFrameGetValue(frame) + TasButtonListStepSize[listIndex])
                else
                    call BlzFrameSetValue(frame, BlzFrameGetValue(frame) - TasButtonListStepSize[listIndex])
                endif
            else
                set TasButtonListViewPoint[listIndex] = R2I(BlzGetTriggerFrameValue())
                call UpdateTasButtonList(listIndex)
            endif
        endif
        set frame = null
    endfunction

    // runs once for each button shown
    function UpdateTasButtonListDefaultObject takes nothing returns nothing
    //TasButtonListFrame
    //TasButtonListData
    //TasButtonListIndex
        local integer frameHandle = GetHandleId(TasButtonListFrame)
        local integer data = TasButtonListData
        local integer lumber
        local integer gold
     
        call BlzFrameSetTexture(LoadFrameHandle(Hash, frameHandle, HASH_ICON),  BlzGetAbilityIcon(data), 0, false)
        call BlzFrameSetText(LoadFrameHandle(Hash, frameHandle, HASH_TEXT), GetObjectName(data))

        call BlzFrameSetTexture(LoadFrameHandle(Hash, frameHandle, HASH_TOOL_TIP_ICON), BlzGetAbilityIcon(data), 0, false)
        call BlzFrameSetText(LoadFrameHandle(Hash, frameHandle, HASH_TOOL_TIP_NAME), GetObjectName(data))
        call BlzFrameSetText(LoadFrameHandle(Hash, frameHandle, HASH_TOOL_TIP_TEXT), BlzGetAbilityExtendedTooltip(data, 0))

        if not IsUnitIdType(data, UNIT_TYPE_HERO) then
            // GetUnitWoodCost GetUnitGoldCost CRASH with heroes
            set lumber = GetUnitWoodCost(data)
            set gold = GetUnitGoldCost(data)
            if GetPlayerState(GetLocalPlayer(), PLAYER_STATE_RESOURCE_GOLD) >= gold then
                call BlzFrameSetText(LoadFrameHandle(Hash, frameHandle, HASH_TEXT_GOLD), I2S(GetUnitGoldCost(data)))
            else
                call BlzFrameSetText(LoadFrameHandle(Hash, frameHandle, HASH_TEXT_GOLD), "|cffff2010" + I2S(GetUnitGoldCost(data)))
            endif
           
            if GetPlayerState(GetLocalPlayer(), PLAYER_STATE_RESOURCE_LUMBER) >= lumber then
               call BlzFrameSetText(LoadFrameHandle(Hash, frameHandle, HASH_TEXT_LUMBER), I2S(GetUnitWoodCost(data)))
            else
               call BlzFrameSetText(LoadFrameHandle(Hash, frameHandle, HASH_TEXT_LUMBER), "|cffff2010" + I2S(GetUnitWoodCost(data)))
            endif
        else
            call BlzFrameSetText(LoadFrameHandle(Hash, frameHandle, HASH_TEXT_LUMBER), "0")
            call BlzFrameSetText(LoadFrameHandle(Hash, frameHandle, HASH_TEXT_GOLD), "0")
        endif
    endfunction

    function SearchTasButtonListDefaultObject takes nothing returns boolean
    //TasButtonListText
    //TasButtonListData
    //TasButtonListIndex
        return FindIndex(GetObjectName(TasButtonListData), TasButtonListText) >= 0
    endfunction


    function InitTasButtonListObject takes framehandle parent, code buttonAction, code updateAction, code searchAction, code filterAction returns integer
        local framehandle frame
        set Counter = Counter + 1
        // the locations are created to have an unique slot in the hash which are used as something like a Lua table.
        set TasButtonListDataList[Counter] = Location(0, 0) //
        set TasButtonListDataListFiltered[Counter] = Location(0, 0) //
        set TasButtonListFrameList[Counter] = Location(0, 0) //
        set TasButtonListParent[Counter] = parent
        set TasButtonListViewPoint[Counter] = 0

        set TasButtonListButtonAction[Counter] = CreateTrigger() //call this inside the SyncAction after a button is clicked
        set TasButtonListUpdateAction[Counter] = CreateTrigger() //function defining how to display stuff (async)
        set TasButtonListFilterAction[Counter] = CreateTrigger() //function to return the searched Text (async)
        set TasButtonListSearchAction[Counter] = CreateTrigger()
        call TriggerAddAction(TasButtonListButtonAction[Counter], buttonAction)
       
        // update is a condition with it can be run with TriggerEvaluate in localPlayer code. TriggerExecute would desync
        if updateAction == null then
            call TriggerAddCondition(TasButtonListUpdateAction[Counter], Filter(function UpdateTasButtonListDefaultObject))
        else
            call TriggerAddCondition(TasButtonListUpdateAction[Counter], Filter(updateAction))
        endif

        if searchAction == null then
            call TriggerAddCondition(TasButtonListSearchAction[Counter], Filter(function SearchTasButtonListDefaultObject))
        else
            call TriggerAddCondition(TasButtonListSearchAction[Counter], Filter(searchAction))
        endif
        if filterAction != null then
            call TriggerAddCondition(TasButtonListFilterAction[Counter], Filter(filterAction))
        endif
       
        set frame = BlzCreateFrameByType("SLIDER", "", parent, "", 0)
        set TasButtonListSyncFrame[Counter] = frame
        call BlzFrameSetMinMaxValue(frame, 0, 9999999)
        call BlzFrameSetStepSize(frame, 1.0)
        call BlzTriggerRegisterFrameEvent(SyncTrigger, frame, FRAMEEVENT_SLIDER_VALUE_CHANGED)
        call BlzFrameSetVisible(frame, false)
        call SaveInteger(Hash, GetHandleId(frame), 0, Counter)

        set frame = BlzCreateFrame("TasEditBox", parent, 0, 0)
        set TasButtonListInputFrame[Counter] = frame
        call BlzTriggerRegisterFrameEvent(SearchTrigger, frame, FRAMEEVENT_EDITBOX_TEXT_CHANGED)
        call BlzFrameSetPoint(frame, FRAMEPOINT_TOPRIGHT, parent, FRAMEPOINT_TOPRIGHT, 0, 0)
        call SaveInteger(Hash, GetHandleId(frame), 0, Counter)

        set frame = null
        return Counter
    endfunction

    function InitTasButtonListSlider takes integer listIndex, integer stepSize, integer rowCount returns nothing
        local framehandle frame = BlzCreateFrameByType("SLIDER", "FrameListSlider", TasButtonListParent[listIndex], "QuestMainListScrollBar", 0)
        local framehandle buttonFrame = LoadFrameHandle(Hash, GetHandleId(TasButtonListFrameList[listIndex]), 1)
        set TasButtonListSlider[listIndex] = frame
        call SaveInteger(Hash, GetHandleId(frame), 0, listIndex) // the slider nows the TasButtonListobject
        set TasButtonListStepSize[listIndex] = stepSize
       
        call BlzFrameSetStepSize(frame, stepSize)
        call BlzFrameClearAllPoints(frame)
        call BlzFrameSetVisible(frame, true)
        call BlzFrameSetMinMaxValue(frame, 0, 0)
        call BlzFrameSetPoint(frame, FRAMEPOINT_TOPLEFT, buttonFrame, FRAMEPOINT_TOPRIGHT, 0, 0)
        call BlzFrameSetSize(frame, 0.012, BlzFrameGetHeight(buttonFrame) * rowCount)
        call BlzTriggerRegisterFrameEvent(SliderTrigger, frame , FRAMEEVENT_SLIDER_VALUE_CHANGED)
        call BlzTriggerRegisterFrameEvent(SliderTrigger, frame , FRAMEEVENT_MOUSE_WHEEL)
    endfunction

    function CreateTasButtonList takes integer buttonCount, framehandle parent, code buttonAction, code updateAction, code searchAction, code filterAction returns integer
        local integer listIndex = InitTasButtonListObject(parent, buttonAction, updateAction, searchAction, filterAction)  
        local integer i = 1
        local integer frameListHash = GetHandleId(TasButtonListFrameList[listIndex])
        local framehandle frame
        local framehandle frameButton
        local integer frameHandle    

        set TasButtonListButtonCount[listIndex] = buttonCount
        loop
            exitwhen i > buttonCount
           
            set frame = BlzCreateFrame("TasButton", parent, 0, 0)
            set frameHandle = GetHandleId(frame)
            call SaveFrameHandle(Hash, frameListHash, i, frame)
            call SaveInteger(Hash, frameHandle, 0, listIndex) // the button knows the TasButtonListIndex
            call SaveInteger(Hash, frameHandle, 1, i) // the button knows its index in the frameList
            call BlzTriggerRegisterFrameEvent(ButtonTrigger, frame, FRAMEEVENT_CONTROL_CLICK)
            call BlzTriggerRegisterFrameEvent(ButtonScrollTrigger, frame, FRAMEEVENT_MOUSE_WHEEL)
            set frameButton = frame

            call SaveFrameHandle(Hash, frameHandle, HASH_ICON, BlzGetFrameByName("TasButtonIcon", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TEXT, BlzGetFrameByName("TasButtonText", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_ICON_GOLD, BlzGetFrameByName("TasButtonIconGold", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TEXT_GOLD, BlzGetFrameByName("TasButtonTextGold", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_ICON_LUMBER, BlzGetFrameByName("TasButtonIconLumber", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TEXT_LUMBER, BlzGetFrameByName("TasButtonTextLumber", 0))

            set frame = BlzCreateFrame("TasButtonListTooltipBox", frameButton, 0, 0)

            call SaveFrameHandle(Hash, frameHandle, HASH_TOOL_TIP, frame)
            call SaveFrameHandle(Hash, frameHandle, HASH_TOOL_TIP_ICON, BlzGetFrameByName("TasButtonListTooltipIcon", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TOOL_TIP_NAME, BlzGetFrameByName("TasButtonListTooltipName", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TOOL_TIP_SEP, BlzGetFrameByName("TasButtonListTooltipSeperator", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TOOL_TIP_TEXT, BlzGetFrameByName("TasButtonListTooltipText", 0))

            call BlzFrameSetPoint(frame, FRAMEPOINT_TOPRIGHT, parent, FRAMEPOINT_TOPLEFT, -0.001, 0)
            call BlzFrameSetTooltip(frameButton, frame)        
           
            if i > 1 then
               call BlzFrameSetPoint(frameButton, FRAMEPOINT_TOP, LoadFrameHandle(Hash, frameListHash, i - 1), FRAMEPOINT_BOTTOM, 0, -0)
            else
                call BlzFrameSetPoint(frameButton, FRAMEPOINT_TOPRIGHT, TasButtonListInputFrame[listIndex], FRAMEPOINT_BOTTOMRIGHT, 0, 0)
            endif
            set i = i + 1
        endloop
        call InitTasButtonListSlider(listIndex, 1, buttonCount)
        set frame = null
        set frameButton = null
        return listIndex
    endfunction

    function CreateTasButtonListV2 takes integer rowCount, framehandle parent, code buttonAction, code updateAction, code searchAction, code filterAction returns integer
        local integer buttonCount = rowCount*2
        local integer listIndex = InitTasButtonListObject(parent, buttonAction, updateAction, searchAction, filterAction)  
        local integer i = 1
        local integer frameListHash = GetHandleId(TasButtonListFrameList[listIndex])
        local framehandle frame
        local framehandle frameButton
        local integer frameHandle
        local boolean rowEnd = false
        set TasButtonListButtonCount[listIndex] = buttonCount
        loop
            exitwhen i > buttonCount
           
            set frame = BlzCreateFrame("TasButtonSmall", parent, 0, 0)
            set frameHandle = GetHandleId(frame)
            call SaveFrameHandle(Hash, frameListHash, i, frame)
            call SaveInteger(Hash, frameHandle, 0, listIndex) // the button knows the TasButtonListIndex
            call SaveInteger(Hash, frameHandle, 1, i) // the button knows its index in the frameList
            call BlzTriggerRegisterFrameEvent(ButtonTrigger, frame, FRAMEEVENT_CONTROL_CLICK)
            call BlzTriggerRegisterFrameEvent(ButtonScrollTrigger, frame, FRAMEEVENT_MOUSE_WHEEL)
            set frameButton = frame

            call SaveFrameHandle(Hash, frameHandle, HASH_ICON, BlzGetFrameByName("TasButtonSmallIcon", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TEXT, BlzGetFrameByName("TasButtonSmallText", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_ICON_GOLD, BlzGetFrameByName("TasButtonSmallIconGold", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TEXT_GOLD, BlzGetFrameByName("TasButtonSmallTextGold", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_ICON_LUMBER, BlzGetFrameByName("TasButtonSmallIconLumber", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TEXT_LUMBER, BlzGetFrameByName("TasButtonSmallTextLumber", 0))

            set frame = BlzCreateFrame("TasButtonListTooltipBox", frameButton, 0, 0)

            call SaveFrameHandle(Hash, frameHandle, HASH_TOOL_TIP, frame)
            call SaveFrameHandle(Hash, frameHandle, HASH_TOOL_TIP_ICON, BlzGetFrameByName("TasButtonListTooltipIcon", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TOOL_TIP_NAME, BlzGetFrameByName("TasButtonListTooltipName", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TOOL_TIP_SEP, BlzGetFrameByName("TasButtonListTooltipSeperator", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TOOL_TIP_TEXT, BlzGetFrameByName("TasButtonListTooltipText", 0))

            call BlzFrameSetPoint(frame, FRAMEPOINT_TOPRIGHT, parent, FRAMEPOINT_TOPLEFT, -0.001, 0)
            call BlzFrameSetTooltip(frameButton, frame)        
           
            set rowEnd = not rowEnd
            if i > 1 then
                if rowEnd then
                    call BlzFrameSetPoint(frameButton, FRAMEPOINT_TOP, LoadFrameHandle(Hash, frameListHash, i - 2), FRAMEPOINT_BOTTOM, 0, -0)
                else
                    call BlzFrameSetPoint(frameButton, FRAMEPOINT_RIGHT, LoadFrameHandle(Hash, frameListHash, i - 1), FRAMEPOINT_LEFT, 0, -0)
                endif
            else
                call BlzFrameSetPoint(frameButton, FRAMEPOINT_TOPRIGHT, TasButtonListInputFrame[listIndex], FRAMEPOINT_BOTTOMRIGHT, 0, 0)
            endif

            set i = i + 1
        endloop
        call InitTasButtonListSlider(listIndex, 2, rowCount)
        set frame = null
        set frameButton = null
        return listIndex
    endfunction

    function CreateTasButtonListV3 takes integer rowCount, framehandle parent, code buttonAction, code updateAction, code searchAction, code filterAction returns integer
        local integer buttonCount = rowCount*3
        local integer listIndex = InitTasButtonListObject(parent, buttonAction, updateAction, searchAction, filterAction)  
        local integer i = 1
        local integer frameListHash = GetHandleId(TasButtonListFrameList[listIndex])
        local framehandle frame
        local framehandle frameButton
        local integer frameHandle

        local integer rowRemain = 3
        set TasButtonListButtonCount[listIndex] = buttonCount
        loop
            exitwhen i > buttonCount
           
            set frame = BlzCreateFrame("TasButtonGrid", parent, 0, 0)
            set frameHandle = GetHandleId(frame)
            call SaveFrameHandle(Hash, frameListHash, i, frame)
            call SaveInteger(Hash, frameHandle, 0, listIndex) // the button knows the TasButtonListIndex
            call SaveInteger(Hash, frameHandle, 1, i) // the button knows its index in the frameList
            call BlzTriggerRegisterFrameEvent(ButtonTrigger, frame, FRAMEEVENT_CONTROL_CLICK)
            call BlzTriggerRegisterFrameEvent(ButtonScrollTrigger, frame, FRAMEEVENT_MOUSE_WHEEL)
            set frameButton = frame

            call SaveFrameHandle(Hash, frameHandle, HASH_ICON, BlzGetFrameByName("TasButtonGridIcon", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TEXT, BlzGetFrameByName("TasButtonGridText", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_ICON_GOLD, BlzGetFrameByName("TasButtonGridIconGold", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TEXT_GOLD, BlzGetFrameByName("TasButtonGridTextGold", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_ICON_LUMBER, BlzGetFrameByName("TasButtonGridIconLumber", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TEXT_LUMBER, BlzGetFrameByName("TasButtonGridTextLumber", 0))

            set frame = BlzCreateFrame("TasButtonListTooltipBox", frameButton, 0, 0)

            call SaveFrameHandle(Hash, frameHandle, HASH_TOOL_TIP, frame)
            call SaveFrameHandle(Hash, frameHandle, HASH_TOOL_TIP_ICON, BlzGetFrameByName("TasButtonListTooltipIcon", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TOOL_TIP_NAME, BlzGetFrameByName("TasButtonListTooltipName", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TOOL_TIP_SEP, BlzGetFrameByName("TasButtonListTooltipSeperator", 0))
            call SaveFrameHandle(Hash, frameHandle, HASH_TOOL_TIP_TEXT, BlzGetFrameByName("TasButtonListTooltipText", 0))

            call BlzFrameSetPoint(frame, FRAMEPOINT_TOPRIGHT, parent, FRAMEPOINT_TOPLEFT, -0.001, 0)
            call BlzFrameSetTooltip(frameButton, frame)        
           

            if i > 1 then
                if rowRemain == 0 then
                    call BlzFrameSetPoint(frameButton, FRAMEPOINT_TOP, LoadFrameHandle(Hash, frameListHash, i - 3), FRAMEPOINT_BOTTOM, 0, -0)
                    set rowRemain = 3
                else
                    call BlzFrameSetPoint(frameButton, FRAMEPOINT_RIGHT, LoadFrameHandle(Hash, frameListHash, i - 1), FRAMEPOINT_LEFT, 0, -0)
                endif
            else
                call BlzFrameSetPoint(frameButton, FRAMEPOINT_TOPRIGHT, TasButtonListInputFrame[listIndex], FRAMEPOINT_BOTTOMRIGHT, 0, 0)
            endif
            set rowRemain = rowRemain - 1


            set i = i + 1
        endloop
        call InitTasButtonListSlider(listIndex, 3, rowCount)
        set frame = null
        set frameButton = null
        return listIndex
    endfunction

    function TasButtonListAddData takes integer listIndex, integer data returns nothing
        local integer listHandle = GetHandleId(TasButtonListDataList[listIndex])
        local integer index = LoadInteger(Hash, listHandle, 0) + 1
        call SaveInteger(Hash, listHandle, 0, index)
        call SaveInteger(Hash, listHandle, index, data)
        set listHandle = GetHandleId(TasButtonListDataListFiltered[listIndex])
        call SaveInteger(Hash, listHandle, 0, index)
        call SaveInteger(Hash, listHandle, index, index)
        call BlzFrameSetMinMaxValue(TasButtonListSlider[listIndex], 0, IMaxBJ(index - (TasButtonListButtonCount[listIndex] + 0),0))
    endfunction

    function TasButtonListCopyData takes integer writeObject, integer readObject returns nothing
        local integer i = LoadInteger(Hash, GetHandleId(TasButtonListDataListFiltered[readObject]), 0)
        local integer listHandleRead = GetHandleId(TasButtonListDataListFiltered[readObject])
        local integer listHandleWrite = GetHandleId(TasButtonListDataListFiltered[writeObject])
        call FlushChildHashtable(Hash, GetHandleId(TasButtonListDataList[writeObject]))
        call RemoveLocation(TasButtonListDataList[writeObject])
        set TasButtonListDataList[writeObject] = TasButtonListDataList[readObject]
        loop
            exitwhen i < 0
            call SaveInteger(Hash, listHandleWrite, i, LoadInteger(Hash, listHandleRead, i))
            set i = i -1
        endloop
       
        call BlzFrameSetMinMaxValue(TasButtonListSlider[writeObject], 0, IMaxBJ(LoadInteger(Hash, listHandleRead, 0) - (TasButtonListButtonCount[writeObject] + 0),0))
        call UpdateTasButtonList(writeObject)
    endfunction


    function TasButtonListRemoveData takes integer listIndex, integer data returns nothing
        local integer listHandle = GetHandleId(TasButtonListDataList[listIndex])
        local integer i = LoadInteger(Hash, listHandle, 0)
        local integer max = LoadInteger(Hash, listHandle, 0)
        local integer temp
        loop
            exitwhen i <= 0
            if LoadInteger(Hash, listHandle, 0) == data then
                call SaveInteger(Hash, listHandle, i, LoadInteger(Hash, listHandle, max))
                call RemoveSavedInteger(Hash, listHandle, max)
                exitwhen true
            endif
            set i = i - 1
        endloop
        call BlzFrameSetMinMaxValue(TasButtonListSlider[listIndex], 0, IMaxBJ(LoadInteger(Hash, listHandle, 0) - (TasButtonListButtonCount[listIndex] + 0),0))
    endfunction

    function TasButtonListClearData takes integer listIndex returns nothing
        call FlushChildHashtable(Hash, GetHandleId(TasButtonListDataList[listIndex]))
        call FlushChildHashtable(Hash, GetHandleId(TasButtonListDataListFiltered[listIndex]))
        call BlzFrameSetMinMaxValue(TasButtonListSlider[listIndex], 0, 0)
    endfunction

     private function Init takes nothing returns nothing    
        call BlzLoadTOCFile("war3mapimported\\TasButtonList.toc")
        call TriggerAddAction(SyncTrigger, function TasButtonListTriggerActionSync)
        call TriggerAddAction(ButtonTrigger, function TasButtonListTriggerActionButton)
        call TriggerAddAction(SearchTrigger, function TasButtonListTriggerActionSearch)
        call TriggerAddAction(ButtonScrollTrigger, function TasButtonListTriggerActionButtonScroll)
        call TriggerAddAction(SliderTrigger, function TasButtonListTriggerActionSlider)
       


    endfunction

    endlibrary
     


There are some differences between the (v)jass & Lua version.
in the jass version the mapper's actions are run over triggers, hence there are globals instead of args.
"" """""" The Button is the frameObject instead of being a member of it.
""""" every TasButtonList is one Index in an array.
""""" data used in TasButtonList is only integer.
"""" accessing the Frames is ugly.​

Changelog


V7
One can now force a list to search & filter
The Slider should now only show when there is more data than buttons​
V6
replaced BlzSendSyncData with a SLIDER
removed some wrong arguments or when they were to much mostly GetObjectName and BlzFrameCreateByType.
Added a (v)jass version​
V5 First Release
Previews
Contents

TasButtonListV7 (Map)

TasButtonListV7 jass (Map)

  1. Kain88

    Kain88

    Joined:
    May 26, 2020
    Messages:
    5
    Resources:
    0
    Resources:
    0
    Come on GUI or Jass version=)
     
  2. imek

    imek

    Joined:
    Aug 18, 2016
    Messages:
    42
    Resources:
    0
    Resources:
    0
    Brilliant! Super helpful. I got it to work too! Thank you Tasyen! Now I just need to study it and learn how you made it.
     
  3. imek

    imek

    Joined:
    Aug 18, 2016
    Messages:
    42
    Resources:
    0
    Resources:
    0
    Question: how to i get the Button List to close out and then Open a different Button List depending on which button I click on?

    Example:

    TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\PASHolyNovaHD.dds", Text = "Wizard"})
    TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNSlow", Text = "Custom B"})
    TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNInvisibility", Text = "Custom C"})
    TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNBanish", Text = "Custom D"})
    TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNCrystalBall", Text = "Custom E"})
    TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNBoots", Text = "Custom F"})
    TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNTalisman", Text = "Custom G"})

    If I click on the Wizard button I want to go to the Units under that category.
     
  4. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,557
    Resources:
    18
    Tools:
    2
    Maps:
    3
    Spells:
    8
    Tutorials:
    4
    JASS:
    1
    Resources:
    18
    To show hide a TasButtonList one uses BlzFrameSetVisible onto the ButtonLists Parent, at least it is meant to be handled that way. The buttonslist knows their parent: can be done like that
    BlzFrameSetVisible(buttonListObject.Parent, false)


    Now you have to set the buttonAction as wanted when creating the ButtonList:
    inside the buttonAction somehow know that the wanted Button showing that data is clicked, here I check for data.Text == "Wizard" then show/hide the parents of the buttonsLists for the triggering player only.
    Code (Lua):

    local object = CreateTasButtonList(4, frame, function(data, buttonListObject, dataIndex)
            if data.Text == "Wizard" and GetTriggerPlayer() == GetLocalPlayer() then
                BlzFrameSetVisible(buttonListObject.Parent, false)
                BlzFrameSetVisible(otherButtonList.Parent, true)
            end
        end)
     
    This example will shows only the concept of showing hiding, might be easier to understand than the now longer example below:

    Code (Lua):


    TimerStart(CreateTimer(), 0.0, false, function()
        xpcall(function()
        -- create an empty Frame that will be the ButtonLists parent. if you want to hide/move the ButtonList hide/move the parent.
        local frame = BlzCreateFrameByType("FRAME", "", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0,0)
        BlzFrameSetSize(frame, 0.23, 0.001)
        BlzFrameSetAbsPoint(frame, FRAMEPOINT_TOP, 0.6, 0.5)
        -- create a new ButtonList with 4 Rows, frame is the parent and define the action when clicking the Button
        local object = CreateTasButtonList(3, frame, function(data, buttonListObject, dataIndex)
            if data.Text == "Wizard" and GetTriggerPlayer() == GetLocalPlayer() then
                BlzFrameSetVisible(buttonListObject.Parent, false)
                BlzFrameSetVisible(WizardButtonList.Parent, true)
            end
        end,
        function(frameObject, data)
            BlzFrameSetTexture(frameObject.Icon, data.Icon, 0, false)
            BlzFrameSetText(frameObject.Text, data.Text)

            BlzFrameSetTexture(frameObject.ToolTipFrameIcon, data.Icon, 0, false)
            BlzFrameSetText(frameObject.ToolTipFrameName, data.Text)
        end)
        -- add various data
        TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNPriest", Text = "Wizard"})
        TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNSlow", Text = "Custom B"})
        TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNInvisibility", Text = "Custom C"})

        MainList = object
        UpdateTasButtonList(object)
     
        local frame = BlzCreateFrameByType("FRAME", "", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0,0)
        BlzFrameSetSize(frame, 0.23, 0.001)
        BlzFrameSetAbsPoint(frame, FRAMEPOINT_TOP, 0.6, 0.5)
        BlzFrameSetVisible(frame, false)
        -- create a new ButtonList with 4 Rows, frame is the parent and define the action when clicking the Button
        local object = CreateTasButtonList(2, frame, function(data, buttonListObject, dataIndex)
            if data.Text == "Back" and GetTriggerPlayer() == GetLocalPlayer() then
                BlzFrameSetVisible(buttonListObject.Parent, false)
                BlzFrameSetVisible(MainList.Parent, true)
            elseif  data.Text == "Close" and GetTriggerPlayer() == GetLocalPlayer() then
                BlzFrameSetVisible(buttonListObject.Parent, false)
            end
        end,
        function(frameObject, data)
            BlzFrameSetTexture(frameObject.Icon, data.Icon, 0, false)
            BlzFrameSetText(frameObject.Text, data.Text)

            BlzFrameSetTexture(frameObject.ToolTipFrameIcon, data.Icon, 0, false)
            BlzFrameSetText(frameObject.ToolTipFrameName, data.Text)
        end)
        WizardButtonList = object
        TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNTalisman", Text = "Back"})
        TasButtonListAddData(object, {Icon = "ReplaceableTextures\\CommandButtons\\BTNTalisman", Text = "Close"})

        -- force an update
        UpdateTasButtonList(object)

        print("done")
        DestroyTimer(GetExpiredTimer())
    end, print)
    end)
    Good that this system is useful to you.
     
  5. imek

    imek

    Joined:
    Aug 18, 2016
    Messages:
    42
    Resources:
    0
    Resources:
    0
    Thank you again.
     
  6. imek

    imek

    Joined:
    Aug 18, 2016
    Messages:
    42
    Resources:
    0
    Resources:
    0
    I am still having trouble creating categories. I think I almost have all the code I need, but there is still stuff I don't understand. I am attaching my map file to this post. Maybe if you look at what I'm trying to do you will be able to give me instructions. I was able to make the 1st category but not all the others. Imek Amtgard map 05-31-2020 | HIVE

    Question: Can you please tell me how to finish adding the categories to my map? I need 13 different categories for different units. The 1st category has Goose and Fox in it.
     
  7. SpasMaster

    SpasMaster

    Joined:
    Jan 29, 2010
    Messages:
    1,885
    Resources:
    4
    Icons:
    2
    Maps:
    2
    Resources:
    4
    I am curious if a Jass version is something you plan on doing?

    Regardless, this seems neat as usual. +rep
     
  8. imek

    imek

    Joined:
    Aug 18, 2016
    Messages:
    42
    Resources:
    0
    Resources:
    0
    Never mind I figured out how to it works. I added all the categories. Thank you again Tasyen!
     
  9. imek

    imek

    Joined:
    Aug 18, 2016
    Messages:
    42
    Resources:
    0
    Resources:
    0
    So I have this code below and I need to UpdateTasButtonList(object) for the --add various data section of the code. But I can't get the icon with the value H001 to update and show up in the menu. Can some one please help me do this?

    --******SUMMON UNITS For WIZARD CLASS****************************************************************
    local frame = BlzCreateFrameByType("FRAME", "", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0,0)
    BlzFrameSetSize(frame, 0.23, 0.001)
    BlzFrameSetAbsPoint(frame, FRAMEPOINT_TOP, 0.4, 0.5)
    BlzFrameSetVisible(frame, false)

    -- create a new ButtonList with 10 Rows, frame is the parent and define the action when clicking the Button
    local object = CreateTasButtonList(10, frame, function(data, buttonListObject, dataIndex)
    if data.Text == "Back" and GetTriggerPlayer() == GetLocalPlayer() then
    BlzFrameSetVisible(buttonListObject.Parent, false)
    BlzFrameSetVisible(MainList.Parent, true)
    elseif data.Text == "Close" and GetTriggerPlayer() == GetLocalPlayer() then
    BlzFrameSetVisible(buttonListObject.Parent, false)
    end

    if data.Text == "Atta" and GetTriggerPlayer() == GetLocalPlayer() then
    BlzFrameSetVisible(buttonListObject.Parent, false)
    local frame = BlzCreateFrameByType("FRAME", "", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), 0,0)
    BlzFrameSetSize(frame, 0.23, 0.001)
    BlzFrameSetAbsPoint(frame, FRAMEPOINT_TOP, 0.4, 0.5)
    -- create a new ButtonList with 1 Rows, frame is the parent and define the action when clicking the Button
    local object = CreateTasButtonList(1, frame, function(data, buttonListObject, dataIndex)
    -- create an unit for the clicking player at 0/0 with facing 0
    CreateUnit(GetTriggerPlayer(), data, 0, 0, 0)
    BlzFrameSetVisible(buttonListObject.Parent, false)
    end)

    -- add various data
    TasButtonListAddData(object, FourCC("H001"))

    end
     
  10. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,557
    Resources:
    18
    Tools:
    2
    Maps:
    3
    Spells:
    8
    Tutorials:
    4
    JASS:
    1
    Resources:
    18
    I was expecting this, hence I already have thinkered about a way to create this in (v)jass. I am not against it. Probably do it in some time, but don't expect great (v)jass.
     
    Last edited: Jun 1, 2020
  11. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,557
    Resources:
    18
    Tools:
    2
    Maps:
    3
    Spells:
    8
    Tutorials:
    4
    JASS:
    1
    Resources:
    18
    Updated to Version6 which includes some small changes/fixes aswell as a (v)jass version.

    The (v)jass versions was built out of the Lua version hence it is also quite similar.
    There are still some differences between the (v)jass & Lua version.
    in the jass version the mapper's actions are run over triggers, hence there are globals instead of args.
    "" """""" The Button is the frameObject instead of being a member of it.
    """"" every TasButtonList is one Index in an array.
    """"" data used in TasButtonList is only integer.
    """" accessing the Frames is ugly.​
    Code (vJASS):

        //args for custom user actions
        integer TasButtonListData = 0
        string TasButtonListText = ""
        boolean TasButtonListIsSearching = false
        integer TasButtonListIndex = 0
        framehandle TasButtonListFrame = null
     


    The (v)jass versions did desync at first when i was using TriggerAction + TriggerExecute for the updateAction. In the released version this was replaced with TriggerCondition + TriggerEvaluate. With this change there were no desyncs during testing in Warcraft 3 1.31.1.
     
    Last edited: Jun 3, 2020
  12. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,557
    Resources:
    18
    Tools:
    2
    Maps:
    3
    Spells:
    8
    Tutorials:
    4
    JASS:
    1
    Resources:
    18
    Updated to V7 a small update.
    the searchTriggerAction code was pushed into a call able function, making it more easy/faster to reapply filter/search.
    The scrollFrame is now only shown when there is more filtered Data then buttons (it was also shown with an equal amount).
     
    Last edited: Jun 16, 2020
  13. KitsuneTailsPrower

    KitsuneTailsPrower

    Joined:
    Oct 9, 2019
    Messages:
    10
    Resources:
    0
    Resources:
    0
    A very useful and flexible system
     
  14. MyPad

    MyPad

    Spell Reviewer

    Joined:
    May 9, 2014
    Messages:
    1,469
    Resources:
    8
    Models:
    1
    Icons:
    2
    Maps:
    1
    Spells:
    3
    JASS:
    1
    Resources:
    8
    Splendid work with creating UI systems. There is a minor kink, though.
    Apparently, the button elements (when the slider is at the top) are supposed to be at the bottom.
    The video below should better explain the issue: