diff Veneer.lua @ 87:27db212af783

- polished position management code; goes something like: - core:Reanchor() to soft fix all anchors - module:Reanchor() or core:InternalReanchor(module) to position a specific set of neighboring frames
author Nenue
date Wed, 19 Oct 2016 16:51:17 -0400
parents 16b300d96724
children b107b4df7eb6
line wrap: on
line diff
--- a/Veneer.lua	Tue Oct 18 19:53:24 2016 -0400
+++ b/Veneer.lua	Wed Oct 19 16:51:17 2016 -0400
@@ -17,7 +17,9 @@
   pendingCalls = {},
 }
 VeneerHandlerMixin = {
-  Reanchor = nop
+  Reanchor = nop,
+  anchorPoint = 'CENTER', -- indicates the initial cluster group point
+  --anchorPath = 'BOTTOM', -- indicates the point from which the frame is anchored in a cluster arrangement
 }
 local print = DEVIAN_WORKSPACE and function(...) print('Veneer', ...) end or nop
 local wipe = table.wipe
@@ -48,11 +50,33 @@
   return (IsFrameHandle(table) and table:GetName()) or tostring(table)
 end
 
-local anchor_coefficients = {
-  ['TOP'] = function(x, y) return x, y end,
-  ['BOTTOM'] = function(x, y) return x,y end,
-  ['LEFT'] = function(x, y) return x,y end,
-  ['RIGHT'] = function(x,y) return x,y end,
+local OFFSET_PARALLELS = {
+  TOP = {'LEFT', 'RIGHT', 'SetHeight'},
+  BOTTOM = {'LEFT', 'RIGHT', 'SetHeight'},
+  LEFT = {'TOP', 'BOTTOM', 'SetWidth'},
+  RIGHT = {'TOP', 'BOTTOM', 'SetWidth'},
+}
+local ANCHOR_OFFSET_POINT = {
+  TOP = 'BOTTOM',
+  TOPLEFT = 'BOTTOMRIGHT',
+  TOPRIGHT = 'BOTTOMLEFT',
+  LEFT = 'RIGHT',
+  RIGHT = 'LEFT',
+  CENTER = 'CENTER',
+  BOTTOM = 'TOP',
+  BOTTOMRIGHT = 'TOPLEFT',
+  BOTTOMLEFT = 'TOPRIGHT',
+}
+local ANCHOR_INSET_DELTA = {
+  TOP = {0, -1},
+  TOPLEFT = {1, -1},
+  TOPRIGHT = {-1,-1},
+  LEFT = {1, 0},
+  BOTTOMLEFT = {1, 1},
+  BOTTOM = {0, 1},
+  BOTTOMRIGHT = {-1, 1},
+  RIGHT = {-1, 0},
+  CENTER = {0, 0},
 }
 
 function VeneerCore:print(...)
@@ -76,8 +100,11 @@
 function VeneerCore:OnEvent(event, ...)
   if event == 'ADDON_LOADED' or event == 'PLAYER_LOGIN' then
     if IsLoggedIn() and not self.intialized then
-      self.intialized = true
       self:Setup()
+      self:UnregisterEvent('ADDON_LOADED')
+      self:UnregisterEvent('PLAYER_LOGIN')
+      self:Reanchor()
+      self:Update()
     end
   end
 end
@@ -92,52 +119,145 @@
 end
 
 function VeneerCore:Setup ()
+  self.initialized = true
   if (not VeneerData) or (not VeneerData.version) then
     VeneerData = defaults
   end
   self.data = VeneerData
+  self:ExecuteOnClusters(nil, 'Setup')
+end
 
 
-  self:ExecuteOnClusters(nil, 'Setup')
+function VeneerCore:GetClusterFromArgs (...)
+  local primaryAnchor
+  local insertPosition
+  local clusterTable = self.FrameClusters
+  for i = 1, select('#', ...) do
+    local arg = select(i, ...)
+    local argType = type(arg)
+    if argType == 'string' then
+      if not primaryAnchor then
+        primaryAnchor = arg
+      end
+      clusterTable[arg] = clusterTable[arg] or {}
+      clusterTable = clusterTable[arg]
+      print(string.rep(' ', i)..'anchor cluster', i, arg)
+    elseif argType == 'boolean' then
+      insertPosition = 1
+    end
+  end
+  if not primaryAnchor then
+    primaryAnchor = 'TOPLEFT'
+  end
+  if not insertPosition then
+    insertPosition = #clusterTable + 1
+  end
+
+
+  return primaryAnchor, clusterTable, insertPosition
 end
 
 function VeneerCore:AddHandler(handler, ...)
   print('*** Adding handler:', handler.moduleName or handler:GetName())
-  local clusterTable = self.FrameClusters
-  for i = 1, select('#', ...) do
-    local anchor = select(i, ...)
-    clusterTable[anchor] = clusterTable[anchor] or {}
-    clusterTable = clusterTable[anchor]
-    print('    cluster layer', i, anchor)
+
+  local anchorGroup, clusterTable, clusterIndex = self:GetClusterFromArgs(...)
+  if clusterIndex == 1 then
+    for i, frame in ipairs(clusterTable) do
+      frame.clusterIndex = i + 1
+    end
   end
+  tinsert(clusterTable, clusterIndex, handler)
+  print('cluster', anchorGroup, 'table', clusterTable, 'position', clusterIndex)
+
+
+  handler.anchorCluster = clusterTable
+  handler.anchorIndex = clusterIndex
   for k,v in pairs(VeneerHandlerMixin) do
     if not handler[k] then
+      print(' * from mixin:', k)
       handler[k] = v
     end
   end
-  tinsert(clusterTable, handler)
-  handler:Reanchor()
+  if self.initialized then
+    print('  -- doing initialization')
+    if handler.Setup and not handler.initialized then
+      handler:Setup()
+      handler.initialized = true
+    end
+    if handler.Update then
+      handler:Update()
+    end
+    self:InternalReanchor(handler)
+
+  end
+end
+
+function VeneerCore:Reanchor()
+  self:ExecuteOnClusters(nil, 'Reanchor')
+end
+
+function VeneerCore:Update()
+  self:ExecuteOnClusters(nil, 'Update')
+end
+
+-- updates anchor relations to and from the target handler
+function VeneerCore:GetAnchor(...)
+
+end
+
+function VeneerCore:InternalReanchor(handler, printFunc)
+  print('|cFF00FFFFVeneer:InternalReanchor('..handler:GetName()..')')
+  local anchorPoint = handler.anchorPath or handler.anchorPoint
+  local anchorParent, anchorTo = UIParent, anchorPoint
+  for i, frame in ipairs(handler.anchorCluster) do
+    if frame ~= handler then
+      anchorParent = frame
+      anchorTo = ANCHOR_OFFSET_POINT[anchorPoint]
+
+    else
+      local nextFrame = handler.anchorCluster[i+1]
+      if nextFrame then
+
+        local subPoint = nextFrame.anchorPath or nextFrame.anchorPoint
+        local subTo = ANCHOR_OFFSET_POINT[subPoint]
+        nextFrame:ClearAllPoints()
+        nextFrame:SetPoint(subPoint, handler, subTo, 0, 0)
+        print(' -- pushing '..nextFrame:GetName()..' down the anchor chain', subPoint, subTo)
+      end
+      break
+    end
+  end
+
+  handler:ClearAllPoints()
+  handler:SetPoint(anchorPoint, anchorParent, anchorTo, 0, 0)
+
+  print(handler.anchorPoint, anchorParent, anchorTo)
+  if printFunc then
+    printFunc('|cFF88FF00'..handler:GetName()..':SetPoint(', handler.anchorPoint, anchorParent, anchorTo)
+  end
+
 end
 
 function VeneerCore:ExecuteOnClusters(layer, method)
   self.parserDepth = self.parserDepth + 1
-  layer = layer or self.FrameClusters
   if not layer then
-    if self.parserDepth >= 1 then
+    if self.parserDepth > 1 then
       tinsert(self.pendingCalls, method)
       print('delaying walk for', method)
       return
     end
-    print('|cFF00FFFFVeneer|r:'..method..'('..tostring(layer)..')')
+    print('|cFF00FF00Veneer:ExecuteOnClusters|r('..tostring(layer)..', '..method..')')
   else
-    print(' L'..self.parserDepth)
+    print(' Level '..self.parserDepth)
   end
+
+  layer = layer or self.FrameClusters
   for anchor, cluster in pairs(layer) do
     for index, frame in ipairs(cluster) do
-      print('  '..anchor..'.'..index..' = '..frame:GetName())
+      print(' '..anchor..'.'..index..' = '..frame:GetName())
       if frame[method] then
-        print('  '..frame:GetName()..':'..method..'(...)')
-        frame[method](frame)
+        print('  |cFF00FF00'..frame:GetName())
+        frame[method](frame, true)
       end
     end
     if cluster.FrameClusters then
@@ -153,10 +273,6 @@
   end
 end
 
-function VeneerCore:Update()
-  self:ExecuteOnClusters(nil, 'Update')
-end
-
 local VeneerButton_OnDragStart = function(self)
   self.startingLeft = self:GetLeft()
   self.startingBottom = self:GetBottom()