diff Bar.lua @ 33:c54c481ad0ed

- Moved bar control frame from ConfigUI to Bar - Added LICENSE.txt - added profile management options - other minor cleanup
author Flick <flickerstreak@gmail.com>
date Thu, 03 Apr 2008 20:25:40 +0000
parents 0d95ce7a9ec2
children c3c64e2def50
line wrap: on
line diff
--- a/Bar.lua	Thu Apr 03 16:59:16 2008 +0000
+++ b/Bar.lua	Thu Apr 03 20:25:40 2008 +0000
@@ -2,9 +2,16 @@
 local L = ReAction.L
 local _G = _G
 local CreateFrame = CreateFrame
+local InCombatLockdown = InCombatLockdown
+local floor = math.floor
+local min = math.min
+local format = string.format
+local GameTooltip = GameTooltip
+
+
 
 -- update ReAction revision if this file is newer
-local revision = tonumber(("$Revision: 1 $"):match("%d+"))
+local revision = tonumber(("$Revision$"):match("%d+"))
 if revision > ReAction.revision then
   Reaction.revision = revision
 end
@@ -112,6 +119,13 @@
   return self.name
 end
 
+function Bar:SetName(name)
+  self.name = name
+  if self.controlLabelString then
+    self.controlLabelString:SetText(self.name)
+  end
+end
+
 function Bar:PlaceButton(f, idx, baseW, baseH)
   local r, c, s = self:GetButtonGrid()
   local bh, bw = self:GetButtonSize()
@@ -127,6 +141,378 @@
 
 
 
