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.

446 lines
17 KiB

local _, Cell = ...
local L = Cell.L
local F = Cell.funcs
local P = Cell.pixelPerfectFuncs
local codeSnippetsFrame
local topPane, codePane, bottomPane, renameEB, newBtn, errorPopup
local buttons = {}
local selected, forceLoadSelected = 0, true
local LoadList, LoadSnippet, RunSnippet
local function CreateCodeSnippetsFrame()
codeSnippetsFrame = Cell:CreateMovableFrame("Cell "..L["Code Snippets"], "CellCodeSnippetsFrame", 641, 550, "DIALOG")
Cell.frames.codeSnippetsFrame = codeSnippetsFrame
codeSnippetsFrame:SetToplevel(true)
codeSnippetsFrame:SetPoint("CENTER")
P:SetEffectiveScale(codeSnippetsFrame)
local reloadBtn = Cell:CreateButton(codeSnippetsFrame.header, "Reload", "blue", {70, 20})
reloadBtn:SetPoint("TOPRIGHT", codeSnippetsFrame.header.closeBtn, "TOPLEFT", P:Scale(1), 0)
reloadBtn:SetScript("OnClick", ReloadUI)
local tips = Cell:CreateScrollTextFrame(codeSnippetsFrame, "|cffb7b7b7"..L["SNIPPETS_TIPS"])
tips:SetPoint("TOPLEFT", 10, -10)
tips:SetPoint("TOPRIGHT", -10, -10)
-- rename box
renameEB = Cell:CreateEditBox(codeSnippetsFrame, 20, 20)
Cell:StylizeFrame(renameEB, {0.115, 0.115, 0.115, 0.9}, Cell:GetAccentColorTable())
renameEB:Hide()
renameEB:SetScript("OnEscapePressed", function()
renameEB:Hide()
end)
renameEB:SetScript("OnHide", function()
renameEB:Hide()
end)
-- top
topPane = CreateFrame("Frame", nil, codeSnippetsFrame, "BackdropTemplate")
-- Cell:StylizeFrame(topPane, {0,1,0,0.1}, {0,0,0,0})
topPane:SetPoint("TOPLEFT", 10, -40)
topPane:SetPoint("TOPRIGHT", -10, -40)
topPane:SetHeight(20)
-- add
newBtn = Cell:CreateButton(topPane, "", "accent-hover", {156, 20})
newBtn.tex = newBtn:CreateTexture(nil, "ARTWORK")
newBtn.tex:SetPoint("CENTER")
newBtn.tex:SetSize(12, 12)
newBtn.tex:SetTexture("Interface\\AddOns\\Cell\\Media\\Icons\\add.tga")
newBtn:SetScript("OnClick", function()
tinsert(CellDB["snippets"], {
["name"] = L["unnamed"],
["autorun"] = false,
["code"] = "\n\n", -- NOTE: FAIAP
})
selected = #CellDB["snippets"]
forceLoadSelected = true
LoadList()
end)
-- bottom
bottomPane = CreateFrame("Frame", nil, codeSnippetsFrame, "BackdropTemplate")
-- Cell:StylizeFrame(bottomPane, {0,1,0,0.1}, {0,0,0,0})
bottomPane:SetPoint("BOTTOMLEFT", 10, 10)
bottomPane:SetPoint("BOTTOMRIGHT", -10, 10)
bottomPane:SetHeight(20)
local runBtn = Cell:CreateButton(bottomPane, L["Run"], "red", {200, 20})
bottomPane.runBtn = runBtn
runBtn:SetPoint("BOTTOMLEFT")
runBtn:SetEnabled(false)
runBtn:SetScript("OnClick", function()
local errorMsg = RunSnippet(codePane:GetText())
if errorMsg then
errorPopup.text:SetText(errorMsg)
errorPopup.count = 1
errorPopup:SetScript("OnUpdate", function(self, elapsed)
errorPopup.count = errorPopup.count + 1
errorPopup:SetHeight(errorPopup.text:GetStringHeight() + 40)
if errorPopup.count >= 5 then
errorPopup:SetScript("OnUpdate", nil)
end
end)
errorPopup:Show()
end
end)
local cancelBtn = Cell:CreateButton(bottomPane, L["Cancel"], "red", {200, 20})
bottomPane.cancelBtn = cancelBtn
cancelBtn:SetPoint("BOTTOMRIGHT")
cancelBtn:SetEnabled(false)
cancelBtn:SetScript("OnClick", function()
codePane:SetText(CellDB["snippets"][selected]["code"])
cancelBtn:SetEnabled(false)
bottomPane.saveBtn:SetEnabled(false)
end)
local saveBtn = Cell:CreateButton(bottomPane, L["Save"], "red", {200, 20})
bottomPane.saveBtn = saveBtn
saveBtn:SetPoint("BOTTOMLEFT", runBtn, "BOTTOMRIGHT", 10, 0)
saveBtn:SetPoint("BOTTOMRIGHT", cancelBtn, "BOTTOMLEFT", -10, 0)
saveBtn:SetEnabled(false)
saveBtn:SetScript("OnClick", function()
CellDB["snippets"][selected]["code"] = codePane:GetText()
saveBtn:SetEnabled(false)
bottomPane.cancelBtn:SetEnabled(false)
end)
-- current line number
local lineNumber = codeSnippetsFrame.header:CreateFontString(nil, "OVERLAY", "CELL_FONT_CLASS")
lineNumber:SetPoint("LEFT", 5, 0)
-- code
codePane = Cell:CreateScrollEditBox(codeSnippetsFrame, nil, 3)
codePane.scrollFrame:SetScrollStep(1000)
codePane.eb:SetEnabled(false)
codePane.eb:SetFontObject(ChatFontNormal)
Cell:StylizeFrame(codePane.scrollFrame, {0.115, 0.115, 0.115, 0.9})
codePane:SetPoint("TOPLEFT", topPane, "BOTTOMLEFT", 0, -10)
codePane:SetPoint("BOTTOMRIGHT", bottomPane, "TOPRIGHT", 0, 10)
-- codePane.eb:SetSpacing(3)
codePane.eb:HookScript("OnTextChanged", function(self, userChanged)
local changed = CellDB["snippets"][selected]["code"] ~= codePane:GetText()
saveBtn:SetEnabled(changed)
cancelBtn:SetEnabled(changed)
end)
codePane.eb:SetScript("OnEditFocusGained", function()
lineNumber:Show()
end)
codePane.eb:SetScript("OnEditFocusLost", function()
lineNumber:Hide()
end)
codePane.OriginalGetText = codePane.eb.GetText -- NOTE: FAIAP overrides GetText
codePane.eb:HookScript("OnCursorChanged", function(self, x, y)
if not codePane.eb:HasFocus() then return end
local cursorPosition = codePane.eb:GetCursorPosition()
local next = -1
local line = 0
while (next and cursorPosition >= next) do
next = codePane.OriginalGetText(codePane.eb):find("[\n]", next + 1)
line = line + 1
end
lineNumber:SetText(line)
end)
-- NOTE: indentation
Cell.IndentationLib.enable(codePane.eb)
-- errorPopup
errorPopup = CreateFrame("Frame", nil, codePane, "BackdropTemplate")
errorPopup:SetFrameStrata("TOOLTIP")
Cell:StylizeFrame(errorPopup, {0.15, 0.1, 0.1, 0.95})
errorPopup:SetWidth(200)
errorPopup:SetPoint("BOTTOMLEFT")
errorPopup:SetPoint("BOTTOMRIGHT")
errorPopup:Hide()
errorPopup.close = Cell:CreateButton(errorPopup, "×", "red", {18, 18}, false, false, "CELL_FONT_SPECIAL", "CELL_FONT_SPECIAL")
errorPopup.close:SetPoint("TOPRIGHT")
errorPopup.close:SetScript("OnClick", function()
errorPopup:Hide()
end)
errorPopup.text = errorPopup:CreateFontString(nil, "OVERLAY", "CELL_FONT_WIDGET")
errorPopup.text:SetTextColor(1, 0.19, 0.19)
errorPopup.text:SetPoint("TOPLEFT", 20, -20)
errorPopup.text:SetPoint("TOPRIGHT", -20, -20)
errorPopup.text:SetJustifyH("LEFT")
errorPopup.text:SetWordWrap(true)
errorPopup.text:SetSpacing(3)
end
LoadList = function()
-- built-in
if not buttons[0] then
buttons[0] = Cell:CreateButton(topPane, "", "accent-hover", {156, 20})
buttons[0].id = 0 -- for highlight
buttons[0]:SetPoint("TOPLEFT")
-- checkbox
buttons[0].cb = Cell:CreateCheckButton(buttons[0], "", function(checked)
CellDB["snippets"][0]["autorun"] = checked
end)
buttons[0].cb:SetPoint("LEFT", 3, 0)
buttons[0].cb:HookScript("OnEnter", function()
buttons[0]:GetScript("OnEnter")(buttons[0])
end)
buttons[0].cb:HookScript("OnLeave", function()
buttons[0]:GetScript("OnLeave")(buttons[0])
end)
-- label
buttons[0].label = buttons[0]:CreateFontString(nil, "OVERLAY", "CELL_FONT_WIDGET")
buttons[0].label:SetPoint("LEFT", buttons[0].cb, "RIGHT", 3, 0)
buttons[0].label:SetPoint("RIGHT", -3, 0)
buttons[0].label:SetJustifyH("LEFT")
buttons[0].label:SetWordWrap(false)
buttons[0].label:SetText("Cell")
end
buttons[0].cb:SetChecked(CellDB["snippets"][0]["autorun"])
-- user created
for i, t in ipairs(CellDB["snippets"]) do
if not buttons[i] then
buttons[i] = Cell:CreateButton(topPane, "", "accent-hover", {156, 20})
buttons[i].id = i -- for highlight
-- rename
buttons[i]:SetScript("OnDoubleClick", function()
renameEB:ClearAllPoints()
renameEB:SetAllPoints(buttons[i])
renameEB:SetFrameLevel(buttons[i]:GetFrameLevel()+7)
renameEB:SetText(CellDB["snippets"][i]["name"])
renameEB:Show()
renameEB:SetFocus(true)
renameEB:SetScript("OnEnterPressed", function()
renameEB:Hide()
CellDB["snippets"][i]["name"] = strtrim(renameEB:GetText())
buttons[i].label:SetText(i.."."..CellDB["snippets"][i]["name"])
end)
end)
-- checkbox
buttons[i].cb = Cell:CreateCheckButton(buttons[i], "", function(checked)
CellDB["snippets"][i]["autorun"] = checked
end)
buttons[i].cb:SetPoint("LEFT", 3, 0)
buttons[i].cb:HookScript("OnEnter", function()
buttons[i]:GetScript("OnEnter")(buttons[i])
end)
buttons[i].cb:HookScript("OnLeave", function()
buttons[i]:GetScript("OnLeave")(buttons[i])
end)
-- delete
buttons[i].del = CreateFrame("Button", nil, buttons[i])
buttons[i].del:SetPoint("RIGHT", -1, 0)
buttons[i].del:SetSize(12, 12)
buttons[i].del.tex = buttons[i].del:CreateTexture(nil, "ARTWORK")
buttons[i].del.tex:SetAllPoints(buttons[i].del)
buttons[i].del.tex:SetTexture("Interface\\AddOns\\Cell\\Media\\Icons\\close.tga")
buttons[i].del.tex:SetVertexColor(0.4, 0.4, 0.4, 1)
buttons[i].del:SetScript("OnEnter", function()
buttons[i]:GetScript("OnEnter")(buttons[i])
buttons[i].del.tex:SetVertexColor(1, 1, 1, 1)
end)
buttons[i].del:SetScript("OnLeave", function()
buttons[i]:GetScript("OnLeave")(buttons[i])
buttons[i].del.tex:SetVertexColor(0.4, 0.4, 0.4, 1)
end)
buttons[i].del:SetScript("OnClick", function()
if IsShiftKeyDown() then
tremove(CellDB["snippets"], i)
if selected == i then -- delete selected
selected = 0
forceLoadSelected = true
elseif selected > i then -- before selected
selected = selected - 1
renameEB:Hide()
end
LoadList()
end
end)
-- label
buttons[i].label = buttons[i]:CreateFontString(nil, "OVERLAY", "CELL_FONT_WIDGET")
buttons[i].label:SetPoint("LEFT", buttons[i].cb, "RIGHT", 3, 0)
buttons[i].label:SetPoint("RIGHT", buttons[i].del, "LEFT", -3, 0)
buttons[i].label:SetJustifyH("LEFT")
buttons[i].label:SetWordWrap(false)
-- tooltip
buttons[i].ShowTooltip = function()
if buttons[i].label:IsTruncated() then
CellTooltip:SetOwner(buttons[i], "ANCHOR_NONE")
CellTooltip:SetPoint("BOTTOMLEFT", buttons[i], "TOPLEFT", 0, 1)
CellTooltip:AddLine(buttons[i].label:GetText())
CellTooltip:Show()
end
end
buttons[i].HideTooltip = function()
CellTooltip:Hide()
end
end
buttons[i].cb:SetChecked(t["autorun"])
buttons[i].label:SetText(i.."."..t["name"])
buttons[i]:ClearAllPoints()
if i % 4 == 0 then
buttons[i]:SetPoint("TOPLEFT", buttons[i-4], "BOTTOMLEFT", 0, 1)
else
buttons[i]:SetPoint("TOPLEFT", buttons[i-1], "TOPRIGHT", -1, 0)
end
buttons[i]:Show()
end
-- update NEW button
local total = #CellDB["snippets"]
if total == 0 then
newBtn:ClearAllPoints()
newBtn:SetPoint("TOPLEFT", buttons[0], "TOPRIGHT", -1, 0)
newBtn:Show()
elseif total == 19 then
newBtn:ClearAllPoints()
newBtn:Hide()
elseif (total + 1) % 4 == 0 then
newBtn:ClearAllPoints()
newBtn:SetPoint("TOPLEFT", buttons[total-3], "BOTTOMLEFT", 0, 1)
newBtn:Show()
else
newBtn:ClearAllPoints()
newBtn:SetPoint("TOPLEFT", buttons[total], "TOPRIGHT", -1, 0)
newBtn:Show()
end
-- highlight
local Highlight = Cell:CreateButtonGroup(buttons, function(index)
LoadSnippet(index)
end)
Highlight(selected)
LoadSnippet(selected)
-- update height
local rows
if total == 19 then
rows = 5
else
rows = math.ceil((total+2) / 4)
end
topPane:SetHeight(rows*20 - (rows-1))
-- update scroll
codePane.scrollFrame:UpdateSize()
-- hide spare buttons
for i = total+1, #buttons do
buttons[i]:ClearAllPoints()
buttons[i]:Hide()
end
end
LoadSnippet = function(index)
if selected ~= index or forceLoadSelected then
selected = index
forceLoadSelected = false
codePane:SetText(CellDB["snippets"][index]["code"])
codePane:SetEnabled(true)
bottomPane.runBtn:SetEnabled(true)
bottomPane.saveBtn:SetEnabled(false)
bottomPane.cancelBtn:SetEnabled(false)
renameEB:Hide()
errorPopup:Hide()
end
end
RunSnippet = function(snippet)
-- https://wowpedia.fandom.com/wiki/API_loadstring
local func, errorMessage = loadstring(snippet)
if (not func) then
return errorMessage
end
local success, errorMessage = pcall(func)
if (not success) then
return errorMessage
end
end
function F:ShowCodeSnippets()
if not codeSnippetsFrame then
CreateCodeSnippetsFrame()
P:PixelPerfectPoint(codeSnippetsFrame)
LoadList()
end
if codeSnippetsFrame:IsShown() then
codeSnippetsFrame:Hide()
else
codeSnippetsFrame:Show()
end
end
function F:RunSnippets()
for i = 0, #CellDB["snippets"] do
local t = CellDB["snippets"][i]
if t["autorun"] then
local errorMsg = RunSnippet(t["code"])
if errorMsg then
F:Print("|cFFFF3030Snippet Error ("..i.."."..(t["name"] or "Cell").."):|r "..errorMsg)
end
end
end
end
function F:GetDefaultSnippet()
return {
["autorun"] = true,
["code"] = "-- snippets can be found at https://github.com/enderneko/Cell/tree/master/.snippets\n"..
"-- use \"/run CellDB['snippets'][0]=nil ReloadUI()\" to reset this snippet\n\n"..
"-- cooldown style for icon/block indicators (\"VERTICAL\", \"CLOCK\")\n"..
"CELL_COOLDOWN_STYLE = \"VERTICAL\"\n\n"..
"-- fade out unit button if hp percent > (number: 0-1)\n"..
"CELL_FADE_OUT_HEALTH_PERCENT = nil\n\n"..
"-- add summon icons to Status Icon indicator (boolean, retail only)\n"..
"CELL_SUMMON_ICONS_ENABLED = false\n\n"..
"-- use separate width and height for custom indicator icons (boolean)\n"..
"CELL_RECTANGULAR_CUSTOM_INDICATOR_ICONS = false\n\n"..
"-- Use nicknames from Details! Damage Meter (boolean, NickTag-1.0 library)\n"..
"CELL_NICKTAG_ENABLED = false\n\n"..
"-- remove raid setup details from the tooltip of the Raid button (boolean)\n"..
"CELL_TOOLTIP_REMOVE_RAID_SETUP_DETAILS = false\n\n"..
"-- border thickness: unit button and icon (number)\n"..
"CELL_BORDER_SIZE = 1\n\n"..
"-- unit button border color ({r, g, b, a}, number: 0-1)\n"..
"CELL_BORDER_COLOR = {0, 0, 0, 1}\n\n"..
"-- show raid pet owner name (\"VEHICLE\", \"NAME\", nil)\n"..
"CELL_SHOW_RAID_PET_OWNER_NAME = nil\n\n"..
"-- use LibHealComm (boolean, non-retail)\n"..
"CELL_USE_LIBHEALCOMM = false"
}
end
function F:DisableSnippets()
for i = 1, #CellDB["snippets"] do
CellDB["snippets"][i]["autorun"] = false
end
local popup = Cell:CreateNotificationPopup(Cell.frames.anchorFrame, 200, L["All snippets have been disabled, due to the version update"])
popup:RegisterEvent("PLAYER_ENTERING_WORLD")
popup:SetScript("OnEvent", function()
popup:UnregisterAllEvents()
popup:SetScript("OnEvent", nil)
popup:SetPoint(Cell.vars.currentLayoutTable.main.anchor)
popup:Show()
end)
end