Thread Tools Display Modes
08-20-15, 09:32 PM   #1
VincentSDSH
Non-Canadian Luzer!
 
VincentSDSH's Avatar
AddOn Author - Click to view addons
Join Date: Jun 2006
Posts: 350
Interface options and teaching a camel to play the saxophone

I have one of those simple-but-involved questions that I've done a lot -- yet perhaps insufficient amount -- of research and testing on and I'm stymied on something that is fairly simple in a lot of frameworks I've used but is somehow missing here or I'm missing something staggeringly obvious in how to trigger it.

Inside the Ace3 options table are these little beasties...
Code:
      set = function(info,val) MyAddon.enabled = val end,
      get = function(info) return MyAddon.enabled end
They're generally happy and straight forward since the data you set remains visibly in the control.

The problem I'm running into is that data in the control itself is reflected in another part of the options table. Using the above generic example, imagine the following from another leaf in the options table:
Code:
icon=function() 
  if MyAddon.enabled then return MyAddon.icon.enabled 
  else return MyAddon.icon.disabled 
  end 
end
When the aforementioned set is executed in leaf A the icon function in leaf B doesn't update, which is fine and there's nothing inherently wrong with that.

What I can't figure out is how to signal icon in leaf B or leaf B itself to update.

Obviously I can't just call the <>.get() function in the options table directly -- it's fun but it just gives me the result of the <>.get function -- and I can't for the life of me find any type of refresh prompt, signal, call, semaphore, smoke signal, or kicked alley cat that would prompt an update.

Now, thankfully, I generate the options table dynamically and use shared, hidden keys in the data and the options table so it's trivial to find the leaf (or stem), prune it, and re-add it but that seems kinda drastic just to force a single-control re-calc (in testing, this is unobserved by the user even when the control/leaf/stem they are in is pruned/readded but that feels like a slow-timing issue with the blizzard options panel and may not work for all users/machines/addon-loads).

So...is there a way to pretty-please-with-sugar-on-top to get a 2nd-party element to recalculate its value?

(For background, my options table is set of nested, inline=false groups for the purpose of easy user access to controls (i.e., collapsible group of group groups) but this winds up with a control in this group resetting the displayed name on this group in a group{group{group{group{group{controls}}}}} -type setup in one scenario.)

Last edited by VincentSDSH : 08-22-15 at 01:00 PM.
  Reply With Quote
08-21-15, 09:15 PM   #2
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Might help to know which framework you are using. Are you using AceConfig to automatically generate your options UI? Are you using AceGUI directly? Or some other framework?

Also, assuming you're using an AceConfig options table (regardless of whether you're using AceConfig or direct AceGUI) -- are the things you're talking about all in the same table? Your post is pretty all over the place...
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
08-22-15, 01:02 PM   #3
VincentSDSH
Non-Canadian Luzer!
 
VincentSDSH's Avatar
AddOn Author - Click to view addons
Join Date: Jun 2006
Posts: 350
Originally Posted by Phanx View Post
Might help to know which framework you are using
Ace3 for loading the options to the BlizzardUI but it was the Blizzard framework that seems to lack the 'hey, re-run 2nd-party .get() for this item' ability.
  Reply With Quote
08-22-15, 05:08 PM   #4
Torhal
A Pyroguard Emberseer
 
Torhal's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2008
Posts: 1,196
I'm not entirely certain this is what you're after, but look at my config code in Toaster. I have a section that dynamically updates the list of AddOns which can be configured; they're added when detected (or if previously detected from SVs) and recolored/sorted when enabled or disabled.
__________________
Whenever someone says "pls" because it's shorter than "please", I say "no" because it's shorter than "yes".

Author of NPCScan and many other AddOns.
  Reply With Quote
08-22-15, 11:24 PM   #5
VincentSDSH
Non-Canadian Luzer!
 
VincentSDSH's Avatar
AddOn Author - Click to view addons
Join Date: Jun 2006
Posts: 350
I may have simplified this a bit too much but it's just to explain one element of the basic situation. There's a number of other thing that happen with the group of group groups list that's displayed but this is the simplest to explain. Since the parentName is displayed in the UI, it needs to update when/after the elementName.set is run.

My only concern is that the method I'm using is...weird to use in the context it's used in. If this was between openings of the UI, I wouldn't bat a eye at it. It just feels like a clumsy way to go about it when you need to update secondary controls while still in the blizzard addon options UI.

