Puppeteer/gui/component/ButtonEditor.lua
2025-08-09 23:20:17 -07:00

411 lines
13 KiB
Lua

PTButtonEditor = PTGuiComponent:Extend("puppeteer_button_editor")
local util = PTUtil
local RotateTexture = util.RotateTexture
function PTButtonEditor:New()
local obj = setmetatable({}, self)
local frame = CreateFrame("Frame", self:GenerateName())
obj:SetHandle(frame)
obj:SetSimpleBackground(PTGuiComponent.BACKGROUND_DIALOG)
local title = PTGuiLib.Get("title", frame)
:SetSize(192, 36)
:SetPoint("CENTER", frame, "TOP")
:SetText("Edit Buttons")
obj:AddComponent("Title", title)
local scrollFrame = PTGuiLib.Get("scroll_frame", frame)
:SetPoint("TOPLEFT", frame, "TOPLEFT", 5, -50)
:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -5, 100)
:SetSimpleBackground()
obj:AddComponent("ScrollFrame", scrollFrame)
local controlsLabel = PTGuiLib.Get("text", frame)
:SetText("Controls")
:SetWidth(66)
:SetHeight(30)
:SetPoint("TOPLEFT", scrollFrame:GetHandle(), "TOPLEFT", 5, 33)
:SetFontSize(14)
:SetFontFlags("OUTLINE")
:SetJustifyV("BOTTOM")
local buttonIDLabel = PTGuiLib.Get("text", frame)
:SetText("Button ID")
:SetWidth(100)
:SetHeight(30)
:SetPoint("LEFT", controlsLabel, "RIGHT", 0, 0)
:SetFontSize(14)
:SetFontFlags("OUTLINE")
:SetJustifyV("BOTTOM")
local customNameLabel = PTGuiLib.Get("text", frame)
:SetText("Custom Name")
:SetWidth(130)
:SetHeight(30)
:SetPoint("LEFT", buttonIDLabel, "RIGHT", 0, 0)
:SetFontSize(14)
:SetFontFlags("OUTLINE")
:SetJustifyV("BOTTOM")
local showUnboundLabel = PTGuiLib.Get("text", frame)
:SetText("Show Unbound")
:SetWidth(82)
:SetHeight(30)
:SetPoint("LEFT", customNameLabel, "RIGHT", 0, 0)
:SetFontSize(14)
:SetFontFlags("OUTLINE")
:SetJustifyV("BOTTOM")
local done = PTGuiLib.Get("button", frame)
:SetPoint("BOTTOM", frame, "BOTTOM", 0, 5)
:SetText("Done")
:SetSize(200, 20)
:OnClick(function()
local Buttons = PTOptions.Buttons
local buttonInfo = PTOptions.ButtonInfo
PTUtil.ClearTable(Buttons)
for _, line in ipairs(obj.Lines) do
local button = line.Button
table.insert(Buttons, button)
if not buttonInfo[button] then
buttonInfo[button] = {}
end
local info = buttonInfo[button]
info.Name = line:GetCustomButtonName()
info.ShowUnbound = line:IsUnboundShown()
end
PTSettingsGui.ReloadBindingLines()
PTSettingsGui.UpdateBindingsInterface()
Puppeteer.InitBindingDisplayCache()
Puppeteer.InitOverrideBindingsMapping()
obj:Dispose()
PTSettingsGui.PopOverlayFrame()
end)
local addButton = PTGuiLib.Get("button", frame)
:SetPoint("BOTTOM", done, "TOP", 0, 10)
:SetSize(200, 50)
:SetText("Add a Button")
:OnClick(function(self)
if not obj.AddMode then
obj:SetAddMode(true)
end
end)
addButton:HookScript("OnMouseUp", function(self)
if not obj.AddMode then
return
end
if not obj:ContainsButton(arg1) then
obj:AddButtonLine(arg1, arg1)
end
obj:SetAddMode(false)
local onClick = addButton:GetScript("OnClick")
addButton:SetScript("OnClick", nil)
PTUtil.RunLater(function()
addButton:SetScript("OnClick", onClick, true)
end)
end)
addButton:SetScript("OnKeyUp", function(self)
if not obj.AddMode then
return
end
if arg1 == "ESCAPE" then
obj:SetAddMode(false)
return
end
if not obj:ContainsButton(arg1) then
if not obj:AreBindingsFull() then
obj:AddButtonLine(arg1, arg1)
else
DEFAULT_CHAT_FRAME:AddMessage("You cannot add any more non-mouse buttons!")
end
end
obj:SetAddMode(false)
end)
addButton:SetScript("OnMouseWheel", function(self)
if not obj.AddMode then
return
end
if arg1 > 0 then
if not obj:ContainsButton("MOUSEWHEELUP") then
if not obj:AreBindingsFull() then
obj:AddButtonLine("MOUSEWHEELUP", "MOUSEWHEELUP")
else
DEFAULT_CHAT_FRAME:AddMessage("You cannot add any more non-mouse buttons!")
end
end
elseif arg1 < 0 then
if not obj:ContainsButton("MOUSEWHEELDOWN") then
if not obj:AreBindingsFull() then
obj:AddButtonLine("MOUSEWHEELDOWN", "MOUSEWHEELDOWN")
else
DEFAULT_CHAT_FRAME:AddMessage("You cannot add any more non-mouse buttons!")
end
end
end
obj:SetAddMode(false)
end)
obj:AddComponent("AddButton", addButton)
obj:SetAddMode(false)
obj.Lines = {}
obj.LineMap = {}
return obj
end
function PTButtonEditor:OnAcquire()
self.super.OnAcquire(self)
self:SetSize(425, 400)
self:GetScrollFrame():FixNextUpdate()
for _, button in ipairs(PTOptions.Buttons) do
self:AddButtonLine(button, button)
end
end
function PTButtonEditor:OnDispose()
self.super.OnDispose(self)
self:ClearButtonLines()
self:SetAddMode(false)
end
PTButtonEditor:CreateGetter("ScrollFrame")
PTButtonEditor:CreateGetter("AddButton")
function PTButtonEditor:SetAddMode(addMode)
self.AddMode = addMode
self:GetAddButton():GetHandle():EnableKeyboard(self.AddMode)
self:GetAddButton():GetHandle():EnableMouseWheel(self.AddMode)
self:GetAddButton():SetText(self.AddMode and "Press any button, key,\nor mouse wheel to bind\nPress Esc to Cancel"
or "Left click to start\nbinding a button")
end
function PTButtonEditor:ContainsButton(button)
return self.LineMap[button] ~= nil
end
function PTButtonEditor:GetNumUsedBindings()
local nonBindingButtons = util.GetAllButtonsSet()
local used = 0
for button, _ in pairs(self.LineMap) do
if not nonBindingButtons[button] then
used = used + 1
end
end
return used
end
function PTButtonEditor:AreBindingsFull()
return self:GetNumUsedBindings() >= 24
end
function PTButtonEditor:SwapIndexes(index1, index2)
self.Lines[index1], self.Lines[index2] = self.Lines[index2], self.Lines[index1]
self:UpdateLinePositions()
end
function PTButtonEditor:AddButtonLine(id, button)
local line = PTGuiLib.Get("puppeteer_button_line", self:GetScrollFrame())
:SetSize(380, 25)
:SetButton(button)
:SetControlHandler(self)
table.insert(self.Lines, line)
if id then
self.LineMap[id] = line
end
self:UpdateLinePositions()
return line
end
function PTButtonEditor:RemoveButtonLine(line)
for id, l in pairs(self.LineMap) do
if line == l then
self.LineMap[id] = nil
end
end
PTUtil.RemoveElement(self.Lines, line)
line:Dispose()
self:UpdateLinePositions()
end
function PTButtonEditor:ClearButtonLines()
for _, line in ipairs(self.Lines) do
line:Dispose()
end
PTUtil.ClearTable(self.Lines)
PTUtil.ClearTable(self.LineMap)
end
function PTButtonEditor:UpdateLinePositions()
local INTERVAL = 26
for i, line in ipairs(self.Lines) do
line:SetPoint("TOPLEFT", self:GetScrollFrame(), "TOPLEFT", 5, -5 - (INTERVAL * (i - 1)))
end
self:GetScrollFrame():UpdateScrollChildRect()
end
-- Control handler functions
function PTButtonEditor:OnLineDelete(line)
self:RemoveButtonLine(line)
end
function PTButtonEditor:OnLineUp(line)
local index = PTUtil.IndexOf(self.Lines, line)
if IsShiftKeyDown() then
for i = index, 2, -1 do
self:SwapIndexes(i, i - 1)
end
elseif index > 1 and table.getn(self.Lines) > 1 then
self:SwapIndexes(index, index - 1)
end
end
function PTButtonEditor:OnLineDown(line)
local index = PTUtil.IndexOf(self.Lines, line)
local lineCount = table.getn(self.Lines)
if IsShiftKeyDown() then
for i = index, lineCount - 1 do
self:SwapIndexes(i, i + 1)
end
elseif index < table.getn(self.Lines) then
self:SwapIndexes(index, index + 1)
end
end
-- End of control handler functions
PTGuiLib.RegisterComponent(PTButtonEditor)
-- Button line component
PTButtonLine = PTGuiComponent:Extend("puppeteer_button_line")
function PTButtonLine:New()
local obj = setmetatable({}, self)
local frame = CreateFrame("Frame", self:GenerateName())
obj:SetHandle(frame)
local delete = PTGuiLib.Get("button", frame)
:SetPoint("LEFT", frame, "LEFT", 0, 0)
:SetSize(20, 20)
:ApplyTooltip("Delete this button")
:OnClick(function()
if obj.ControlHandler then
obj.ControlHandler:OnLineDelete(obj)
end
end)
delete.NormalTexture:SetTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Up")
RotateTexture(delete.NormalTexture, 180, 0.7)
delete.PushedTexture:SetTexture("Interface\\Buttons\\UI-Panel-MinimizeButton-Down")
RotateTexture(delete.PushedTexture, 180, 0.7)
delete:SetUseDefaultTextures(true)
local up = PTGuiLib.Get("button", frame)
:SetPoint("LEFT", delete, "RIGHT", 6, 0)
:SetSize(20, 20)
:ApplyTooltip("Move this button up", "Hold shift to move to top")
:OnClick(function()
if obj.ControlHandler then
obj.ControlHandler:OnLineUp(obj)
end
end)
up.NormalTexture:SetTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up")
RotateTexture(up.NormalTexture, -90, 0.75)
up.PushedTexture:SetTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Down")
RotateTexture(up.PushedTexture, -90, 0.75)
up.HighlightTexture:SetTexture("Interface\\Buttons\\UI-Common-MouseHilight")
up.HighlightTexture:SetTexCoord(0, 1, 0, 1)
up:SetUseDefaultTextures(true)
local down = PTGuiLib.Get("button", frame)
:SetPoint("LEFT", up, "RIGHT", 1, 0)
:SetSize(20, 20)
:ApplyTooltip("Move this button down", "Hold shift to move to bottom")
:OnClick(function()
if obj.ControlHandler then
obj.ControlHandler:OnLineDown(obj)
end
end, true)
down.NormalTexture:SetTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up")
RotateTexture(down.NormalTexture, 90, 0.75)
down.PushedTexture:SetTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Down")
RotateTexture(down.PushedTexture, 90, 0.75)
down.HighlightTexture:SetTexture("Interface\\Buttons\\UI-Common-MouseHilight")
down.HighlightTexture:SetTexCoord(0, 1, 0, 1)
down:SetUseDefaultTextures(true)
local buttonNameLabel = PTGuiLib.Get("text", frame)
:SetPoint("LEFT", down, "RIGHT", 5, 0)
:SetText("Left")
:SetWidth(90)
:SetHeight(30)
:SetJustifyH("RIGHT")
:SetNonSpaceWrap(true)
obj:AddComponent("ButtonNameLabel", buttonNameLabel)
local nameEditbox = PTGuiLib.Get("editbox", frame)
:SetPoint("LEFT", buttonNameLabel, "RIGHT", 5, 0)
:SetSize(130, 20)
:SetScript("OnEnterPressed", function(self)
self:ClearFocus()
end)
:ApplyTooltip("This name will be shown on the binding tooltip")
obj:AddComponent("NameEditbox", nameEditbox)
local showUnboundCheckbox = PTGuiLib.Get("checkbox", frame)
:SetPoint("LEFT", nameEditbox, "RIGHT", 30, 0)
:SetSize(20, 20)
:ApplyTooltip("If enabled, the binding tooltip will show this key when unbound")
obj:AddComponent("ShowUnboundCheckbox", showUnboundCheckbox)
return obj
end
function PTButtonLine:OnAcquire()
self.super.OnAcquire(self)
self:SetSize(380, 25)
end
function PTButtonLine:OnDispose()
self.super.OnDispose(self)
self.Button = nil
end
PTButtonLine:CreateGetter("ButtonNameLabel")
PTButtonLine:CreateGetter("NameEditbox")
PTButtonLine:CreateGetter("ShowUnboundCheckbox")
function PTButtonLine:SetButton(button)
self.Button = button
self:GetButtonNameLabel():SetText(util.GetButtonName(button))
local buttonInfo = PTOptions.ButtonInfo
if not buttonInfo[button] then
buttonInfo[button] = {Name = util.GetButtonName(button), ShowUnbound = true}
end
self:GetNameEditbox():SetText(buttonInfo[button].Name or util.GetButtonName(button))
self:GetShowUnboundCheckbox():SetChecked(buttonInfo[button].ShowUnbound)
return self
end
-- The handler is expected to have functions OnLineDelete, OnLineUp, OnLineDown
function PTButtonLine:SetControlHandler(handler)
self.ControlHandler = handler
return self
end
function PTButtonLine:GetCustomButtonName()
local text = self:GetNameEditbox():GetText()
if text == "" then
text = util.GetButtonName(self.Button)
end
return text
end
function PTButtonLine:IsUnboundShown()
return self:GetShowUnboundCheckbox():GetChecked() == 1
end
PTGuiLib.RegisterComponent(PTButtonLine)