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