Thread Tools Display Modes
09-29-18, 06:48 AM   #1
Lyak
A Cyclonian
Join Date: Jul 2018
Posts: 46
[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?

Last edited by Lyak : 09-29-18 at 07:15 AM.
  Reply With Quote
09-29-18, 09:44 AM   #2
Vrul
A Scalebane Royal Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 404
Originally Posted by Lyak View Post
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)
  Reply With Quote
09-29-18, 03:37 PM   #3
Lyak
A Cyclonian
Join Date: Jul 2018
Posts: 46
Originally Posted by Vrul View Post
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?

Last edited by Lyak : 09-29-18 at 04:27 PM.
  Reply With Quote
09-29-18, 04:33 PM   #4
Vrul
A Scalebane Royal Guard
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 404
Originally Posted by Lyak View Post
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.
  Reply With Quote
09-29-18, 05:46 PM   #5
Lyak
A Cyclonian
Join Date: Jul 2018
Posts: 46
Originally Posted by Vrul View Post
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

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

Last edited by Lyak : 09-29-18 at 06:04 PM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » [AceConfig] Update options(?) based on selected unit

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off