flickerstreak@1
|
1
|
flickerstreak@1
|
2 -- private constants
|
flickerstreak@1
|
3 local insideFrame = 1
|
flickerstreak@1
|
4 local outsideFrame = 2
|
flickerstreak@1
|
5
|
flickerstreak@1
|
6 local pointFindTable = {
|
flickerstreak@1
|
7 BOTTOMLEFT = function(f) return f:GetLeft(), f:GetBottom() end,
|
flickerstreak@1
|
8 BOTTOM = function(f) return nil, f:GetBottom() end,
|
flickerstreak@1
|
9 BOTTOMRIGHT = function(f) return f:GetRight(), f:GetBottom() end,
|
flickerstreak@1
|
10 RIGHT = function(f) return f:GetRight(), nil end,
|
flickerstreak@1
|
11 TOPRIGHT = function(f) return f:GetRight(), f:GetTop() end,
|
flickerstreak@1
|
12 TOP = function(f) return nil, f:GetTop() end,
|
flickerstreak@1
|
13 TOPLEFT = function(f) return f:GetLeft(), f:GetTop() end,
|
flickerstreak@1
|
14 LEFT = function(f) return f:GetLeft(), nil end,
|
flickerstreak@1
|
15 }
|
flickerstreak@1
|
16
|
flickerstreak@1
|
17 local oppositePointTable = {
|
flickerstreak@1
|
18 BOTTOMLEFT = "TOPRIGHT",
|
flickerstreak@1
|
19 BOTTOM = "TOP",
|
flickerstreak@1
|
20 BOTTOMRIGHT = "TOPLEFT",
|
flickerstreak@1
|
21 RIGHT = "LEFT",
|
flickerstreak@1
|
22 TOPRIGHT = "BOTTOMLEFT",
|
flickerstreak@1
|
23 TOP = "BOTTOM",
|
flickerstreak@1
|
24 TOPLEFT = "BOTTOMRIGHT",
|
flickerstreak@1
|
25 LEFT = "RIGHT"
|
flickerstreak@1
|
26 }
|
flickerstreak@1
|
27
|
flickerstreak@2
|
28 local anchoredLabelColor = { r =0.6, g = 0.2, b = 1.0 }
|
flickerstreak@2
|
29 local nonAnchoredLabelColor = { r = 1.0, g = 0.82, b = 0.0 }
|
flickerstreak@2
|
30
|
flickerstreak@1
|
31 -- private variables
|
flickerstreak@1
|
32 local stickyTargets = {
|
flickerstreak@1
|
33 [UIParent] = insideFrame,
|
flickerstreak@1
|
34 [WorldFrame] = insideFrame
|
flickerstreak@1
|
35 }
|
flickerstreak@1
|
36
|
flickerstreak@1
|
37 -- ReBar is an Ace 2 class prototype object.
|
flickerstreak@1
|
38 ReBar = AceLibrary("AceOO-2.0").Class("AceEvent-2.0")
|
flickerstreak@1
|
39
|
flickerstreak@1
|
40 local dewdrop = AceLibrary("Dewdrop-2.0")
|
flickerstreak@1
|
41
|
flickerstreak@1
|
42 function ReBar.prototype:init( config, id )
|
flickerstreak@1
|
43 ReBar.super.prototype.init(self)
|
flickerstreak@1
|
44
|
flickerstreak@2
|
45 local buttonClass = config and config.btnConfig and config.btnConfig.type and getglobal(config.btnConfig.type)
|
flickerstreak@1
|
46 self.config = config
|
flickerstreak@1
|
47 self.barID = id
|
flickerstreak@1
|
48 self.class = { button = buttonClass }
|
flickerstreak@1
|
49 self.buttons = { }
|
flickerstreak@1
|
50
|
flickerstreak@1
|
51 -- create the bar and control widgets
|
flickerstreak@1
|
52 self.barFrame = CreateFrame("Frame", "ReBar_"..self.barID, UIParent, "ReBarTemplate")
|
flickerstreak@2
|
53 self.controlFrame = getglobal(self.barFrame:GetName().."Controls")
|
flickerstreak@1
|
54 self.controlFrame.reBar = self
|
flickerstreak@2
|
55 self.barFrame:SetClampedToScreen(true)
|
flickerstreak@1
|
56
|
flickerstreak@1
|
57 -- set the text label on the control widget
|
flickerstreak@2
|
58 self.labelString = getglobal(self.controlFrame:GetName().."LabelString")
|
flickerstreak@2
|
59 self.labelString:SetText(id)
|
flickerstreak@1
|
60
|
flickerstreak@1
|
61 -- initialize the bar layout
|
flickerstreak@1
|
62 self:ApplySize()
|
flickerstreak@1
|
63 self:ApplyAnchor()
|
flickerstreak@1
|
64 self:LayoutButtons()
|
flickerstreak@1
|
65 self:ApplyVisibility()
|
flickerstreak@1
|
66
|
flickerstreak@1
|
67 -- add bar to stickyTargets list
|
flickerstreak@1
|
68 stickyTargets[self.barFrame] = outsideFrame
|
flickerstreak@1
|
69
|
flickerstreak@1
|
70 -- initialize dewdrop menu
|
flickerstreak@1
|
71 dewdrop:Register(self.controlFrame, 'children', function()
|
flickerstreak@1
|
72 dewdrop:FeedAceOptionsTable(ReActionGlobalMenuOptions)
|
flickerstreak@1
|
73 dewdrop:FeedAceOptionsTable(GenerateReActionBarOptions(self))
|
flickerstreak@1
|
74 dewdrop:FeedAceOptionsTable(GenerateReActionButtonOptions(self))
|
flickerstreak@1
|
75 end,
|
flickerstreak@1
|
76 'cursorX', true,
|
flickerstreak@1
|
77 'cursorY', true
|
flickerstreak@1
|
78 )
|
flickerstreak@1
|
79 end
|
flickerstreak@1
|
80
|
flickerstreak@1
|
81
|
flickerstreak@1
|
82 function ReBar.prototype:Destroy()
|
flickerstreak@1
|
83 if self.barFrame == dewdrop:GetOpenedParent() then
|
flickerstreak@1
|
84 dewdrop:Close()
|
flickerstreak@1
|
85 dewdrop:Unregister(self.barFrame)
|
flickerstreak@1
|
86 end
|
flickerstreak@1
|
87
|
flickerstreak@2
|
88 self:HideControls()
|
flickerstreak@1
|
89 self.barFrame:Hide()
|
flickerstreak@1
|
90 self.barFrame:ClearAllPoints()
|
flickerstreak@1
|
91 self.barFrame:SetParent(nil)
|
flickerstreak@2
|
92 self.barFrame:SetPoint("BOTTOMRIGHT", UIParent, "TOPLEFT", 0, 0)
|
flickerstreak@1
|
93
|
flickerstreak@1
|
94 -- need to keep around self.config for dewdrop menus in the process of deleting self
|
flickerstreak@1
|
95
|
flickerstreak@1
|
96 while #self.buttons > 0 do
|
flickerstreak@1
|
97 self.class.button:release(table.remove(self.buttons))
|
flickerstreak@1
|
98 end
|
flickerstreak@1
|
99
|
flickerstreak@1
|
100 -- remove from sticky targets table
|
flickerstreak@1
|
101 stickyTargets[self.barFrame] = nil
|
flickerstreak@1
|
102
|
flickerstreak@1
|
103 -- remove from global table
|
flickerstreak@1
|
104 -- for some reason after a destroy/recreate the globals still reference
|
flickerstreak@1
|
105 -- the old frames
|
flickerstreak@1
|
106 setglobal(self.barFrame:GetName(), nil)
|
flickerstreak@1
|
107 setglobal(self.barFrame:GetName().."Controls", nil)
|
flickerstreak@1
|
108 setglobal(self.controlFrame:GetName().."LabelString", nil)
|
flickerstreak@1
|
109 end
|
flickerstreak@1
|
110
|
flickerstreak@1
|
111
|
flickerstreak@1
|
112 -- show/hide the control frame
|
flickerstreak@1
|
113 function ReBar.prototype:ShowControls()
|
flickerstreak@1
|
114 self.controlFrame:Show()
|
flickerstreak@2
|
115 for _, b in ipairs(self.buttons) do
|
flickerstreak@2
|
116 b:BarUnlocked()
|
flickerstreak@2
|
117 end
|
flickerstreak@1
|
118 end
|
flickerstreak@1
|
119
|
flickerstreak@1
|
120 function ReBar.prototype:HideControls()
|
flickerstreak@1
|
121 local b = self.barFrame
|
flickerstreak@1
|
122 if b.isMoving or b.resizing then
|
flickerstreak@1
|
123 b:StopMovingOrSizing()
|
flickerstreak@1
|
124 b:SetScript("OnUpdate",nil)
|
flickerstreak@1
|
125 end
|
flickerstreak@1
|
126 -- close any dewdrop menu owned by us
|
flickerstreak@1
|
127 if self.barFrame == dewdrop:GetOpenedParent() then
|
flickerstreak@1
|
128 dewdrop:Close()
|
flickerstreak@1
|
129 end
|
flickerstreak@2
|
130 for _, b in ipairs(self.buttons) do
|
flickerstreak@2
|
131 b:BarLocked()
|
flickerstreak@2
|
132 end
|
flickerstreak@1
|
133 self.controlFrame:Hide()
|
flickerstreak@1
|
134 end
|
flickerstreak@1
|
135
|
flickerstreak@1
|
136
|
flickerstreak@1
|
137
|
flickerstreak@1
|
138
|
flickerstreak@1
|
139 -- accessors
|
flickerstreak@1
|
140 function ReBar.prototype:GetVisibility()
|
flickerstreak@1
|
141 return self.config.visible
|
flickerstreak@1
|
142 end
|
flickerstreak@1
|
143
|
flickerstreak@1
|
144 function ReBar.prototype:ToggleVisibility()
|
flickerstreak@1
|
145 self.config.visible = not self.config.visible
|
flickerstreak@1
|
146 self:ApplyVisibility()
|
flickerstreak@1
|
147 end
|
flickerstreak@1
|
148
|
flickerstreak@1
|
149 function ReBar.prototype:GetOpacity()
|
flickerstreak@1
|
150 return self.config.opacity or 100
|
flickerstreak@1
|
151 end
|
flickerstreak@1
|
152
|
flickerstreak@1
|
153 function ReBar.prototype:SetOpacity( o )
|
flickerstreak@1
|
154 self.config.opacity = tonumber(o)
|
flickerstreak@1
|
155 self:ApplyVisibility()
|
flickerstreak@1
|
156 return self.config.opacity
|
flickerstreak@1
|
157 end
|
flickerstreak@1
|
158
|
flickerstreak@1
|
159
|
flickerstreak@1
|
160 -- layout methods
|
flickerstreak@1
|
161 function ReBar.prototype:ApplySize()
|
flickerstreak@1
|
162 local buttonSz = self.config.size or 36
|
flickerstreak@1
|
163 local spacing = self.config.spacing or 4
|
flickerstreak@1
|
164 local rows = self.config.rows or 1
|
flickerstreak@1
|
165 local columns = self.config.columns or 12
|
flickerstreak@1
|
166 local w = buttonSz * columns + spacing * (columns + 1)
|
flickerstreak@1
|
167 local h = buttonSz * rows + spacing * (rows + 1)
|
flickerstreak@1
|
168 local f = self.barFrame
|
flickerstreak@1
|
169
|
flickerstreak@1
|
170 -- +1: avoid resizing oddities caused by fractional UI scale setting
|
flickerstreak@1
|
171 f:SetMinResize(buttonSz + spacing*2 + 1, buttonSz + spacing*2 + 1)
|
flickerstreak@1
|
172 f:SetWidth(w + 1)
|
flickerstreak@1
|
173 f:SetHeight(h + 1)
|
flickerstreak@1
|
174 end
|
flickerstreak@1
|
175
|
flickerstreak@1
|
176 function ReBar.prototype:ApplyAnchor()
|
flickerstreak@1
|
177 local a = self.config.anchor
|
flickerstreak@1
|
178 local f = self.barFrame
|
flickerstreak@2
|
179 if a then
|
flickerstreak@2
|
180 f:ClearAllPoints()
|
flickerstreak@2
|
181 f:SetPoint(a.point,getglobal(a.to),a.relPoint,a.x,a.y)
|
flickerstreak@2
|
182 local color = anchoredLabelColor
|
flickerstreak@2
|
183 if a.to == "UIParent" or a.to == "WorldFrame" then
|
flickerstreak@2
|
184 color = nonAnchoredLabelColor
|
flickerstreak@2
|
185 end
|
flickerstreak@2
|
186 self.labelString:SetTextColor(color.r, color.g, color.b)
|
flickerstreak@2
|
187 end
|
flickerstreak@1
|
188 end
|
flickerstreak@1
|
189
|
flickerstreak@1
|
190 function ReBar.prototype:ApplyVisibility()
|
flickerstreak@1
|
191 local v = self.config.visibility
|
flickerstreak@1
|
192 if type(v) == "table" then
|
flickerstreak@1
|
193 if v.class then
|
flickerstreak@1
|
194 local _, c = UnitClass("player")
|
flickerstreak@1
|
195 v = v.class[c]
|
flickerstreak@1
|
196 end
|
flickerstreak@1
|
197 elseif type(v) == "string" then
|
flickerstreak@1
|
198 local value = getglobal(v)
|
flickerstreak@1
|
199 v = value
|
flickerstreak@1
|
200 end
|
flickerstreak@1
|
201
|
flickerstreak@1
|
202 if self.config.opacity then
|
flickerstreak@1
|
203 self.barFrame:SetAlpha(self.config.opacity / 100)
|
flickerstreak@1
|
204 end
|
flickerstreak@1
|
205
|
flickerstreak@1
|
206 if v then
|
flickerstreak@1
|
207 self.barFrame:Show()
|
flickerstreak@1
|
208 else
|
flickerstreak@1
|
209 self.barFrame:Hide()
|
flickerstreak@1
|
210 end
|
flickerstreak@1
|
211 end
|
flickerstreak@1
|
212
|
flickerstreak@1
|
213 function ReBar.prototype:LayoutButtons()
|
flickerstreak@1
|
214 local r = self.config.rows
|
flickerstreak@1
|
215 local c = self.config.columns
|
flickerstreak@1
|
216 local n = r * c
|
flickerstreak@1
|
217 local sp = self.config.spacing
|
flickerstreak@1
|
218 local sz = self.config.size
|
flickerstreak@1
|
219 local gSize = sp + sz
|
flickerstreak@1
|
220
|
flickerstreak@1
|
221 for i = 1, n do
|
flickerstreak@1
|
222 if self.buttons[i] == nil then
|
flickerstreak@1
|
223 table.insert(self.buttons, self.class.button:acquire(self.barFrame, self.config.btnConfig, i))
|
flickerstreak@1
|
224 end
|
flickerstreak@1
|
225 local b = self.buttons[i]
|
flickerstreak@1
|
226 if b == nil then
|
flickerstreak@1
|
227 break -- handling for button types that support limited numbers
|
flickerstreak@1
|
228 end
|
flickerstreak@1
|
229 b:PlaceButton("TOPLEFT", sp + gSize * math.fmod(i-1,c), - (sp + gSize * math.floor((i-1)/c)), sz)
|
flickerstreak@1
|
230 end
|
flickerstreak@1
|
231
|
flickerstreak@1
|
232 -- b == nil, above, should always be the case if and only if i == n. ReBar never monkeys
|
flickerstreak@1
|
233 -- with buttons in the middle of the sequence: it always adds or removes on the array end
|
flickerstreak@1
|
234 while #self.buttons > n do
|
flickerstreak@1
|
235 self.class.button:release(table.remove(self.buttons))
|
flickerstreak@1
|
236 end
|
flickerstreak@1
|
237
|
flickerstreak@1
|
238 end
|
flickerstreak@1
|
239
|
flickerstreak@1
|
240
|
flickerstreak@1
|
241 function ReBar.prototype:StoreAnchor(f, p, rp, x, y)
|
flickerstreak@1
|
242 local name = f:GetName()
|
flickerstreak@1
|
243 -- no point if we can't store the name or the offsets are incomplete
|
flickerstreak@1
|
244 if name and x and y then
|
flickerstreak@1
|
245 self.config.anchor = {
|
flickerstreak@1
|
246 to = name,
|
flickerstreak@1
|
247 point = p,
|
flickerstreak@1
|
248 relPoint = rp or p,
|
flickerstreak@1
|
249 x = x,
|
flickerstreak@1
|
250 y = y
|
flickerstreak@1
|
251 }
|
flickerstreak@1
|
252 end
|
flickerstreak@1
|
253 end
|
flickerstreak@1
|
254
|
flickerstreak@1
|
255
|
flickerstreak@1
|
256
|
flickerstreak@1
|
257 -- mouse event handlers (clicking/dragging/resizing the bar)
|
flickerstreak@1
|
258 function ReBar.prototype:BeginDrag()
|
flickerstreak@1
|
259 local f = self.barFrame
|
flickerstreak@1
|
260 f:StartMoving()
|
flickerstreak@1
|
261 f.isMoving = true
|
flickerstreak@1
|
262 f:SetScript("OnUpdate", function() self:StickyIndicatorUpdate() end)
|
flickerstreak@1
|
263 end
|
flickerstreak@1
|
264
|
flickerstreak@1
|
265 function ReBar.prototype:FinishDrag()
|
flickerstreak@1
|
266 local f, p, rp, x, y
|
flickerstreak@1
|
267 local bf = self.barFrame
|
flickerstreak@1
|
268
|
flickerstreak@1
|
269 bf:StopMovingOrSizing()
|
flickerstreak@1
|
270 bf.isMoving = false
|
flickerstreak@1
|
271
|
flickerstreak@1
|
272 bf:SetScript("OnUpdate",nil)
|
flickerstreak@1
|
273 if IsShiftKeyDown() then
|
flickerstreak@1
|
274 f, p, rp, x, y = self:GetStickyAnchor()
|
flickerstreak@1
|
275 ReBarStickyIndicator1:Hide()
|
flickerstreak@1
|
276 ReBarStickyIndicator2:Hide()
|
flickerstreak@1
|
277 end
|
flickerstreak@1
|
278
|
flickerstreak@1
|
279 if f == nil then
|
flickerstreak@1
|
280 f = UIParent
|
flickerstreak@1
|
281 local _
|
flickerstreak@1
|
282 _, p,rp,x,y = self:GetClosestPointTo(f)
|
flickerstreak@1
|
283 end
|
flickerstreak@1
|
284
|
flickerstreak@1
|
285 if f then
|
flickerstreak@1
|
286 self:StoreAnchor(f,p,rp,x,y)
|
flickerstreak@1
|
287 self:ApplyAnchor()
|
flickerstreak@1
|
288 end
|
flickerstreak@1
|
289 end
|
flickerstreak@1
|
290
|
flickerstreak@1
|
291 function ReBar.prototype:BeginBarResize( sizingPoint )
|
flickerstreak@1
|
292 local f = self.barFrame
|
flickerstreak@1
|
293 f:StartSizing(sizingPoint)
|
flickerstreak@1
|
294 f.resizing = true
|
flickerstreak@1
|
295 f:SetScript("OnUpdate",function() self:ReflowButtons() end)
|
flickerstreak@1
|
296 end
|
flickerstreak@1
|
297
|
flickerstreak@1
|
298 function ReBar.prototype:BeginButtonResize( sizingPoint, mouseBtn )
|
flickerstreak@1
|
299 local f = self.barFrame
|
flickerstreak@1
|
300 f:StartSizing(sizingPoint)
|
flickerstreak@1
|
301 f.resizing = true
|
flickerstreak@1
|
302 local r = self.config.rows
|
flickerstreak@1
|
303 local c = self.config.columns
|
flickerstreak@1
|
304 local s = self.config.spacing
|
flickerstreak@1
|
305 local sz = self.config.size
|
flickerstreak@1
|
306 if mouseBtn == "LeftButton" then
|
flickerstreak@1
|
307 f:SetMinResize(c*(12 + 2*s) +1, r*(12 + 2*s) +1)
|
flickerstreak@1
|
308 f:SetScript("OnUpdate",function() self:DragSizeButtons() end)
|
flickerstreak@1
|
309 elseif mouseBtn == "RightButton" then
|
flickerstreak@1
|
310 f:SetMinResize(c*sz+1, r*sz+1)
|
flickerstreak@1
|
311 f:SetScript("OnUpdate",function() self:DragSizeSpacing() end)
|
flickerstreak@1
|
312 end
|
flickerstreak@1
|
313 end
|
flickerstreak@1
|
314
|
flickerstreak@1
|
315 function ReBar.prototype:FinishResize()
|
flickerstreak@1
|
316 local f = self.barFrame
|
flickerstreak@1
|
317 f:StopMovingOrSizing()
|
flickerstreak@1
|
318 f.resizing = false
|
flickerstreak@1
|
319 f:SetScript("OnUpdate",nil)
|
flickerstreak@1
|
320 self:ApplySize()
|
flickerstreak@1
|
321 end
|
flickerstreak@1
|
322
|
flickerstreak@1
|
323
|
flickerstreak@1
|
324
|
flickerstreak@1
|
325
|
flickerstreak@1
|
326 -- sticky anchoring functions
|
flickerstreak@1
|
327 function ReBar.prototype:StickyIndicatorUpdate()
|
flickerstreak@1
|
328 local si1 = ReBarStickyIndicator1
|
flickerstreak@1
|
329 local si2 = ReBarStickyIndicator2
|
flickerstreak@1
|
330 if IsShiftKeyDown() then
|
flickerstreak@1
|
331 local f, p, rp, x, y = self:GetStickyAnchor()
|
flickerstreak@1
|
332 if f then
|
flickerstreak@1
|
333 si1:ClearAllPoints()
|
flickerstreak@1
|
334 si2:ClearAllPoints()
|
flickerstreak@1
|
335 si1:SetPoint("CENTER",self.barFrame,p,0,0)
|
flickerstreak@1
|
336 si2:SetPoint("CENTER",f,rp,x,y)
|
flickerstreak@1
|
337 si1:Show()
|
flickerstreak@1
|
338 si2:Show()
|
flickerstreak@1
|
339 return nil
|
flickerstreak@1
|
340 end
|
flickerstreak@1
|
341 end
|
flickerstreak@1
|
342 si1:Hide()
|
flickerstreak@1
|
343 si2:Hide()
|
flickerstreak@1
|
344 si1:ClearAllPoints()
|
flickerstreak@1
|
345 si2:ClearAllPoints()
|
flickerstreak@1
|
346 end
|
flickerstreak@1
|
347
|
flickerstreak@1
|
348 function ReBar.prototype:CheckAnchorable(f)
|
flickerstreak@1
|
349 -- can't anchor to self or to a hidden frame
|
flickerstreak@1
|
350 if f == self.barFrame or not(f:IsShown()) then return false end
|
flickerstreak@1
|
351
|
flickerstreak@1
|
352 -- also can't anchor to frames that are anchored to self
|
flickerstreak@1
|
353 for i = 1, f:GetNumPoints() do
|
flickerstreak@1
|
354 local _, f2 = f:GetPoint(i)
|
flickerstreak@1
|
355 if f2 == self.barFrame then return false end
|
flickerstreak@1
|
356 end
|
flickerstreak@1
|
357
|
flickerstreak@1
|
358 return true
|
flickerstreak@1
|
359 end
|
flickerstreak@1
|
360
|
flickerstreak@1
|
361
|
flickerstreak@1
|
362 function ReBar.prototype:GetStickyAnchor()
|
flickerstreak@1
|
363 local snapRange = (self.config.size + self.config.spacing)
|
flickerstreak@1
|
364 local r2, f, p, rp, x, y = self:GetClosestAnchor()
|
flickerstreak@1
|
365
|
flickerstreak@1
|
366 if f and p then
|
flickerstreak@1
|
367 local xx, yy = pointFindTable[p](f)
|
flickerstreak@1
|
368 if r2 and r2 < (snapRange*snapRange) then
|
flickerstreak@1
|
369 if xx or math.abs(x) < snapRange then x = 0 end
|
flickerstreak@1
|
370 if yy or math.abs(y) < snapRange then y = 0 end
|
flickerstreak@1
|
371 elseif not(yy) and math.abs(x) < snapRange then
|
flickerstreak@1
|
372 x = 0
|
flickerstreak@1
|
373 elseif not(xx) and math.abs(y) < snapRange then
|
flickerstreak@1
|
374 y = 0
|
flickerstreak@1
|
375 else
|
flickerstreak@1
|
376 f = nil -- nothing in range
|
flickerstreak@1
|
377 end
|
flickerstreak@1
|
378 end
|
flickerstreak@1
|
379 return f, p, rp, x, y
|
flickerstreak@1
|
380 end
|
flickerstreak@1
|
381
|
flickerstreak@1
|
382 function ReBar.prototype:GetClosestAnchor()
|
flickerstreak@1
|
383 -- choose the closest anchor point on the list of target frames
|
flickerstreak@1
|
384 local range2, frame, point, relPoint, offsetX, offsetY
|
flickerstreak@1
|
385
|
flickerstreak@1
|
386 for f, tgtRegion in pairs(stickyTargets) do
|
flickerstreak@1
|
387 if self:CheckAnchorable(f) then
|
flickerstreak@1
|
388 local r2 ,p, rp, x, y = self:GetClosestPointTo(f,tgtRegion)
|
flickerstreak@1
|
389 if r2 then
|
flickerstreak@1
|
390 if not(range2 and range2 < r2) then
|
flickerstreak@1
|
391 range2, frame, point, relPoint, offsetX, offsetY = r2, f, p, rp, x, y
|
flickerstreak@1
|
392 end
|
flickerstreak@1
|
393 end
|
flickerstreak@1
|
394 end
|
flickerstreak@1
|
395 end
|
flickerstreak@1
|
396
|
flickerstreak@1
|
397 return range2, frame, point, relPoint, offsetX, offsetY
|
flickerstreak@1
|
398 end
|
flickerstreak@1
|
399
|
flickerstreak@1
|
400 function ReBar.prototype:GetClosestPointTo(f,inside)
|
flickerstreak@1
|
401 local range2, point, relPoint, offsetX, offsetY
|
flickerstreak@1
|
402 local pft = pointFindTable
|
flickerstreak@1
|
403 local cx, cy = self.barFrame:GetCenter()
|
flickerstreak@1
|
404 local fcx, fcy = f:GetCenter()
|
flickerstreak@1
|
405 local fh = f:GetHeight()
|
flickerstreak@1
|
406 local fw = f:GetWidth()
|
flickerstreak@1
|
407
|
flickerstreak@1
|
408 -- compute whether edge bisector intersects target edge
|
flickerstreak@1
|
409 local dcx = math.abs(cx-fcx) < fw/2 and (cx-fcx)
|
flickerstreak@1
|
410 local dcy = math.abs(cy-fcy) < fh/2 and (cy-fcy)
|
flickerstreak@1
|
411
|
flickerstreak@1
|
412 for p, func in pairs(pft) do
|
flickerstreak@1
|
413 local rp, x, y
|
flickerstreak@1
|
414 if inside == outsideFrame then
|
flickerstreak@1
|
415 rp = oppositePointTable[p]
|
flickerstreak@1
|
416 x, y = self:GetOffsetToPoint(f, func, pft[rp])
|
flickerstreak@1
|
417 else
|
flickerstreak@1
|
418 rp = p
|
flickerstreak@1
|
419 x, y = self:GetOffsetToPoint(f, func, func)
|
flickerstreak@1
|
420 end
|
flickerstreak@1
|
421
|
flickerstreak@1
|
422 -- if anchoring to an edge, only anchor if the center point overlaps the other edge
|
flickerstreak@1
|
423 if (x or dcx) and (y or dcy) then
|
flickerstreak@1
|
424 local r2 = (x or 0)^2 + (y or 0)^2
|
flickerstreak@1
|
425 if range2 == nil or r2 < range2 then
|
flickerstreak@1
|
426 range2, point, relPoint, offsetX, offsetY = r2, p, rp, x or dcx, y or dcy
|
flickerstreak@1
|
427 end
|
flickerstreak@1
|
428 end
|
flickerstreak@1
|
429 end
|
flickerstreak@1
|
430 return range2, point, relPoint, offsetX, offsetY
|
flickerstreak@1
|
431 end
|
flickerstreak@1
|
432
|
flickerstreak@1
|
433 function ReBar.prototype:GetOffsetToPoint(f,func,ffunc)
|
flickerstreak@1
|
434 local x, y = func(self.barFrame) -- coordinates of the point on this frame
|
flickerstreak@1
|
435 local fx, fy = ffunc(f) -- coordinates of the point on the target frame
|
flickerstreak@1
|
436 -- guarantees: if x then fx, if y then fy
|
flickerstreak@1
|
437 return x and (x-fx), y and (y-fy)
|
flickerstreak@1
|
438 end
|
flickerstreak@1
|
439
|
flickerstreak@1
|
440
|
flickerstreak@1
|
441
|
flickerstreak@1
|
442
|
flickerstreak@1
|
443
|
flickerstreak@1
|
444
|
flickerstreak@1
|
445 -- utility function to get the height, width, and button size attributes
|
flickerstreak@1
|
446 function ReBar.prototype:GetLayout()
|
flickerstreak@1
|
447 local c = self.config
|
flickerstreak@1
|
448 local f = self.barFrame
|
flickerstreak@1
|
449 return f:GetWidth(), f:GetHeight(), c.size, c.rows, c.columns, c.spacing
|
flickerstreak@1
|
450 end
|
flickerstreak@1
|
451
|
flickerstreak@1
|
452 -- add and remove buttons dynamically as the bar is resized
|
flickerstreak@1
|
453 function ReBar.prototype:ReflowButtons()
|
flickerstreak@1
|
454 local w, h, sz, r, c, sp = self:GetLayout()
|
flickerstreak@1
|
455
|
flickerstreak@1
|
456 self.config.rows = math.floor( (h - sp) / (sz + sp) )
|
flickerstreak@1
|
457 self.config.columns = math.floor( (w - sp) / (sz + sp) )
|
flickerstreak@1
|
458
|
flickerstreak@1
|
459 if self.config.rows ~= r or self.config.columns ~= c then
|
flickerstreak@1
|
460 self:LayoutButtons()
|
flickerstreak@1
|
461 end
|
flickerstreak@1
|
462 end
|
flickerstreak@1
|
463
|
flickerstreak@1
|
464
|
flickerstreak@1
|
465 -- change the size of buttons as the bar is resized
|
flickerstreak@1
|
466 function ReBar.prototype:DragSizeButtons()
|
flickerstreak@1
|
467 local w, h, sz, r, c, sp = self:GetLayout()
|
flickerstreak@1
|
468
|
flickerstreak@1
|
469 local newSzW = math.floor((w - (c+1)*sp)/c)
|
flickerstreak@1
|
470 local newSzH = math.floor((h - (r+1)*sp)/r)
|
flickerstreak@1
|
471
|
flickerstreak@1
|
472 self.config.size = math.max(12, math.min(newSzW, newSzH))
|
flickerstreak@1
|
473
|
flickerstreak@1
|
474 if self.config.size ~= sz then
|
flickerstreak@1
|
475 self:LayoutButtons()
|
flickerstreak@1
|
476 self:UpdateResizeTooltip()
|
flickerstreak@1
|
477 end
|
flickerstreak@1
|
478 end
|
flickerstreak@1
|
479
|
flickerstreak@1
|
480
|
flickerstreak@1
|
481 -- change the spacing of buttons as the bar is resized
|
flickerstreak@1
|
482 function ReBar.prototype:DragSizeSpacing()
|
flickerstreak@1
|
483 local w, h, sz, r, c, sp = self:GetLayout()
|
flickerstreak@1
|
484
|
flickerstreak@1
|
485 local newSpW = math.floor((w - c*sz)/(c+1))
|
flickerstreak@1
|
486 local newSpH = math.floor((h - r*sz)/(r+1))
|
flickerstreak@1
|
487
|
flickerstreak@1
|
488 self.config.spacing = math.max(0, math.min(newSpW, newSpH))
|
flickerstreak@1
|
489
|
flickerstreak@1
|
490 if self.config.spacing ~= sp then
|
flickerstreak@1
|
491 self:LayoutButtons()
|
flickerstreak@1
|
492 self:UpdateResizeTooltip()
|
flickerstreak@1
|
493 end
|
flickerstreak@1
|
494 end
|
flickerstreak@1
|
495
|
flickerstreak@1
|
496
|
flickerstreak@1
|
497 -- update the drag tooltip to indicate current sizes
|
flickerstreak@1
|
498 function ReBar.prototype:UpdateResizeTooltip()
|
flickerstreak@1
|
499 GameTooltipTextRight4:SetText(self.config.size)
|
flickerstreak@1
|
500 GameTooltipTextRight5:SetText(self.config.spacing)
|
flickerstreak@1
|
501 GameTooltip:Show()
|
flickerstreak@1
|
502 end
|
flickerstreak@1
|
503
|
flickerstreak@1
|
504 function ReBar.prototype:ShowTooltip()
|
flickerstreak@1
|
505 GameTooltip:SetOwner(self.barFrame, "ANCHOR_TOPRIGHT")
|
flickerstreak@1
|
506 GameTooltip:AddLine("Bar "..self.barID)
|
flickerstreak@1
|
507 GameTooltip:AddLine("Drag to move")
|
flickerstreak@1
|
508 GameTooltip:AddLine("Shift-drag for sticky mode")
|
flickerstreak@1
|
509 GameTooltip:AddLine("Right-click for options")
|
flickerstreak@1
|
510 GameTooltip:Show()
|
flickerstreak@1
|
511 end
|
flickerstreak@1
|
512
|
flickerstreak@1
|
513 function ReBar.prototype:ShowButtonResizeTooltip(point)
|
flickerstreak@1
|
514 GameTooltip:SetOwner(self.barFrame, "ANCHOR_"..point)
|
flickerstreak@1
|
515 GameTooltip:AddLine("Drag to resize buttons")
|
flickerstreak@1
|
516 GameTooltip:AddLine("Right-click-drag")
|
flickerstreak@1
|
517 GameTooltip:AddLine("to change spacing")
|
flickerstreak@1
|
518 GameTooltip:AddDoubleLine("Size: ", "0")
|
flickerstreak@1
|
519 GameTooltip:AddDoubleLine("Spacing: ", "0")
|
flickerstreak@1
|
520 self:UpdateResizeTooltip()
|
flickerstreak@1
|
521 end
|
flickerstreak@1
|
522
|
flickerstreak@1
|
523 function ReBar.prototype:ShowBarResizeTooltip(point)
|
flickerstreak@1
|
524 GameTooltip:SetOwner(self.barFrame, "ANCHOR_"..point)
|
flickerstreak@1
|
525 GameTooltip:AddLine("Drag to add/remove buttons")
|
flickerstreak@1
|
526 GameTooltip:Show()
|
flickerstreak@1
|
527 end
|