comparison 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
comparison
equal deleted inserted replaced
86:48182978d1c6 87:27db212af783
15 FrameClusters = {}, 15 FrameClusters = {},
16 parserDepth = 0, 16 parserDepth = 0,
17 pendingCalls = {}, 17 pendingCalls = {},
18 } 18 }
19 VeneerHandlerMixin = { 19 VeneerHandlerMixin = {
20 Reanchor = nop 20 Reanchor = nop,
21 anchorPoint = 'CENTER', -- indicates the initial cluster group point
22 --anchorPath = 'BOTTOM', -- indicates the point from which the frame is anchored in a cluster arrangement
21 } 23 }
22 local print = DEVIAN_WORKSPACE and function(...) print('Veneer', ...) end or nop 24 local print = DEVIAN_WORKSPACE and function(...) print('Veneer', ...) end or nop
23 local wipe = table.wipe 25 local wipe = table.wipe
24 26
25 local defaults = { 27 local defaults = {
46 end 48 end
47 local GetTableName = function(table) 49 local GetTableName = function(table)
48 return (IsFrameHandle(table) and table:GetName()) or tostring(table) 50 return (IsFrameHandle(table) and table:GetName()) or tostring(table)
49 end 51 end
50 52
51 local anchor_coefficients = { 53 local OFFSET_PARALLELS = {
52 ['TOP'] = function(x, y) return x, y end, 54 TOP = {'LEFT', 'RIGHT', 'SetHeight'},
53 ['BOTTOM'] = function(x, y) return x,y end, 55 BOTTOM = {'LEFT', 'RIGHT', 'SetHeight'},
54 ['LEFT'] = function(x, y) return x,y end, 56 LEFT = {'TOP', 'BOTTOM', 'SetWidth'},
55 ['RIGHT'] = function(x,y) return x,y end, 57 RIGHT = {'TOP', 'BOTTOM', 'SetWidth'},
58 }
59 local ANCHOR_OFFSET_POINT = {
60 TOP = 'BOTTOM',
61 TOPLEFT = 'BOTTOMRIGHT',
62 TOPRIGHT = 'BOTTOMLEFT',
63 LEFT = 'RIGHT',
64 RIGHT = 'LEFT',
65 CENTER = 'CENTER',
66 BOTTOM = 'TOP',
67 BOTTOMRIGHT = 'TOPLEFT',
68 BOTTOMLEFT = 'TOPRIGHT',
69 }
70 local ANCHOR_INSET_DELTA = {
71 TOP = {0, -1},
72 TOPLEFT = {1, -1},
73 TOPRIGHT = {-1,-1},
74 LEFT = {1, 0},
75 BOTTOMLEFT = {1, 1},
76 BOTTOM = {0, 1},
77 BOTTOMRIGHT = {-1, 1},
78 RIGHT = {-1, 0},
79 CENTER = {0, 0},
56 } 80 }
57 81
58 function VeneerCore:print(...) 82 function VeneerCore:print(...)
59 local txt = '|cFFFFFF00Veneer|r:' 83 local txt = '|cFFFFFF00Veneer|r:'
60 for i = 1, select('#', ...) do 84 for i = 1, select('#', ...) do
74 end 98 end
75 99
76 function VeneerCore:OnEvent(event, ...) 100 function VeneerCore:OnEvent(event, ...)
77 if event == 'ADDON_LOADED' or event == 'PLAYER_LOGIN' then 101 if event == 'ADDON_LOADED' or event == 'PLAYER_LOGIN' then
78 if IsLoggedIn() and not self.intialized then 102 if IsLoggedIn() and not self.intialized then
79 self.intialized = true
80 self:Setup() 103 self:Setup()
104 self:UnregisterEvent('ADDON_LOADED')
105 self:UnregisterEvent('PLAYER_LOGIN')
106 self:Reanchor()
107 self:Update()
81 end 108 end
82 end 109 end
83 end 110 end
84 111
85 function VeneerCore:OnDragStart() 112 function VeneerCore:OnDragStart()
90 function VeneerCore:OnDragStop() 117 function VeneerCore:OnDragStop()
91 self:StopMovingOrSizing() 118 self:StopMovingOrSizing()
92 end 119 end
93 120
94 function VeneerCore:Setup () 121 function VeneerCore:Setup ()
122 self.initialized = true
95 if (not VeneerData) or (not VeneerData.version) then 123 if (not VeneerData) or (not VeneerData.version) then
96 VeneerData = defaults 124 VeneerData = defaults
97 end 125 end
98 self.data = VeneerData 126 self.data = VeneerData
99
100
101 self:ExecuteOnClusters(nil, 'Setup') 127 self:ExecuteOnClusters(nil, 'Setup')
128 end
129
130
131 function VeneerCore:GetClusterFromArgs (...)
132 local primaryAnchor
133 local insertPosition
134 local clusterTable = self.FrameClusters
135 for i = 1, select('#', ...) do
136 local arg = select(i, ...)
137 local argType = type(arg)
138 if argType == 'string' then
139 if not primaryAnchor then
140 primaryAnchor = arg
141 end
142 clusterTable[arg] = clusterTable[arg] or {}
143 clusterTable = clusterTable[arg]
144 print(string.rep(' ', i)..'anchor cluster', i, arg)
145 elseif argType == 'boolean' then
146 insertPosition = 1
147 end
148 end
149 if not primaryAnchor then
150 primaryAnchor = 'TOPLEFT'
151 end
152 if not insertPosition then
153 insertPosition = #clusterTable + 1
154 end
155
156
157 return primaryAnchor, clusterTable, insertPosition
102 end 158 end
103 159
104 function VeneerCore:AddHandler(handler, ...) 160 function VeneerCore:AddHandler(handler, ...)
105 print('*** Adding handler:', handler.moduleName or handler:GetName()) 161 print('*** Adding handler:', handler.moduleName or handler:GetName())
106 local clusterTable = self.FrameClusters 162
107 for i = 1, select('#', ...) do 163 local anchorGroup, clusterTable, clusterIndex = self:GetClusterFromArgs(...)
108 local anchor = select(i, ...) 164 if clusterIndex == 1 then
109 clusterTable[anchor] = clusterTable[anchor] or {} 165 for i, frame in ipairs(clusterTable) do
110 clusterTable = clusterTable[anchor] 166 frame.clusterIndex = i + 1
111 print(' cluster layer', i, anchor) 167 end
112 end 168 end
169 tinsert(clusterTable, clusterIndex, handler)
170 print('cluster', anchorGroup, 'table', clusterTable, 'position', clusterIndex)
171
172
173 handler.anchorCluster = clusterTable
174 handler.anchorIndex = clusterIndex
113 for k,v in pairs(VeneerHandlerMixin) do 175 for k,v in pairs(VeneerHandlerMixin) do
114 if not handler[k] then 176 if not handler[k] then
177 print(' * from mixin:', k)
115 handler[k] = v 178 handler[k] = v
116 end 179 end
117 end 180 end
118 tinsert(clusterTable, handler) 181 if self.initialized then
119 handler:Reanchor() 182 print(' -- doing initialization')
183 if handler.Setup and not handler.initialized then
184 handler:Setup()
185 handler.initialized = true
186 end
187 if handler.Update then
188 handler:Update()
189 end
190 self:InternalReanchor(handler)
191
192 end
193 end
194
195 function VeneerCore:Reanchor()
196 self:ExecuteOnClusters(nil, 'Reanchor')
197 end
198
199 function VeneerCore:Update()
200 self:ExecuteOnClusters(nil, 'Update')
201 end
202
203 -- updates anchor relations to and from the target handler
204 function VeneerCore:GetAnchor(...)
205
206 end
207
208 function VeneerCore:InternalReanchor(handler, printFunc)
209 print('|cFF00FFFFVeneer:InternalReanchor('..handler:GetName()..')')
210 local anchorPoint = handler.anchorPath or handler.anchorPoint
211 local anchorParent, anchorTo = UIParent, anchorPoint
212 for i, frame in ipairs(handler.anchorCluster) do
213 if frame ~= handler then
214 anchorParent = frame
215 anchorTo = ANCHOR_OFFSET_POINT[anchorPoint]
216
217 else
218 local nextFrame = handler.anchorCluster[i+1]
219 if nextFrame then
220
221 local subPoint = nextFrame.anchorPath or nextFrame.anchorPoint
222 local subTo = ANCHOR_OFFSET_POINT[subPoint]
223 nextFrame:ClearAllPoints()
224 nextFrame:SetPoint(subPoint, handler, subTo, 0, 0)
225 print(' -- pushing '..nextFrame:GetName()..' down the anchor chain', subPoint, subTo)
226 end
227 break
228 end
229 end
230
231 handler:ClearAllPoints()
232 handler:SetPoint(anchorPoint, anchorParent, anchorTo, 0, 0)
233
234 print(handler.anchorPoint, anchorParent, anchorTo)
235 if printFunc then
236 printFunc('|cFF88FF00'..handler:GetName()..':SetPoint(', handler.anchorPoint, anchorParent, anchorTo)
237 end
238
120 end 239 end
121 240
122 function VeneerCore:ExecuteOnClusters(layer, method) 241 function VeneerCore:ExecuteOnClusters(layer, method)
123 self.parserDepth = self.parserDepth + 1 242 self.parserDepth = self.parserDepth + 1
124 layer = layer or self.FrameClusters
125 if not layer then 243 if not layer then
126 if self.parserDepth >= 1 then 244 if self.parserDepth > 1 then
127 tinsert(self.pendingCalls, method) 245 tinsert(self.pendingCalls, method)
128 print('delaying walk for', method) 246 print('delaying walk for', method)
129 return 247 return
130 end 248 end
131 print('|cFF00FFFFVeneer|r:'..method..'('..tostring(layer)..')') 249 print('|cFF00FF00Veneer:ExecuteOnClusters|r('..tostring(layer)..', '..method..')')
132 else 250 else
133 print(' L'..self.parserDepth) 251 print(' Level '..self.parserDepth)
134 end 252 end
253
254 layer = layer or self.FrameClusters
135 for anchor, cluster in pairs(layer) do 255 for anchor, cluster in pairs(layer) do
136 for index, frame in ipairs(cluster) do 256 for index, frame in ipairs(cluster) do
137 print(' '..anchor..'.'..index..' = '..frame:GetName()) 257 print(' '..anchor..'.'..index..' = '..frame:GetName())
138 if frame[method] then 258 if frame[method] then
139 print(' '..frame:GetName()..':'..method..'(...)') 259 print(' |cFF00FF00'..frame:GetName())
140 frame[method](frame) 260 frame[method](frame, true)
141 end 261 end
142 end 262 end
143 if cluster.FrameClusters then 263 if cluster.FrameClusters then
144 self:ExecuteOnClusters(cluster.FrameClusters, method) 264 self:ExecuteOnClusters(cluster.FrameClusters, method)
145 end 265 end
149 if (self.parserDepth == 0) and (#self.pendingCalls >= 1) then 269 if (self.parserDepth == 0) and (#self.pendingCalls >= 1) then
150 local delayedMethod = tremove(self.pendingCalls, 1) 270 local delayedMethod = tremove(self.pendingCalls, 1)
151 print('starting delayed walk for', delayedMethod) 271 print('starting delayed walk for', delayedMethod)
152 self:ExecuteOnClusters(nil, delayedMethod) 272 self:ExecuteOnClusters(nil, delayedMethod)
153 end 273 end
154 end
155
156 function VeneerCore:Update()
157 self:ExecuteOnClusters(nil, 'Update')
158 end 274 end
159 275
160 local VeneerButton_OnDragStart = function(self) 276 local VeneerButton_OnDragStart = function(self)
161 self.startingLeft = self:GetLeft() 277 self.startingLeft = self:GetLeft()
162 self.startingBottom = self:GetBottom() 278 self.startingBottom = self:GetBottom()