You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
269 lines
7.8 KiB
269 lines
7.8 KiB
|
3 years ago
|
-- Neuron is a World of Warcraft® user interface addon.
|
||
|
|
-- Copyright (c) 2017-2021 Britt W. Yazel
|
||
|
|
-- Copyright (c) 2006-2014 Connor H. Chenoweth
|
||
|
|
-- This code is licensed under the MIT license (see LICENSE for details)
|
||
|
|
|
||
|
|
local _, addonTable = ...
|
||
|
|
|
||
|
|
addonTable.overlay = addonTable.overlay or {}
|
||
|
|
|
||
|
|
local L = LibStub("AceLocale-3.0"):GetLocale("Neuron")
|
||
|
|
|
||
|
|
---type definition the contents of the xml file
|
||
|
|
---@class NeuronBarFrame:CheckButton,ScriptObject
|
||
|
|
---@field Text FontString
|
||
|
|
---@field Message FontString
|
||
|
|
---@field MessageBG Texture
|
||
|
|
|
||
|
|
---@class BarOverlay
|
||
|
|
---@field active boolean
|
||
|
|
---@field bar Bar
|
||
|
|
---@field frame NeuronBarFrame
|
||
|
|
---@field microadjust number
|
||
|
|
---@field onClick fun(overlay: BarOverlay, button:string, down: boolean):nil
|
||
|
|
|
||
|
|
---@type NeuronBarFrame[]
|
||
|
|
local framePool = {}
|
||
|
|
|
||
|
|
---@param overlay BarOverlay
|
||
|
|
local function updateAppearance(overlay)
|
||
|
|
local concealed = overlay.bar:GetBarConceal()
|
||
|
|
if concealed and overlay.active then
|
||
|
|
overlay.frame:SetBackdropColor(1,0,0,0.6)
|
||
|
|
overlay.frame.Text:Show()
|
||
|
|
elseif not concealed and overlay.active then
|
||
|
|
overlay.frame:SetBackdropColor(0,0,1,0.5)
|
||
|
|
overlay.frame.Text:Show()
|
||
|
|
elseif concealed and not overlay.active then
|
||
|
|
overlay.frame:SetBackdropColor(1,0,0,0.4)
|
||
|
|
overlay.frame.Text:Hide()
|
||
|
|
elseif not concealed and not overlay.active then
|
||
|
|
overlay.frame:SetBackdropColor(0,0,0,0.4)
|
||
|
|
overlay.frame.Text:Hide()
|
||
|
|
end
|
||
|
|
|
||
|
|
if overlay.microadjust == 0 then
|
||
|
|
overlay.frame.Message:Hide()
|
||
|
|
overlay.frame.MessageBG:Hide()
|
||
|
|
overlay.frame:SetFrameStrata(Neuron.STRATAS[overlay.bar:GetStrata()])
|
||
|
|
else
|
||
|
|
-- overlay never gets keyboard events unless a high strata
|
||
|
|
-- this hack doesn't work if there is a tooltip level bar
|
||
|
|
-- until you choose that bar and then it starts working for others
|
||
|
|
overlay.frame:SetFrameStrata(Neuron.STRATAS[#Neuron.STRATAS])
|
||
|
|
overlay.frame:SetBackdropColor(1,1,0,0.6)
|
||
|
|
overlay.frame.Message:Show()
|
||
|
|
overlay.frame.Message:SetText(overlay.bar.data.point:lower().." x: "..format("%0.2f", overlay.bar:GetXAxis()).." y: "..format("%0.2f", overlay.bar:GetYAxis()))
|
||
|
|
overlay.frame.MessageBG:Show()
|
||
|
|
overlay.frame.MessageBG:SetWidth(overlay.frame.Message:GetWidth()*1.05)
|
||
|
|
overlay.frame.MessageBG:SetHeight(overlay.frame.Message:GetHeight()*1.1)
|
||
|
|
end
|
||
|
|
|
||
|
|
overlay.frame:SetAllPoints(overlay.bar)
|
||
|
|
end
|
||
|
|
|
||
|
|
-- forward declare it so the event handlers can use it
|
||
|
|
local BarEditor
|
||
|
|
|
||
|
|
---@param overlay BarOverlay
|
||
|
|
local function onEnter(overlay)
|
||
|
|
-- we don't want to mutate the real overlay
|
||
|
|
local fakeOverlay = CopyTable(overlay, true --[[shallow copy]])
|
||
|
|
|
||
|
|
-- this will update the real overlay frame as if active
|
||
|
|
BarEditor.activate(fakeOverlay)
|
||
|
|
end
|
||
|
|
|
||
|
|
--TODO: the overlay should not be mutating objects.
|
||
|
|
--put the movement code into the overlay controller
|
||
|
|
---@param overlay BarOverlay
|
||
|
|
---@param button string
|
||
|
|
local function onDragStart(overlay, button)
|
||
|
|
overlay.bar.data.snapToPoint = false
|
||
|
|
overlay.bar.data.snapToFrame = false
|
||
|
|
|
||
|
|
overlay.frame:StartMoving()
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
---@param overlay BarOverlay
|
||
|
|
local function onDragStop(overlay)
|
||
|
|
|
||
|
|
local point
|
||
|
|
overlay.frame:StopMovingOrSizing()
|
||
|
|
|
||
|
|
for _,v in pairs(Neuron.bars) do
|
||
|
|
if not point and overlay.bar:GetSnapTo() and v:GetSnapTo() and overlay.bar ~= v then
|
||
|
|
point = overlay.bar:Stick(v, Neuron.SNAPTO_TOLERANCE, overlay.bar:GetHorizontalPad(), overlay.bar:GetVerticalPad())
|
||
|
|
|
||
|
|
if point then
|
||
|
|
overlay.bar.data.snapToPoint = point
|
||
|
|
overlay.bar.data.snapToFrame = v:GetName()
|
||
|
|
overlay.bar.data.point = "SnapTo: "..point
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
if not point then
|
||
|
|
overlay.bar.data.snapToPoint = false
|
||
|
|
overlay.bar.data.snapToFrame = false
|
||
|
|
|
||
|
|
local newPoint, x, y = overlay.bar.GetPosition(overlay.frame)
|
||
|
|
overlay.bar.data.point = newPoint
|
||
|
|
overlay.bar:SetXAxis(x)
|
||
|
|
overlay.bar:SetYAxis(y)
|
||
|
|
|
||
|
|
overlay.bar:SetPosition()
|
||
|
|
end
|
||
|
|
|
||
|
|
if overlay.bar:GetSnapTo() and not overlay.bar.data.snapToPoint then
|
||
|
|
overlay.bar:StickToEdge()
|
||
|
|
end
|
||
|
|
|
||
|
|
overlay.bar:SetPosition()
|
||
|
|
overlay.bar:UpdateBarStatus()
|
||
|
|
end
|
||
|
|
|
||
|
|
---@param overlay BarOverlay
|
||
|
|
---@param key string
|
||
|
|
local function onKeyDown(overlay, key)
|
||
|
|
if overlay.microadjust == 0 then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
local newPoint, x, y = overlay.bar:GetPosition()
|
||
|
|
overlay.bar.data.point = newPoint
|
||
|
|
overlay.bar:SetXAxis(x)
|
||
|
|
overlay.bar:SetYAxis(y)
|
||
|
|
|
||
|
|
overlay.bar:SetUserPlaced(false)
|
||
|
|
overlay.bar:ClearAllPoints()
|
||
|
|
|
||
|
|
if key == "UP" then
|
||
|
|
overlay.bar:SetYAxis(overlay.bar:GetYAxis() + .1 * overlay.microadjust)
|
||
|
|
elseif key == "DOWN" then
|
||
|
|
overlay.bar:SetYAxis(overlay.bar:GetYAxis() - .1 * overlay.microadjust)
|
||
|
|
elseif key == "LEFT" then
|
||
|
|
overlay.bar:SetXAxis(overlay.bar:GetXAxis() - .1 * overlay.microadjust)
|
||
|
|
elseif key == "RIGHT" then
|
||
|
|
overlay.bar:SetXAxis(overlay.bar:GetXAxis() + .1 * overlay.microadjust)
|
||
|
|
else
|
||
|
|
BarEditor.microadjust(overlay, 0)
|
||
|
|
end
|
||
|
|
|
||
|
|
overlay.bar:SetPosition()
|
||
|
|
overlay.bar:UpdateBarStatus()
|
||
|
|
|
||
|
|
updateAppearance(overlay)
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
---@param overlay BarOverlay
|
||
|
|
local function onLeave(overlay)
|
||
|
|
updateAppearance(overlay)
|
||
|
|
end
|
||
|
|
|
||
|
|
---@param overlay BarOverlay
|
||
|
|
---@param button string
|
||
|
|
---@param down boolean
|
||
|
|
local function onClick(overlay, button, down)
|
||
|
|
overlay.onClick(overlay, button, down)
|
||
|
|
end
|
||
|
|
|
||
|
|
BarEditor = {
|
||
|
|
---@param bar Bar
|
||
|
|
---@param onClickCallback fun(overlay: BarOverlay, button: string, down: boolean): nil
|
||
|
|
---@return BarOverlay
|
||
|
|
allocate = function (bar, onClickCallback)
|
||
|
|
---@type BarOverlay
|
||
|
|
local overlay = {
|
||
|
|
active = false,
|
||
|
|
bar = bar,
|
||
|
|
frame = -- try to pop a frame off the stack, otherwise make a new one
|
||
|
|
table.remove(framePool) or
|
||
|
|
CreateFrame("CheckButton", nil, UIParent, "NeuronBarTemplate") --[[@as NeuronBarFrame]],
|
||
|
|
microadjust = 0,
|
||
|
|
onClick = onClickCallback,
|
||
|
|
}
|
||
|
|
overlay.frame:SetBackdrop({
|
||
|
|
bgFile = "Interface/Tooltips/UI-Tooltip-Background",
|
||
|
|
tile = true,
|
||
|
|
tileSize = 16,
|
||
|
|
insets = {left = 4, right = 4, top = 4, bottom = 4}
|
||
|
|
})
|
||
|
|
|
||
|
|
overlay.frame.Text:SetText(bar:GetBarName())
|
||
|
|
|
||
|
|
overlay.frame:EnableKeyboard(false)
|
||
|
|
overlay.frame:RegisterForClicks("AnyUp", "AnyDown")
|
||
|
|
overlay.frame:RegisterForDrag("LeftButton")
|
||
|
|
overlay.frame:SetScript("OnDragStart", function(_, button) onDragStart(overlay, button) end)
|
||
|
|
overlay.frame:SetScript("OnDragStop", function(_) onDragStop(overlay) end)
|
||
|
|
overlay.frame:SetScript("OnKeyDown", function(_, key) onKeyDown(overlay, key) end)
|
||
|
|
overlay.frame:SetScript("OnEnter", function() onEnter(overlay) end)
|
||
|
|
overlay.frame:SetScript("OnLeave", function() onLeave(overlay) end)
|
||
|
|
overlay.frame:SetScript("OnClick", function(_, button, down) onClick(overlay, button, down) end)
|
||
|
|
|
||
|
|
overlay.frame.Text:Show()
|
||
|
|
overlay.frame:Show()
|
||
|
|
updateAppearance(overlay)
|
||
|
|
|
||
|
|
return overlay
|
||
|
|
end,
|
||
|
|
|
||
|
|
---@param overlay BarOverlay
|
||
|
|
activate = function(overlay)
|
||
|
|
overlay.active = true
|
||
|
|
BarEditor.microadjust(overlay, overlay.microadjust)
|
||
|
|
updateAppearance(overlay)
|
||
|
|
end,
|
||
|
|
|
||
|
|
---@param overlay BarOverlay
|
||
|
|
deactivate = function(overlay)
|
||
|
|
overlay.active = false
|
||
|
|
BarEditor.microadjust(overlay, 0)
|
||
|
|
|
||
|
|
updateAppearance(overlay)
|
||
|
|
end,
|
||
|
|
|
||
|
|
---@param overlay BarOverlay
|
||
|
|
free = function (overlay)
|
||
|
|
overlay.frame:SetScript("OnDragStart", nil)
|
||
|
|
overlay.frame:SetScript("OnDragStop", nil)
|
||
|
|
overlay.frame:SetScript("OnEnter", nil)
|
||
|
|
overlay.frame:SetScript("OnLeave", nil)
|
||
|
|
overlay.frame:SetScript("OnClick", nil)
|
||
|
|
overlay.frame:EnableKeyboard(false)
|
||
|
|
overlay.frame:RegisterForDrag()
|
||
|
|
overlay.frame:RegisterForClicks()
|
||
|
|
overlay.frame:Hide()
|
||
|
|
table.insert(framePool, overlay.frame)
|
||
|
|
|
||
|
|
-- just for good measure to make sure nothing else can mess with
|
||
|
|
-- the frame after we put it back into the pool
|
||
|
|
overlay.frame = nil
|
||
|
|
end,
|
||
|
|
|
||
|
|
---if no value is passed in for microadjust then make it a toggle
|
||
|
|
---@param overlay BarOverlay
|
||
|
|
---@param microadjust number|nil
|
||
|
|
microadjust = function(overlay, microadjust)
|
||
|
|
if microadjust ~= nil then
|
||
|
|
overlay.microadjust = microadjust
|
||
|
|
elseif overlay.microadjust == 0 then
|
||
|
|
overlay.microadjust = 1
|
||
|
|
else
|
||
|
|
overlay.microadjust = 0
|
||
|
|
end
|
||
|
|
|
||
|
|
if microadjust == 0 then
|
||
|
|
overlay.frame:EnableKeyboard(false)
|
||
|
|
else
|
||
|
|
overlay.frame:EnableKeyboard(true)
|
||
|
|
end
|
||
|
|
|
||
|
|
updateAppearance(overlay)
|
||
|
|
end,
|
||
|
|
}
|
||
|
|
|
||
|
|
addonTable.overlay.BarEditor = BarEditor
|