WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   Lua/XML Help (https://www.wowinterface.com/forums/forumdisplay.php?f=16)
-   -   [AceConfig] Update options(?) based on selected unit (https://www.wowinterface.com/forums/showthread.php?t=56726)

Lyak 09-29-18 06:48 AM

[AceConfig] Update options(?) based on selected unit
 
Hi all :),

I am trying to make an interface options with AceConfig-3.0 and here's what I got so far.

Lua Code:
  1. local anchorList = {TOPLEFT = "TOPLEFT", TOPRIGHT = "TOPRIGHT", BOTTOMRIGHT = "BOTTOMRIGHT", BOTTOMLEFT = "BOTTOMLEFT", LEFT = "LEFT", TOP = "TOP", RIGHT = "RIGHT", BOTTOM = "BOTTOM", CENTER = "CENTER"};
  2.  
  3. local selectedUnit = "Player";
  4.  
  5. local testOption = {
  6.     type = "group",
  7.     childGroups = "tab",
  8.     name = "TestOption",
  9.     args = {
  10.         selected = {
  11.             order = 1,
  12.             type = "select",
  13.             name = "Selected Unit",
  14.             values = {Player = "Player", Pet = "Pet", Target = "Target", TargetTarget = "TargetTarget", Focus = "Focus"},
  15.             get = function(info)
  16.                 return selectedUnit;
  17.             end,
  18.             set = function(info, ...)
  19.                 selectedUnit = ...;
  20.             end,
  21.         },
  22.         general = {
  23.             order = 2,
  24.             type = "group",
  25.             name = "General",
  26.             args = {
  27.                 p = {
  28.                     order = 1,
  29.                     type = "select",
  30.                     name = "Point",
  31.                     values = anchorList,
  32.                 },
  33.                 rT = {
  34.                     order = 2,
  35.                     type = "input",
  36.                     name = "Relative To",
  37.                 },
  38.                 rP = {
  39.                     order = 3,
  40.                     type = "select",
  41.                     name = "Relative Point",
  42.                     values = anchorList,
  43.                 },
  44.                 oX = {
  45.                     order = 4,
  46.                     type = "input",
  47.                     name = "X-Offset",
  48.                 },
  49.                 oY = {
  50.                     order = 5,
  51.                     type = "input",
  52.                     name = "Y-Offset",
  53.                 },
  54.             },
  55.         },
  56.         health = {
  57.             order = 3,
  58.             type = "group",
  59.             name = "Health",
  60.             args = {
  61.                 height = {
  62.                     order = 1,
  63.                     type = "range",
  64.                     name = "Height",
  65.                     min = 4,
  66.                     max = 32,
  67.                     step = 1,
  68.                 },
  69.                 texture = {
  70.                     order = 2,
  71.                     type = "select",
  72.                     name = "Texture",
  73.                     dialogControl = "LSM30_Statusbar",
  74.                     values = AceGUIWidgetLSMlists.statusbar,
  75.                 },
  76.             },
  77.         },
  78.         power = {
  79.             order = 4,
  80.             type = "group",
  81.             name = "Power",
  82.             args = {
  83.                 height = {
  84.                     order = 1,
  85.                     type = "range",
  86.                     name = "Height",
  87.                     min = 4,
  88.                     max = 32,
  89.                     step = 1,
  90.                 },
  91.                 texture = {
  92.                     order = 2,
  93.                     type = "select",
  94.                     name = "Texture",
  95.                     dialogControl = "LSM30_Statusbar",
  96.                     values = AceGUIWidgetLSMlists.statusbar,
  97.                 },
  98.             },
  99.         },
  100.     },
  101. };
  102.  
  103. ACR:RegisterOptionsTable("TestOption", testOption);
  104. ACD:AddToBlizOptions("TestOption", nil, nil);



The question is, is it possible to re-use those General, Health and Power tabs, but only change the db entry based on the selected unit? Or should I re-construct all those tabs whenever the unit changes?

Vrul 09-29-18 09:44 AM

Quote:

Originally Posted by Lyak (Post 330302)
The question is, is it possible to re-use those General, Health and Power tabs, but only change the db entry based on the selected unit?

Yes, and the ease of which is determined by how your db table is set up. Here is a generic example of how it could look:
Code:

local ACR = LibStub("AceConfigRegistry-3.0")
local ACD = LibStub("AceConfigDialog-3.0")
local LSM = LibStub("LibSharedMedia-3.0")

local anchorList = {
        TOPLEFT = "TOPLEFT",
        TOPRIGHT = "TOPRIGHT",
        BOTTOMRIGHT = "BOTTOMRIGHT",
        BOTTOMLEFT = "BOTTOMLEFT",
        LEFT = "LEFT",
        TOP = "TOP",
        RIGHT = "RIGHT",
        BOTTOM = "BOTTOM",
        CENTER = "CENTER"
}

local unitFrame = {
        Player = PlayerFrame,
        Pet = PetFrame,
        Target = TargetFrame,
        TargetTarget = TargetFrameToT,
        Focus = FocusFrame
}

local unitList = { }
for unit in pairs(unitFrame) do
        unitList[unit] = unit
end

local db = { }
for unit in pairs(unitFrame) do
        db[unit] = { }
end

local selectedUnit = "Player"

local function GetOption(info)
        return db[selectedUnit][info[#info]]
end

local function SetOption(info, value)
        db[selectedUnit][info[#info]] = value
end

local function UpdatePosition(unit)
        local frame = unitFrame[unit]
        frame:ClearAllPoints()
        local settings = db[unit]
        frame:SetPoint(settings.point or "CENTER", settings.relativeTo or UIParent, settings.relativePoint or settings.point or "CENTER", tonumber(settings.offsetX) or 0, tonumber(settings.offsetY) or 0)
end

local function UpdateStatusBar(unit, barKey)
        local settings = db[unit]
        local statusBar = unitFrame[unit][barKey]
        statusBar:SetHeight(tonumber(settings[barKey .. "Height"]) or 12)
        statusBar:SetStatusBarTexture(LSM:Fetch("statusbar", settings[barKey .. "Texture"]))
end

local function SetStatusBarOption(info, value)
        SetOption(info, value)
        UpdateStatusBar(selectedUnit, info[#info - 1])
end

local testOption = {
    type = "group",
    childGroups = "tab",
    name = "TestOption",
        get = GetOption,
    args = {
        selected = {
            order = 1,
            type = "select",
            name = "Selected Unit",
            values = unitList,
            get = function(info)
                return selectedUnit
            end,
            set = function(info, value)
                selectedUnit = value
            end,
        },
        general = {
            order = 2,
            type = "group",
            name = "General",
                        set = function(info, value)
                                SetOption(info, value)
                                UpdatePosition(selectedUnit)
                        end,
            args = {
                point = {
                    order = 1,
                    type = "select",
                    name = "Point",
                    values = anchorList,
                },
                relativeTo = {
                    order = 2,
                    type = "input",
                    name = "Relative To",
                },
                relativePoint = {
                    order = 3,
                    type = "select",
                    name = "Relative Point",
                    values = anchorList,
                },
                offsetX = {
                    order = 4,
                    type = "input",
                    name = "X-Offset",
                },
                offsetY = {
                    order = 5,
                    type = "input",
                    name = "Y-Offset",
                },
            },
        },
        healthbar = {
            order = 3,
            type = "group",
            name = "Health",
                        set = SetStatusBarOption,
            args = {
                healthbarHeight = {
                    order = 1,
                    type = "range",
                    name = "Height",
                    min = 4,
                    max = 32,
                    step = 1,
                },
                healthbarTexture = {
                    order = 2,
                    type = "select",
                    name = "Texture",
                    dialogControl = "LSM30_Statusbar",
                    values = AceGUIWidgetLSMlists.statusbar,
                },
            },
        },
        manabar = {
            order = 4,
            type = "group",
            name = "Power",
                        set = SetStatusBarOption,
            args = {
                manabarHeight = {
                    order = 1,
                    type = "range",
                    name = "Height",
                    min = 4,
                    max = 32,
                    step = 1,
                },
                manabarTexture = {
                    order = 2,
                    type = "select",
                    name = "Texture",
                    dialogControl = "LSM30_Statusbar",
                    values = AceGUIWidgetLSMlists.statusbar,
                },
            },
        },
    },
}

ACR:RegisterOptionsTable("TestOption", testOption)
ACD:AddToBlizOptions("TestOption", nil, nil)


Lyak 09-29-18 03:37 PM

Quote:

Originally Posted by Vrul (Post 330303)
Yes, and the ease of which is determined by how your db table is set up. Here is a generic example of how it could look:
Code:

-- vrul's code!

Hi vrul,

I really, really and really appreciate your time!

So, is the first getter function being the key point which gets called every single time when the selected unit changes?

If so, what would be the best way to deal with my db structure?

Lua Code:
  1. db = {
  2.     ["**"] = { -- Unit
  3.         point = {
  4.             p = "CENTER",
  5.             rT = "UIParent",
  6.             rP = "CENTER",
  7.             oX = 0,
  8.             oY = 0,
  9.         },
  10.         health = {
  11.             height = 21,
  12.             point = {
  13.                 p = "TOP",
  14.                 rT = "parent",
  15.                 rP = "TOP",
  16.                 oX = 0,
  17.                 oY = 0,
  18.             },
  19.             texture = nil,
  20.             tag = {
  21.                 point = {
  22.                     p = "CENTER",
  23.                     rT = "parent",
  24.                     rP = "CENTER",
  25.                     oX = 0,
  26.                     oY = 0,
  27.                 },
  28.             },
  29.         },
  30.         power = {
  31.             height = 21,
  32.             point = {
  33.                 p = "BOTTOM",
  34.                 rT = "parent",
  35.                 rP = "BOTTOM",
  36.                 oX = 0,
  37.                 oY = 0,
  38.             },
  39.             texture = nil,
  40.             tag = {
  41.                 point = {
  42.                     p = "CENTER",
  43.                     rT = "parent",
  44.                     rP = "CENTER",
  45.                     oX = 0,
  46.                     oY = 0,
  47.                 },
  48.             },
  49.         },
  50.     },
  51. };

Like you said it should be the matter of how simply the db is set-up, but I would like to maintain this structure, if possible.

Would the best chance be putting IF statements to see which 'point' the option is referring to?

Vrul 09-29-18 04:33 PM

Quote:

Originally Posted by Lyak (Post 330304)
Would the best chance be putting IF statements to see which 'point' the option is referring to?

No. The 'get' and 'set' fields are inherited so using a simple save structure allows you to use fewer generic get/set functions. If you insist on a needlessly complex save table then you will have to make more get/set functions for each unique case.

Lyak 09-29-18 05:46 PM

Quote:

Originally Posted by Vrul (Post 330305)
No. The 'get' and 'set' fields are inherited so using a simple save structure allows you to use fewer generic get/set functions. If you insist on a needlessly complex save table then you will have to make more get/set functions for each unique case.

Really?!

I mean I had those inherited getter and setter for those child options, but it didn't really update the values...

Let me have a look first!

SO EXCITED :banana:

EDIT #1

Yeap, you are totally right, Vrul.

I was an idiot.

It was a logical error and here's what happened.

My actual code of getting those general options were like this.

Lua Code:
  1. function CreateGeneralOption()
  2.     local _selectedUnit = string.lower(selectedUnit);
  3.    
  4.     local setting = db.global.module.unitframe;
  5.  
  6.     local option = {
  7.         order = GetOrder(),
  8.         type = "group",
  9.         name = "General",
  10.         get = function(info)
  11.             local value;
  12.             local opt = info[#info];
  13.             if opt == "p" or opt == "rT" or opt == "rP" or opt == "oX" or opt == "oY" then
  14.                 value = tostring(setting[_selectedUnit].point[info[#info]]); -- Won't print 0 if not turned into string
  15.             else
  16.                 value = setting[_selectedUnit][info[#info]];
  17.             end
  18.  
  19.             return value;
  20.         end,
  21.         args = {
  22.             width = {
  23.                 order = 1,
  24.                 type = "range",
  25.                 name = "Width",
  26.                 min = 128,
  27.                 max = 512,
  28.                 step = 1,
  29.                 set = function(info, ...)
  30.                     setting[_selectedUnit].width = ...;
  31.  
  32.                     Module.frames[_selectedUnit]:SetWidth(setting[_selectedUnit].width);
  33.                 end,
  34.             },
  35.             split1 = {
  36.                 order = 2,
  37.                 type = "header",
  38.                 name = "",
  39.             },
  40.             p = {
  41.                 order = 3,
  42.                 type = "select",
  43.                 name = "Point",
  44.                 values = anchorList,
  45.             },
  46.             rT = {
  47.                 order = 4,
  48.                 type = "input",
  49.                 name = "Relative To",
  50.             },
  51.             rP = {
  52.                 order = 5,
  53.                 type = "select",
  54.                 name = "Relative Point",
  55.                 values = anchorList,
  56.             },
  57.             oX = {
  58.                 order = 6,
  59.                 type = "input",
  60.                 name = "X-Offset",
  61.             },
  62.             oY = {
  63.                 order = 7,
  64.                 type = "input",
  65.                 name = "Y-Offset",
  66.             },
  67.         },
  68.     };
  69.  
  70.     return option;
  71. end

The _selectedUnit was never getting updated to newly selected unit and so, the db was always referrring to player's one even if the selected unit changes.

Which should actually be something like

Lua Code:
  1. function CreateGeneralOption()
  2.     local setting = db.global.module.unitframe;
  3.  
  4.     local option = {
  5.         order = GetOrder(),
  6.         type = "group",
  7.         name = "General",
  8.         get = function(info)
  9.             local _selectedUnit = string.lower(selectedUnit);
  10.  
  11.             local value;
  12.             local opt = info[#info];
  13.             if opt == "p" or opt == "rT" or opt == "rP" or opt == "oX" or opt == "oY" then
  14.                 value = tostring(setting[_selectedUnit].point[info[#info]]); -- Won't print 0 if not turned into string
  15.             else
  16.                 value = setting[_selectedUnit][info[#info]];
  17.             end
  18.  
  19.             return value;
  20.         end,
  21.         args = {
  22.             width = {
  23.                 order = 1,
  24.                 type = "range",
  25.                 name = "Width",
  26.                 min = 128,
  27.                 max = 512,
  28.                 step = 1,
  29.                 set = function(info, ...)
  30.                     local _selectedUnit = string.lower(selectedUnit);
  31.  
  32.                     setting[_selectedUnit].width = ...;
  33.  
  34.                     Module.frames[_selectedUnit]:SetWidth(setting[_selectedUnit].width);
  35.                 end,
  36.             },
  37.             split1 = {
  38.                 order = 2,
  39.                 type = "header",
  40.                 name = "",
  41.             },
  42.             p = {
  43.                 order = 3,
  44.                 type = "select",
  45.                 name = "Point",
  46.                 values = anchorList,
  47.             },
  48.             rT = {
  49.                 order = 4,
  50.                 type = "input",
  51.                 name = "Relative To",
  52.             },
  53.             rP = {
  54.                 order = 5,
  55.                 type = "select",
  56.                 name = "Relative Point",
  57.                 values = anchorList,
  58.             },
  59.             oX = {
  60.                 order = 6,
  61.                 type = "input",
  62.                 name = "X-Offset",
  63.             },
  64.             oY = {
  65.                 order = 7,
  66.                 type = "input",
  67.                 name = "Y-Offset",
  68.             },
  69.         },
  70.     };
  71.  
  72.     return option;
  73. end

Now it's working perfectly well!

Thank you so much for enlightening me :banana::banana::banana:


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

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