comparison classes/Overlay.lua @ 122:a2d2f23137c8

- Rearranged and consolidated some files in modules directory - Added 'classes' directory, moved Bar and Overlay there - Added Button, ActionButton, and GridProxy classes, not in use yet
author Flick <flickerstreak@gmail.com>
date Mon, 23 Feb 2009 18:56:57 +0000
parents
children 5c0591a31163
comparison
equal deleted inserted replaced
121:fb6c3a642ae3 122:a2d2f23137c8
1 local ReAction = ReAction
2 local L = ReAction.L
3 local CreateFrame = CreateFrame
4 local InCombatLockdown = InCombatLockdown
5 local floor = math.floor
6 local min = math.min
7 local format = string.format
8 local GameTooltip = GameTooltip
9 local Bar = ReAction.Bar
10 local GetSize = Bar.GetSize
11 local SetSize = Bar.SetSize
12 local GetButtonSize = Bar.GetButtonSize
13 local GetButtonGrid = Bar.GetButtonGrid
14 local SetButtonSize = Bar.SetButtonSize
15 local SetButtonGrid = Bar.SetButtonGrid
16 local ApplyAnchor = Bar.ApplyAnchor
17 local GameTooltipTextRight1 = GameTooltipTextRight1
18 local GameTooltipTextRight2 = GameTooltipTextRight2
19 local GameTooltipTextRight3 = GameTooltipTextRight3
20
21 local KB = LibStub("LibKeyBound-1.0")
22
23 ReAction:UpdateRevision("$Revision$")
24
25
26 --
27 -- Wrap some of the bar manipulators to make them state-aware
28 --
29 local function SetAnchor( bar, point, frame, relPoint, x, y )
30 local state = bar:GetState()
31 if state then
32 local anchorstate = bar:GetStateProperty(state, "anchorEnable")
33 if anchorstate then
34 bar:SetStateProperty(state, "anchorFrame", frame)
35 bar:SetStateProperty(state, "anchorPoint", point)
36 bar:SetStateProperty(state, "anchorRelPoint", relPoint)
37 bar:SetStateProperty(state, "anchorX", x or 0)
38 bar:SetStateProperty(state, "anchorY", y or 0)
39 bar:SetAnchor(bar:GetAnchor())
40 return
41 end
42 end
43 bar:SetAnchor(point, frame, relPoint, x, y)
44 end
45
46 local function GetStateScale( bar )
47 local state = bar:GetState()
48 if state and bar:GetStateProperty(state, "enableScale") then
49 return bar:GetStateProperty(state, "scale")
50 end
51 end
52
53 local function SetStateScale( bar, scale )
54 local state = bar:GetState()
55 if state and bar:GetStateProperty(state, "enableScale") then
56 bar:SetStateProperty(state, "scale", scale)
57 end
58 end
59
60
61 --
62 -- Bar config overlay
63 --
64
65 local function GetNormalTextColor()
66 return 1.0, 1.0, 1.0, 1.0
67 end
68
69 local function GetAnchoredTextColor()
70 return 1.0, 1.0, 1.0, 1.0
71 end
72
73 local function GetNormalBgColor()
74 return 0.7, 0.7, 1.0, 0.3
75 end
76
77 local function GetAnchoredBgColor()
78 return 0.9, 0.2, 0.7, 0.3
79 end
80
81 local function StoreSize(bar)
82 local f = bar:GetFrame()
83 SetSize( bar, f:GetWidth(), f:GetHeight() )
84 end
85
86 local function StoreExtents(bar)
87 local f = bar:GetFrame()
88 local p, fr, rp, x, y = f:GetPoint(1)
89 fr = fr and fr:GetName() or "UIParent"
90 SetAnchor( bar, p, fr, rp, x, y )
91 SetSize( bar, f:GetWidth(), f:GetHeight() )
92 end
93
94 local function RecomputeButtonSize(bar)
95 local w, h = GetSize(bar)
96 local bw, bh = GetButtonSize(bar)
97 local r, c, s = GetButtonGrid(bar)
98
99 local scaleW = (floor(w/c) - s) / bw
100 local scaleH = (floor(h/r) - s) / bh
101 local scale = min(scaleW, scaleH)
102
103 SetButtonSize(bar, scale * bw, scale * bh, s)
104 end
105
106 local function ComputeBarScale(bar)
107 local w, h = bar.controlFrame:GetWidth() - 8, bar.controlFrame:GetHeight() - 8
108 local bw, bh = GetButtonSize(bar)
109 local r, c, s = GetButtonGrid(bar)
110
111 local scaleW = w / (c*(bw+s))
112 local scaleH = h / (r*(bh+s))
113 local scale = min(scaleW, scaleH)
114
115 if scale > 2.5 then
116 scale = 2.5
117 elseif scale < 0.25 then
118 scale = 0.25
119 end
120
121 return scale
122 end
123
124 local function RecomputeButtonSpacing(bar)
125 local w, h = GetSize(bar)
126 local bw, bh = GetButtonSize(bar)
127 local r, c, s = GetButtonGrid(bar)
128
129 SetButtonGrid(bar,r,c,min(floor(w/c) - bw, floor(h/r) - bh))
130 end
131
132 local function RecomputeGrid(bar)
133 local w, h = GetSize(bar)
134 local bw, bh = GetButtonSize(bar)
135 local r, c, s = GetButtonGrid(bar)
136
137 SetButtonGrid(bar, floor(h/(bh+s)), floor(w/(bw+s)), s)
138 end
139
140 local function ClampToButtons(bar)
141 local bw, bh = GetButtonSize(bar)
142 local r, c, s = GetButtonGrid(bar)
143 SetSize(bar, (bw+s)*c + 1, (bh+s)*r + 1)
144 end
145
146 local function HideGameTooltip()
147 GameTooltip:Hide()
148 end
149
150 local anchorInside = { inside = true }
151 local anchorOutside = { outside = true }
152 local edges = { "BOTTOM", "TOP", "LEFT", "RIGHT" }
153 local oppositeEdges = {
154 TOP = "BOTTOM",
155 BOTTOM = "TOP",
156 LEFT = "RIGHT",
157 RIGHT = "LEFT"
158 }
159 local pointsOnEdge = {
160 BOTTOM = { "BOTTOM", "BOTTOMLEFT", "BOTTOMRIGHT", },
161 TOP = { "TOP", "TOPLEFT", "TOPRIGHT", },
162 RIGHT = { "RIGHT", "BOTTOMRIGHT", "TOPRIGHT", },
163 LEFT = { "LEFT", "BOTTOMLEFT", "TOPLEFT", },
164 }
165 local edgeSelector = {
166 BOTTOM = 1, -- select x of x,y
167 TOP = 1, -- select x of x,y
168 LEFT = 2, -- select y of x,y
169 RIGHT = 2, -- select y of x,y
170 }
171 local snapPoints = {
172 [anchorOutside] = {
173 BOTTOMLEFT = {"BOTTOMRIGHT","TOPLEFT","TOPRIGHT"},
174 BOTTOM = {"TOP"},
175 BOTTOMRIGHT = {"BOTTOMLEFT","TOPRIGHT","TOPLEFT"},
176 RIGHT = {"LEFT"},
177 TOPRIGHT = {"TOPLEFT","BOTTOMRIGHT","BOTTOMLEFT"},
178 TOP = {"BOTTOM"},
179 TOPLEFT = {"TOPRIGHT","BOTTOMLEFT","BOTTOMRIGHT"},
180 LEFT = {"RIGHT"},
181 CENTER = {"CENTER"}
182 },
183 [anchorInside] = {
184 BOTTOMLEFT = {"BOTTOMLEFT"},
185 BOTTOM = {"BOTTOM"},
186 BOTTOMRIGHT = {"BOTTOMRIGHT"},
187 RIGHT = {"RIGHT"},
188 TOPRIGHT = {"TOPRIGHT"},
189 TOP = {"TOP"},
190 TOPLEFT = {"TOPLEFT"},
191 LEFT = {"LEFT"},
192 CENTER = {"CENTER"}
193 }
194 }
195 local insidePointOffsetFuncs = {
196 BOTTOMLEFT = function(x, y) return x, y end,
197 BOTTOM = function(x, y) return 0, y end,
198 BOTTOMRIGHT = function(x, y) return -x, y end,
199 RIGHT = function(x, y) return -x, 0 end,
200 TOPRIGHT = function(x, y) return -x, -y end,
201 TOP = function(x, y) return 0, -y end,
202 TOPLEFT = function(x, y) return x, -y end,
203 LEFT = function(x, y) return x, 0 end,
204 CENTER = function(x, y) return x, y end,
205 }
206 local pointCoordFuncs = {
207 BOTTOMLEFT = function(f) return f:GetLeft(), f:GetBottom() end,
208 BOTTOM = function(f) return nil, f:GetBottom() end,
209 BOTTOMRIGHT = function(f) return f:GetRight(), f:GetBottom() end,
210 RIGHT = function(f) return f:GetRight(), nil end,
211 TOPRIGHT = function(f) return f:GetRight(), f:GetTop() end,
212 TOP = function(f) return nil, f:GetTop() end,
213 TOPLEFT = function(f) return f:GetLeft(), f:GetTop() end,
214 LEFT = function(f) return f:GetLeft(), nil end,
215 CENTER = function(f) return f:GetCenter() end,
216 }
217 local edgeBoundsFuncs = {
218 BOTTOM = function(f) return f:GetLeft(), f:GetRight() end,
219 LEFT = function(f) return f:GetBottom(), f:GetTop() end
220 }
221 edgeBoundsFuncs.TOP = edgeBoundsFuncs.BOTTOM
222 edgeBoundsFuncs.RIGHT = edgeBoundsFuncs.LEFT
223 local cornerTexCoords = {
224 -- ULx, ULy, LLx, LLy, URx, URy, LRx, LRy
225 TOPLEFT = { 1, 1, 1, 0, 0, 1, 0, 0 },
226 TOPRIGHT = { 1, 0, 0, 0, 1, 1, 0, 1 },
227 BOTTOMLEFT = { 0, 1, 1, 1, 0, 0, 1, 0 },
228 BOTTOMRIGHT = { 0, 0, 0, 1, 1, 0, 1, 1 },
229 }
230
231 -- Returns absolute coordinates x,y of the named point 'p' of frame 'f'
232 local function GetPointCoords( f, p )
233 local x, y = pointCoordFuncs[p](f)
234 if not(x and y) then
235 local cx, cy = f:GetCenter()
236 x = x or cx
237 y = y or cy
238 end
239 return x, y
240 end
241
242
243 -- Returns true if frame 'f1' can be anchored to frame 'f2'
244 local function CheckAnchorable( f1, f2 )
245 -- can't anchor a frame to itself or to nil
246 if f1 == f2 or f2 == nil then
247 return false
248 end
249
250 -- can always anchor to UIParent
251 if f2 == UIParent then
252 return true
253 end
254
255 -- also can't do circular anchoring of frames
256 -- walk the anchor chain, which generally shouldn't be that expensive
257 -- (who nests draggables that deep anyway?)
258 for i = 1, f2:GetNumPoints() do
259 local _, f = f2:GetPoint(i)
260 if not f then f = f2:GetParent() end
261 return CheckAnchorable(f1,f)
262 end
263
264 return true
265 end
266
267 -- Returns true if frames f1 and f2 specified edges overlap
268 local function CheckEdgeOverlap( f1, f2, e )
269 local l1, u1 = edgeBoundsFuncs[e](f1)
270 local l2, u2 = edgeBoundsFuncs[e](f2)
271 return l1 <= l2 and l2 <= u1 or l2 <= l1 and l1 <= u2
272 end
273
274 -- Returns true if point p1 on frame f1 overlaps edge e2 on frame f2
275 local function CheckPointEdgeOverlap( f1, p1, f2, e2 )
276 local l, u = edgeBoundsFuncs[e2](f2)
277 local x, y = GetPointCoords(f1,p1)
278 x = select(edgeSelector[e2], x, y)
279 return l <= x and x <= u
280 end
281
282 -- Returns the distance between corresponding edges. It is
283 -- assumed that the passed in edges e1 and e2 are the same or opposites
284 local function GetEdgeDistance( f1, f2, e1, e2 )
285 local x1, y1 = pointCoordFuncs[e1](f1)
286 local x2, y2 = pointCoordFuncs[e2](f2)
287 return math.abs((x1 or y1) - (x2 or y2))
288 end
289
290 local globalSnapTargets = { [UIParent] = anchorInside }
291
292 local function GetClosestFrameEdge(f1,f2,a)
293 local dist, edge, opp
294 if f2:IsVisible() and CheckAnchorable(f1,f2) then
295 for _, e in pairs(edges) do
296 local o = a.inside and e or oppositeEdges[e]
297 if CheckEdgeOverlap(f1,f2,e) then
298 local d = GetEdgeDistance(f1, f2, e, o)
299 if not dist or (d < dist) then
300 dist, edge, opp = d, e, o
301 end
302 end
303 end
304 end
305 return dist, edge, opp
306 end
307
308 local function GetClosestVisibleEdge( f )
309 local r, o, e1, e2
310 local a = anchorOutside
311 for _, b in ReAction:IterateBars() do
312 local d, e, opp = GetClosestFrameEdge(f,b:GetFrame(),a)
313 if d and (not r or d < r) then
314 r, o, e1, e2 = d, b:GetFrame(), e, opp
315 end
316 end
317 for f2, a2 in pairs(globalSnapTargets) do
318 local d, e, opp = GetClosestFrameEdge(f,f2,a2)
319 if d and (not r or d < r) then
320 r, o, e1, e2, a = d, f2, e, opp, a2
321 end
322 end
323 return o, e1, e2, a
324 end
325
326 local function GetClosestVisiblePoint(f1)
327 local f2, e1, e2, a = GetClosestVisibleEdge(f1)
328 if f2 then
329 local rsq, p, rp, x, y
330 -- iterate pointsOnEdge in order and use < to prefer edge centers to corners
331 for _, p1 in ipairs(pointsOnEdge[e1]) do
332 if CheckPointEdgeOverlap(f1,p1,f2,e2) then
333 for _, p2 in pairs(snapPoints[a][p1]) do
334 local x1, y1 = GetPointCoords(f1,p1)
335 local x2, y2 = GetPointCoords(f2,p2)
336 local dx = x1 - x2
337 local dy = y1 - y2
338 local rsq2 = dx*dx + dy*dy
339 if not rsq or rsq2 < rsq then
340 rsq, p, rp, x, y = rsq2, p1, p2, dx, dy
341 end
342 end
343 end
344 end
345 return f2, p, rp, x, y
346 end
347 end
348
349 local function GetClosestPointSnapped(f1, rx, ry, xOff, yOff)
350 local o, p, rp, x, y = GetClosestVisiblePoint(f1)
351 local s = false
352
353 local insideOffsetFunc = p and insidePointOffsetFuncs[p]
354 local coordFunc = p and pointCoordFuncs[p]
355 if not insideOffsetFunc or not coordFunc then
356 return
357 end
358
359 local sx, sy = insideOffsetFunc(xOff or 0, yOff or 0)
360 local xx, yy = coordFunc(f1)
361 if xx and yy then
362 if math.abs(x) <= rx then
363 if math.abs(y) <= ry then
364 x = sx
365 y = sy
366 s = true
367 elseif CheckEdgeOverlap(f1,o,"LEFT") then
368 x = sx
369 s = true
370 end
371 elseif math.abs(y) <= ry and CheckEdgeOverlap(f1,o,"TOP") then
372 y = sy
373 s = true
374 end
375 elseif xx then
376 if math.abs(x) <= rx then
377 x = sx
378 s = true
379 if math.abs(y) <= ry then
380 y = sy
381 end
382 end
383 elseif yy then
384 if math.abs(y) <= ry then
385 y = sy
386 s = true
387 if math.abs(x) <= rx then
388 x = sx
389 end
390 end
391 end
392
393 -- correct for some Lua oddities with doubles
394 if x == -0 then x = 0 end
395 if y == -0 then y = 0 end
396
397 if s then
398 return o, p, rp, math.floor(x), math.floor(y)
399 end
400 end
401
402 local function CreateSnapIndicator()
403 local si = CreateFrame("Frame",nil,UIParent)
404 si:SetFrameStrata("HIGH")
405 si:SetHeight(16)
406 si:SetWidth(16)
407 local tex = si:CreateTexture()
408 tex:SetAllPoints()
409 tex:SetTexture("Interface\\AddOns\\ReAction\\img\\lock")
410 tex:SetBlendMode("ADD")
411 tex:SetDrawLayer("OVERLAY")
412 return si
413 end
414
415 local si1 = CreateSnapIndicator()
416 local si2 = CreateSnapIndicator()
417
418 local function DisplaySnapIndicator( f, rx, ry, xOff, yOff )
419 local o, p, rp, x, y, snap = GetClosestPointSnapped(f, rx, ry, xOff, yOff)
420 if o then
421 si1:ClearAllPoints()
422 si2:ClearAllPoints()
423 si1:SetPoint("CENTER", f, p, 0, 0)
424 local xx, yy = pointCoordFuncs[rp](o)
425 x = math.abs(x) <=rx and xx and 0 or x
426 y = math.abs(y) <=ry and yy and 0 or y
427 si2:SetPoint("CENTER", o, rp, x, y)
428 si1:Show()
429 si2:Show()
430 else
431 if si1:IsVisible() then
432 si1:Hide()
433 si2:Hide()
434 end
435 end
436 return o, p
437 end
438
439 local function HideSnapIndicator()
440 if si1:IsVisible() then
441 si1:Hide()
442 si2:Hide()
443 end
444 end
445
446 local function UpdateLabelString(bar)
447 local label = bar.controlLabelString
448 if label then
449 local name = bar.labelName
450 if name and bar.labelSubtext then
451 name = format("%s (%s)", name, bar.labelSubtext)
452 end
453 label:SetText(name or "")
454 end
455 end
456
457 local function CreateControls(bar)
458 local f = bar:GetFrame()
459
460 f:SetMovable(true)
461 f:SetResizable(true)
462
463 -- child of UIParent so that alpha and scale doesn't propagate to it
464 local overlay = CreateFrame("Button", nil, UIParent)
465 overlay:EnableMouse(true)
466 overlay:SetFrameLevel(3) -- set it above the buttons
467 overlay:SetPoint("TOPLEFT", f, "TOPLEFT", -4, 4)
468 overlay:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 4, -4)
469 overlay:SetBackdrop({
470 edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
471 tile = true,
472 tileSize = 16,
473 edgeSize = 16,
474 insets = { left = 0, right = 0, top = 0, bottom = 0 },
475 })
476
477 -- textures
478 local bgTex = overlay:CreateTexture(nil,"BACKGROUND")
479 bgTex:SetTexture(0.7,0.7,1.0,0.2)
480 bgTex:SetPoint("TOPLEFT",4,-4)
481 bgTex:SetPoint("BOTTOMRIGHT",-4,4)
482 local hTex = overlay:CreateTexture(nil,"HIGHLIGHT")
483 hTex:SetTexture(0.7,0.7,1.0,0.2)
484 hTex:SetPoint("TOPLEFT",4,-4)
485 hTex:SetPoint("BOTTOMRIGHT",-4,4)
486 hTex:SetBlendMode("ADD")
487 local aTex = overlay:CreateTexture(nil,"ARTWORK")
488 aTex:SetTexture("Interface\\AddOns\\ReAction\\img\\lock")
489 aTex:SetWidth(16)
490 aTex:SetHeight(16)
491 aTex:Hide()
492
493 -- label
494 local label = overlay:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
495 label:SetAllPoints()
496 label:SetJustifyH("CENTER")
497 label:SetShadowColor(0,0,0,1)
498 label:SetShadowOffset(3,-3)
499 label:SetTextColor(GetNormalTextColor())
500 label:SetText(bar:GetName())
501 label:Show()
502 bar.controlLabelString = label -- so that bar:SetLabel() can update it
503
504 local function UpdateAnchorDecoration()
505 local point, anchor, relPoint, x, y = f:GetPoint(1)
506 if point then
507 local ofsx, ofsy = insidePointOffsetFuncs[point](x,y)
508 if (anchor and anchor ~= UIParent) or (ofsx == 0 and ofsy == 0) then
509 bgTex:SetTexture( GetAnchoredBgColor() )
510 hTex:SetTexture( GetAnchoredBgColor() )
511 label:SetTextColor( GetAnchoredTextColor() )
512 aTex:ClearAllPoints()
513 aTex:SetPoint(point)
514 aTex:Show()
515 return
516 end
517 end
518 bgTex:SetTexture( GetNormalBgColor() )
519 hTex:SetTexture( GetNormalBgColor() )
520 label:SetTextColor( GetNormalTextColor() )
521 aTex:Hide()
522 end
523
524 local function StopResize()
525 f:StopMovingOrSizing()
526 f.isMoving = false
527 f:SetScript("OnUpdate",nil)
528 StoreSize(bar)
529 ClampToButtons(bar)
530 ReAction:RefreshOptions()
531 end
532
533 local function CornerUpdate()
534 local bw, bh = GetButtonSize(bar)
535 local r, c, s = GetButtonGrid(bar)
536 local ss = GetStateScale(bar)
537 if IsShiftKeyDown() then
538 if ss then
539 f:SetMinResize( ((s+bw)*c*0.25)/ss, ((s+bh)*r*0.25)/ss )
540 f:SetMaxResize( ((s+bw)*c*2.5 + 1)/ss, ((s+bh)*r*2.5 + 1)/ss )
541 scale = ComputeBarScale(bar)
542 else
543 f:SetMinResize( (s+12)*c+1, (s+12)*r+1 )
544 f:SetMaxResize( (s+128)*c+1, (s+128)*r+1 )
545 RecomputeButtonSize(bar)
546 end
547 elseif not ss and IsAltKeyDown() then
548 f:SetMinResize( bw*c, bh*r )
549 f:SetMaxResize( 2*bw*c, 2*bh*r )
550 RecomputeButtonSpacing(bar)
551 else
552 f:SetMinResize( bw+s+1, bh+s+1 )
553 f:SetMaxResize( 50*(bw+s)+1, 50*(bh+s)+1 )
554 RecomputeGrid(bar)
555 end
556 GameTooltipTextRight2:SetText(format("%d x %d",r,c))
557
558 local ss = GetStateScale(bar)
559 local state = bar:GetState()
560 if ss then
561 GameTooltipTextRight4:SetText(format("%d%%", scale*100))
562 else
563 local size = (bw == bh) and tostring(bw) or format("%d x %d",bw,bh)
564 GameTooltipTextRight3:SetText(size)
565 GameTooltipTextRight4:SetText(tostring(s))
566 end
567 end
568
569 -- corner drag handles
570 for _, point in pairs({"BOTTOMLEFT","TOPLEFT","BOTTOMRIGHT","TOPRIGHT"}) do
571 local corner = CreateFrame("Frame",nil,overlay)
572 corner:EnableMouse(true)
573 corner:SetWidth(16)
574 corner:SetHeight(16)
575 corner:SetPoint(point)
576
577 local tex = corner:CreateTexture(nil,"HIGHLIGHT")
578 tex:SetTexture("Interface\\AddOns\\ReAction\\img\\corner")
579 tex:SetTexCoord(unpack(cornerTexCoords[point]))
580 tex:SetBlendMode("ADD")
581 tex:SetAlpha(0.6)
582 tex:SetAllPoints()
583
584 corner:SetScript("OnMouseDown",
585 function(_,btn)
586 f:SetScript("OnUpdate", CornerUpdate)
587 f:StartSizing(point)
588 end
589 )
590 corner:SetScript("OnMouseUp",
591 function()
592 local ss = GetStateScale(bar)
593 if ss then
594 local state = bar:GetState()
595 SetStateScale(bar, ComputeBarScale(bar))
596 end
597 StopResize()
598 end)
599 corner:SetScript("OnEnter",
600 function()
601 local bw, bh = GetButtonSize(bar)
602 local r, c, s = bar:GetButtonGrid()
603 local size = (bw == bh) and tostring(bw) or format("%d x %d",bw,bh)
604 local ss = GetStateScale(bar)
605 local state = bar:GetState()
606 GameTooltip:SetOwner(f, "ANCHOR_"..point)
607 if ss then
608 GameTooltip:AddLine(format("%s (%s: %s)", bar:GetName(), L["State"], state))
609 else
610 GameTooltip:AddLine(bar:GetName())
611 end
612 GameTooltip:AddDoubleLine(format("|cffcccccc%s|r %s",L["Drag"],L["to add/remove buttons:"]), format("%d x %d",r,c))
613 if ss then
614 GameTooltip:AddLine(L["State Scale Override"])
615 GameTooltip:AddDoubleLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to change scale:"]), format("%d%%", bar:GetStateProperty(state,"scale")*100))
616 else
617 GameTooltip:AddDoubleLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to resize buttons:"]), tostring(floor(size)))
618 GameTooltip:AddDoubleLine(format("|cff0033cc%s|r %s",L["Hold Alt"], L["to change spacing:"]), tostring(floor(s)))
619 end
620 GameTooltip:Show()
621 end
622 )
623 corner:SetScript("OnLeave",
624 function()
625 GameTooltip:Hide()
626 f:SetScript("OnUpdate",nil)
627 end
628 )
629 end
630
631 overlay:RegisterForDrag("LeftButton")
632 overlay:RegisterForClicks("RightButtonUp")
633
634 overlay:SetScript("OnDragStart",
635 function()
636 f:StartMoving()
637 f.isMoving = true
638 local w,h = bar:GetButtonSize()
639 f:ClearAllPoints()
640 UpdateAnchorDecoration()
641 f:SetScript("OnUpdate", function()
642 if IsShiftKeyDown() then
643 local f, p = DisplaySnapIndicator(f,w,h)
644 else
645 HideSnapIndicator()
646 end
647 end)
648 end
649 )
650
651 local function UpdateDragTooltip()
652 GameTooltip:SetOwner(f, "ANCHOR_TOPRIGHT")
653 local ss = GetStateScale(bar)
654 local state = bar:GetState()
655 if ss then
656 GameTooltip:AddLine(format("%s (%s: %s)", bar:GetName(), L["State"], state))
657 else
658 GameTooltip:AddLine(bar:GetName())
659 end
660 GameTooltip:AddLine(format("|cffcccccc%s|r %s",L["Drag"],L["to move"]))
661 GameTooltip:AddLine(format("|cff00ff00%s|r %s",L["Hold Shift"],L["to anchor to nearby frames"]))
662 GameTooltip:AddLine(format("|cff00cccc%s|r %s",L["Right-click"],L["for options..."]))
663 local point, frame, relpoint, x, y = bar:GetFrame():GetPoint(1)
664 if point then
665 local ofsx, ofsy = insidePointOffsetFuncs[point](x,y)
666 if (frame and frame ~= UIParent) or (ofsx == 0 and ofsy == 0) then
667 frame = frame or UIParent
668 GameTooltip:AddLine(format("%s <%s>",L["Currently anchored to"],frame:GetName()))
669 end
670 end
671 GameTooltip:Show()
672 end
673
674 overlay:SetScript("OnDragStop",
675 function()
676 f:StopMovingOrSizing()
677 f.isMoving = false
678 f:SetScript("OnUpdate",nil)
679
680 if IsShiftKeyDown() then
681 local w, h = bar:GetButtonSize()
682 local a, p, rp, x, y = GetClosestPointSnapped(f,w,h)
683 if a then
684 f:ClearAllPoints()
685 f:SetPoint(p,a,rp,x,y)
686 end
687 HideSnapIndicator()
688 end
689
690 StoreExtents(bar)
691 ReAction:RefreshOptions()
692 UpdateDragTooltip()
693 UpdateAnchorDecoration()
694 end
695 )
696
697 overlay:SetScript("OnEnter",
698 function()
699 UpdateDragTooltip()
700 end
701 )
702
703 overlay:SetScript("OnLeave", HideGameTooltip)
704
705 overlay:SetScript("OnClick",
706 function()
707 ReAction:ShowEditor(bar)
708 end
709 )
710
711 function overlay:LIBKEYBOUND_ENABLED(evt)
712 self:SetFrameLevel(1)
713 end
714
715 function overlay:LIBKEYBOUND_DISABLED(evt)
716 self:SetFrameLevel(3)
717 end
718
719 function overlay:RefreshControls()
720 UpdateAnchorDecoration()
721 end
722
723 overlay:SetScript("OnShow", overlay.RefreshControls)
724
725 KB.RegisterCallback(overlay,"LIBKEYBOUND_ENABLED")
726 KB.RegisterCallback(overlay,"LIBKEYBOUND_DISABLED")
727
728 if ReAction:GetKeybindMode() then
729 overlay:SetFrameLevel(1)
730 end
731
732 bar:SetLabel(bar:GetName())
733 UpdateLabelString(bar)
734 UpdateAnchorDecoration()
735
736 return overlay
737 end
738
739
740 -- export methods to the Bar prototype
741
742 function Bar:ShowControls(show)
743 local f = self.controlFrame
744 if show then
745 if not f then
746 f = CreateControls(self)
747 self.controlFrame = f
748 end
749 f:Show()
750 elseif f then
751 f:Hide()
752 end
753 end
754
755 function Bar:RefreshControls()
756 if self.controlFrame and self.controlFrame:IsShown() then
757 self.controlFrame:RefreshControls()
758 end
759 end
760
761 function Bar:SetLabel(name)
762 self.labelName = name
763 UpdateLabelString(self)
764 end
765
766 function Bar:SetLabelSubtext(text)
767 self.labelSubtext = text
768 UpdateLabelString(self)
769 end