Ok, now what comes to my attention is that you don't call ClearAllPoints in the parents OnHide() function. And if I understand your code correctly this should be there, since you always re-set the points on hiding/showing.
----------
What I am doing has a pretty similar effect to what you are doing, though I'm doing it different. You could simply expand your code to hide empty bags by simply expanding your conditions to hide bags.
Hiding empty bags with parent anchoring
The idea was to save anchoring information in every frame. This is not information about which one the frame is anchored to but rather which frames are anchored to the current one (mainly for performance reasons). So when I'm spawning the bags, it looks like this:
Code:
-----------------------------------------------
-- Store the anchoring order:
-- read: "tar" is anchored to "src" in the direction denoted by "dir".
-----------------------------------------------
local function CreateAnchorInfo(src,tar,dir)
tar.AnchorTo = src
tar.AnchorDir = dir
if src then
if not src.AnchorTargets then src.AnchorTargets = {} end
src.AnchorTargets[tar] = true
end
end
-- Main Anchors:
-- Note that you still have to set points for those!
CreateAnchorInfo(nil, cB_Bags.main, "Bottom")
CreateAnchorInfo(nil, cB_Bags.bank, "Bottom")
cB_Bags.main:SetPoint("BOTTOMRIGHT", -20, 150)
cB_Bags.bank:SetPoint("LEFT", 15, 0)
-- Bank Anchors:
CreateAnchorInfo(cB_Bags.bank, cB_Bags.bankArmor, "Right")
CreateAnchorInfo(cB_Bags.bankArmor, cB_Bags.bankTrade, "Bottom")
-- more CreateAnchorInfos --
As already said, this does nothing more than storing the information about the hierarchy. I'm not setting any other points except those for the two main bags at the time of spawning. The "main bags" are obviously those which are anchored to UIParent.
Now you need this little fella in your code:
Code:
function cargBags_Nivaya:UpdateAnchors(self)
if not self.AnchorTargets then return end
for v,_ in pairs(self.AnchorTargets) do
local t, u = v.AnchorTo, v.AnchorDir
if t then
local h = cB_BagHidden[t.Name]
v:ClearAllPoints()
if not h and u == "Top" then v:SetPoint("BOTTOM", t, "TOP", 0, 15)
elseif h and u == "Top" then v:SetPoint("BOTTOM", t, "BOTTOM")
elseif not h and u == "Bottom" then v:SetPoint("TOP", t, "BOTTOM", 0, -15)
elseif h and u == "Bottom" then v:SetPoint("TOP", t, "TOP")
elseif u == "Left" then v:SetPoint("BOTTOMRIGHT", t, "BOTTOMLEFT", -15, 0)
elseif u == "Right" then v:SetPoint("TOPLEFT", t, "TOPRIGHT", 15, 0) end
end
end
end
This function is responsible for actually setting the points. Not all directions are covered, only those I currently need. But I hope you get the point.
The last thing you have to do is bind the anchoring update to an event. So just add something like the following to your UpdateButtonPositions handler. At the same time I'm checking for empty bags:
Code:
local tName = self.Name
local isEmpty = true
for _,v in ipairs(buttons) do
...
isEmpty = false
end
cB_BagHidden[tName] = (not t) and isEmpty or false
cargBags_Nivaya:UpdateAnchors(self)
cB_BagHidden saves information about which bags should be hidden, which equals to the empty state for me. "t" is for exceptions, if you have them (see below).
Now it basically should work. There's two things you still have to do. First is to apply the check for empty bags to you OpenCargBags() function, I'm doing it like this:
Code:
local function ShowBag(bag) if not cB_BagHidden[bag.Name] then bag:Show() end end
function OpenCargBags()
cB_Bags.main:Show()
ShowBag(cB_Bags.armor)
ShowBag(cB_Bags.bagNew)
ShowBag(cB_Bags.bagItemSets)
ShowBag(cB_Bags.quest)
...
end
The second thing you might wanna do is handle exceptions. So basically you usually don't want to hide the main bags when they're empty. This is also done in UpdateButtonPositions, for my layout it looks kinda messy though:
Code:
local tName = self.Name
local tBankBags = string.find(tName, "cBniv_Bank%a+")
local tBank = tBankBags or (tName == "cBniv_Bank")
local t = (tName == "cBniv_Bag") or (tName == "cBniv_Bank") or (tName == "cBniv_Keyring")
local tAS = (tName == "cBniv_Ammo") or (tName == "cBniv_Soulshards")
if (not tBankBags and cB_Bags.main:IsShown() and not (t or tAS)) or (tBankBags and cB_Bags.bank:IsShown()) then
if isEmpty then self:Hide() else self:Show() end
end
"t" excludes the main bags and the keyring, that's all the bags I never want to be automatically hidden or shown. The rest of the code handles automatic hiding and showing based on some conditions (appropriate main bag is opened and it's not one of the "locked" bags).
After typing all that I realize how complex my solution is..
Hope it helps anyways.