+
+
+
+
+--
+-- Bar config overlay
+--
+local StoreExtents, RecomputeButtonSize, RecomputeButtonSpacing, RecomputeGrid, ClampToButtons, HideGameTooltip, CreateControls
+
+do
+  -- upvalue some of these for small OnUpdate performance boost
+  local GetSize       = Bar.GetSize
+  local GetButtonSize = Bar.GetButtonSize
+  local GetButtonGrid = Bar.GetButtonGrid
+  local SetSize       = Bar.SetSize
+  local SetButtonSize = Bar.SetButtonSize
+  local SetButtonGrid = Bar.SetButtonGrid
+  local ApplyAnchor   = Bar.ApplyAnchor
+
+  StoreExtents = function(bar)
+    local f = bar.frame
+    local point, relativeTo, relativePoint, x, y = f:GetPoint(1)
+    relativeTo = relativeTo or f:GetParent()
+    local anchorTo
+    for name, b in pairs(ReAction.bars) do
+      if b then
+        if b:GetFrame() == relativeTo then
+          anchorTo = name
+          break
+        end
+      end
+    end
+    anchorTo = anchorTo or relativeTo:GetName()
+    local c = bar.config
+    c.anchor = point
+    c.anchorTo = anchorTo
+    c.relativePoint = relativePoint
+    c.x = x
+    c.y = y
+    c.width, c.height = f:GetWidth(), f:GetHeight()
+  end
+
+  RecomputeButtonSize = function(bar)
+    local w, h = GetSize(bar)
+    local bw, bh = GetButtonSize(bar)
+    local r, c, s = GetButtonGrid(bar)
+
+    local scaleW = (floor(w/c) - s) / bw
+    local scaleH = (floor(h/r) - s) / bh
+    local scale = min(scaleW, scaleH)
+
+    SetButtonSize(bar, scale * bw, scale * bh, s)
+  end
+
+  RecomputeButtonSpacing = function(bar)
+    local w, h = GetSize(bar)
+    local bw, bh = GetButtonSize(bar)
+    local r, c, s = GetButtonGrid(bar)
+
+    SetButtonGrid(bar,r,c,min(floor(w/c) - bw, floor(h/r) - bh))
+  end
+
+  RecomputeGrid = function(bar)
+    local w, h = GetSize(bar)
+    local bw, bh = GetButtonSize(bar)
+    local r, c, s = GetButtonGrid(bar)
+
+    SetButtonGrid(bar, floor(h/(bh+s)), floor(w/(bw+s)), s)
+  end
+
+  ClampToButtons = function(bar)
+    local bw, bh = GetButtonSize(bar)
+    local r, c, s = GetButtonGrid(bar)
+    SetSize(bar, (bw+s)*c, (bh+s)*r )
+  end
+
+  HideGameTooltip = function()
+    GameTooltip:Hide()
+  end
+
+  CreateControls = function(bar)
+    local f = bar.frame
+
+    f:SetMovable(true)
+    f:SetResizable(true)
+    f:SetClampedToScreen(true)
+
+    -- buttons on the bar should be direct children of the bar frame.
+    -- The control elements need to float on top of this, which we could
+    -- do with SetFrameLevel() or Raise(), but it's more reliable to do it
+    -- via frame nesting, hence good old foo's appearance here.
+    local foo = CreateFrame("Frame",nil,f)
+    foo:SetAllPoints()
+
+    local control = CreateFrame("Button", nil, foo)
+    control:EnableMouse(true)
+    control:SetToplevel(true)
+    control:SetPoint("TOPLEFT", -4, 4)
+    control:SetPoint("BOTTOMRIGHT", 4, -4)
+    control:SetBackdrop({
+      edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
+      tile = true,
+      tileSize = 16,
+      edgeSize = 16,
+      insets = { left = 0, right = 0, top = 0, bottom = 0 },
+    })
+
+    -- textures
+    local bgTex = control:CreateTexture(nil,"BACKGROUND")
+    bgTex:SetTexture(0.7,0.7,1.0,0.2)
+    bgTex:SetPoint("TOPLEFT",4,-4)
+    bgTex:SetPoint("BOTTOMRIGHT",-4,4)
+    local hTex = control:CreateTexture(nil,"HIGHLIGHT")
+    hTex:SetTexture(0.7,0.7,1.0,0.2)
+    hTex:SetPoint("TOPLEFT",4,-4)
+    hTex:SetPoint("BOTTOMRIGHT",-4,4)
+    hTex:SetBlendMode("ADD")
+
+    -- label
+    local label = control:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
+    label:SetAllPoints()
+    label:SetJustifyH("CENTER")
+    label:SetShadowColor(0,0,0,1)
+    label:SetShadowOffset(2,-2)
+    label:SetTextColor(1,1,1,1)
+    label:SetText(bar:GetName())
+    label:Show()
+    bar.controlLabelString = label  -- so that bar:SetName() can update it
+
+    local StopResize = function()
+      f:StopMovingOrSizing()
+      f.isMoving = false
+      f:SetScript("OnUpdate",nil)
+      StoreExtents(bar)
+      ClampToButtons(bar)
+      ApplyAnchor(bar)
+    end
+
+    -- edge drag handles
+    for _, point in pairs({"LEFT","TOP","RIGHT","BOTTOM"}) do
+      local edge = CreateFrame("Frame",nil,control)
+      edge:EnableMouse(true)
+      edge:SetWidth(8)
+      edge:SetHeight(8)
+      if point == "TOP" or point == "BOTTOM" then
+        edge:SetPoint(point.."LEFT")
+        edge:SetPoint(point.."RIGHT")
+      else
+        edge:SetPoint("TOP"..point)
+        edge:SetPoint("BOTTOM"..point)
+      end
+      local tex = edge:CreateTexture(nil,"HIGHLIGHT")
+      tex:SetTexture(1.0,0.82,0,0.7)
+      tex:SetBlendMode("ADD")
+      tex:SetAllPoints()
+      edge:RegisterForDrag("LeftButton")
+      edge:SetScript("OnMouseDown",
+        function()
+          local bw, bh = GetButtonSize(bar)
+          local r, c, s = GetButtonGrid(bar)
+          f:SetMinResize( bw+s+1, bh+s+1 )
+          f:StartSizing(point)
+          f:SetScript("OnUpdate", 
+            function()
+              RecomputeGrid(bar)
+              bar:RefreshLayout()
+            end
+          )
+        end
+      )
+      edge:SetScript("OnMouseUp", StopResize)
+      edge:SetScript("OnEnter",
+        function()
+          GameTooltip:SetOwner(f, "ANCHOR_"..point)
+          GameTooltip:AddLine(L["Drag to add/remove buttons"])
+          GameTooltip:Show()
+        end
+      )
+      edge:SetScript("OnLeave", HideGameTooltip)
+      edge:Show()
+    end
+
+    -- corner drag handles, again nested in an anonymous frame so that they are on top
+    local foo2 = CreateFrame("Frame",nil,control)
+    foo2:SetAllPoints(true)
+    for _, point in pairs({"BOTTOMLEFT","TOPLEFT","BOTTOMRIGHT","TOPRIGHT"}) do
+      local corner = CreateFrame("Frame",nil,foo2)
+      corner:EnableMouse(true)
+      corner:SetWidth(12)
+      corner:SetHeight(12)
+      corner:SetPoint(point)
+      local tex = corner:CreateTexture(nil,"HIGHLIGHT")
+      tex:SetTexture(1.0,0.82,0,0.7)
+      tex:SetBlendMode("ADD")
+      tex:SetAllPoints()
+      corner:RegisterForDrag("LeftButton","RightButton")
+      local updateTooltip = function()
+        local size, size2 = bar:GetButtonSize()
+        local rows, cols, spacing = bar:GetButtonGrid()
+        size = (size == size2) and tostring(size) or format("%dx%d",size,size2)
+        GameTooltipTextRight4:SetText(size)
+        GameTooltipTextRight5:SetText(tostring(spacing))
+      end
+      corner:SetScript("OnMouseDown",
+        function(_,btn)
+          local bw, bh = GetButtonSize(bar)
+          local r, c, s = GetButtonGrid(bar)
+          if btn == "LeftButton" then -- button resize
+            f:SetMinResize( (s+12)*c+1, (s+12)*r+1 )
+            f:SetScript("OnUpdate", 
+              function()
+                RecomputeButtonSize(bar)
+                bar:RefreshLayout()
+                updateTooltip()
+              end
+            )
+          elseif btn == "RightButton" then -- spacing resize
+            f:SetMinResize( bw*c, bh*r )
+            f:SetScript("OnUpdate", 
+              function()
+                RecomputeButtonSpacing(bar)
+                bar:RefreshLayout()
+                updateTooltip()
+              end
+            )
+          end
+          f:StartSizing(point)
+        end
+      )
+      corner:SetScript("OnMouseUp",StopResize)
+      corner:SetScript("OnEnter",
+        function()
+          GameTooltip:SetOwner(f, "ANCHOR_"..point)
+          GameTooltip:AddLine(L["Drag to resize buttons"])
+          GameTooltip:AddLine(L["Right-click-drag"])
+          GameTooltip:AddLine(L["to change spacing"])
+          local size, size2 = bar:GetButtonSize()
+          local rows, cols, spacing = bar:GetButtonGrid()
+          size = (size == size2) and tostring(size) or format("%dx%d",size,size2)
+          GameTooltip:AddDoubleLine(L["Size:"], size)
+          GameTooltip:AddDoubleLine(L["Spacing:"], tostring(spacing))
+          GameTooltip:Show()
+        end
+      )
+      corner:SetScript("OnLeave", 
+        function()
+          GameTooltip:Hide()
+          f:SetScript("OnUpdate",nil)
+        end
+      )
+
+    end
+
+    control:RegisterForDrag("LeftButton")
+    control:RegisterForClicks("RightButtonDown")
+    
+    control:SetScript("OnDragStart",
+      function()
+        f:StartMoving()
+        f.isMoving = true
+        -- TODO: snap indicator update install
+      end
+    )
+
+    control:SetScript("OnDragStop",
+      function()
+        f:StopMovingOrSizing()
+        f.isMoving = false
+        f:SetScript("OnUpdate",nil)
+        -- TODO: snap frame here
+        StoreExtents(bar)
+      end
+    )
+
+    control:SetScript("OnEnter",
+      function()
+        -- add bar type and status information to name
+        local name = bar.name
+        for _, m in ReAction:IterateModules() do
+          --[[
+          local suffix = safecall(m,"GetBarNameModifier",bar)
+          if suffix then
+            name = ("%s %s"):format(name,suffix)
+          end
+          --]]
+        end
+        
+        GameTooltip:SetOwner(f, "ANCHOR_TOPRIGHT")
+        GameTooltip:AddLine(name)
+        GameTooltip:AddLine(L["Drag to move"])
+        --GameTooltip:AddLine(L["Shift-drag for sticky mode"])
+        GameTooltip:AddLine(L["Right-click for options"])
+        GameTooltip:Show()
+      end
+    )
+
+    control:SetScript("OnLeave", HideGameTooltip)
+
+    control:SetScript("OnClick",
+      function()
+        bar:ShowMenu()
+      end
+    )
+
+    return control
+  end
+end
+
+
+local OpenMenu, CloseMenu
+do
+  -- Looking for a lightweight AceConfig3-struct-compatible 
+  -- replacement for Dewdrop, encapsulate here
+  -- Considering Blizzard's EasyMenu/UIDropDownMenu, but that's
+  -- a bit tricky to convert from AceConfig3-struct
+  local Dewdrop = AceLibrary("Dewdrop-2.0")
+  OpenMenu = function(frame, opts)
+    Dewdrop:Open(frame, "children", opts, "cursorX", true, "cursorY", true)
+  end
+  CloseMenu = function(frame)
+    if Dewdrop:GetOpenedParent() == frame then
+      Dewdrop:Close()
+    end
+  end
+end
+
+
+function Bar:ShowControls(show)
+  if show then
+    if not self.controlFrame then
+      self.controlFrame = CreateControls(self)
+    end
+    self.controlFrame:Show()
+  elseif self.controlFrame then
+    CloseMenu(self.controlFrame)
+    self.controlFrame:Hide()
+  end
+end
+
+function Bar:ShowMenu()
+  if not self.menuOpts then
+    self.menuOpts = {
+      type = "group",
+      args = {
+        --[[
+        openConfig = {
+          type = "execute",
+          name = L["Configure..."],
+          desc = L["Open the configuration dialogue for this bar"],
+          func = function() CloseMenu(self.controlFrame); module:OpenConfig(self) end,
+          disabled = InCombatLockdown,
+          order = 1
+        },
+        --]]
+        delete = {
+          type = "execute",
+          name = L["Delete Bar"],
+          desc = L["Remove the bar from the current profile"],
+          func = function() ReAction:EraseBar(self) end,
+          order = 2
+        },
+      }
+    }
+  end
+  if self.modMenuOpts == nil then
+    self.modMenuOpts = { }
+  end
+  OpenMenu(self.controlFrame, self.menuOpts)
+end
+
+
+
 ------ Export as a class-factory ------
 ReAction.Bar = {
   prototype = Bar,