Lua Code:
  1. return { -- returns an ultimate group in the tree
  2.     type = "group",
  3.     name = parentName, -- This group name is what needs to change dynamically
  4.                        -- when its child's set is run
  5.     args = {
  6.         elementName = {
  7.             name = "name",
  8.             type = "input",
  9.             get = function() return parentName end,
  10.             set = function(i, v)
  11.  
  12.                 parentName= <updated parent name>
  13.            
  14.             -- What I do: self:regrow(thisParentID). Prunes all the code
  15.             -- shown (and all that's not shown) from the
  16.             -- trunk var for the Options Table and immediately regenerates
  17.             -- it using the updated var, which changes the options UI and
  18.             -- leaves the user in the same open leaf. It actually works
  19.             -- better than I have any right to expect.
  20.             end,
  21.         },
  22.     },
  23. }

Again, the methods I'm using works so perfectly it's a tad bothersome -- it even works when rebuilding huge chunks of the options table (e.g., resorting options within the list of groups, which I would rather alter the *.order= for and prompt a refresh).

I'm just wondering if there's a way of doing it that I've missed or if no one's tried to teach this particular camel to play the sax. Every other place I've seen this type of problem solved in a WoW addon, it's done in a way that avoids the blizzard UI.

As I was just writing that last sentence, it hit me that I had seen this happen in one other control (altering the name of a profile) where an setting an input field's data dynamically updated the name of the selected profile in the drop-down sister control to the new name (Addon is ChronoBars)...alas, though CB nukes the controls and recreates them.
  Reply With Quote
08-24-15, 08:12 AM   #6
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
I still don't know what you're actually doing, or wanting to do... how is any Blizzard stuff even involved in this? Are you trying to change the names of option categories displayed in the Interface Options window? If so, how is AceConfig usage relevant?
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
08-24-15, 11:41 AM   #7
VincentSDSH
Non-Canadian Luzer!
 
VincentSDSH's Avatar
AddOn Author - Click to view addons
Join Date: Jun 2006
Posts: 350
This is what Ace has to do with it but I'm not sure it's important.
Lua Code:
  1. LibStub("AceConfigRegistry-3.0"):RegisterOptionsTable(appName, AceOptionsTable)
  2. LibStub("AceConfigDialog-3.0"):AddToBlizOptions(appName, Localized.appName)
When the OptionsTable is built, most of it is dynamic: user generated groups and items have properties so the code creates OptionTable entries for them. Most of the time you see multiple select controls but that is really annoying when you're trying to get a sense of what's going on across groups of groups & contents, so I used a non-inline group to create a categorized list. Entry A wants to be named Entry Alpha so click on Entry A in the categorized list (who's name is supplied in the OptionsTable's name= for the group). One of the controls in Entry A's arg list is an input field to change Entry A's name. When changed, the core data is changed just fine (e.g., the savedvariable table is updated with the new name) but the tab still had the original name, it doesn't pick up the change while you are still in the config dialog. Given that many edits may occur during configuration, this isn't something easily written off from a UX perspective, so I needed a way to signal the control to 'refresh' its display much the same why a 'get' runs after the 'set' is done for the control itself. There just doesn't seem to be a way to fresh a 2nd-party control.

The only thing I've seen the blizzard config display respond to is removals and additions to the OptionsTable. Adding an item to the OptionsTable or removing it seems to have immediate effect. Thus, I can be in the properties panel of an group-item in a group-container, prune off all group-containers, rebuild all group-containers, and the user never realizes what happened (If pruned but not rebuilt, the config dialog resets the user to a new position, just as you'd expect). It works so damned perfectly I'm tempted to think that it's intentional -- daft as it is -- but I can't shake the feeling that there's a timing issue my testing data-set or addon load isn't big enough to run afoul of, 'cause this really feels like damned weird. If it ignored prunes & additions, I'd assume the config dialog was a static reading (excepting the reflexive :get) but it does.

Most of the time this type of problem isn't handled in a config dialog but within the controls themselves, where this kind of update-of-scale is handled in the addon's refresh methods. The only place I can recall seeing this in-blizzard-config-dialog dynamic is with ChronoBars 'rename profile' and, as I noted above, follows the 'cull and repopulate' logic I'm using.

That's a good test if you want to see it: dependent sister controls: A reacts to B, change B then convince A to react w/o leaving the config dialog.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Interface options and teaching a camel to play the saxophone


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