Files
pfUI/modules/share.lua
T
shagu 0214eebf36 core: switch from mousedown to drag functions
Due to crashes/freezes while moving some frames, one possible
reason could be that pfUI was using OnMouseDown and OnMouseUp
to run its frame-moving code. I have noticed better performance
when using the intended functions, OnDragStart and OnDragStop
to move frames.

This commit changes every occurrence of such functions and splits
drag and click into seperate functions where required.
2022-05-07 21:35:52 +02:00

450 lines
14 KiB
Lua

pfUI:RegisterModule("share", "vanilla:tbc", function ()
local function serialize(tbl, comp, name, ignored, spacing)
local spacing = spacing or ""
local match = nil
local tname = ( spacing == "" and "" or "[\"" ) .. name .. ( spacing == "" and "" or "\"]" )
local str = spacing .. tname .. " = {\n"
for k, v in pairs(tbl) do
if not ( ignored[k] and spacing == "" ) and ( not comp or not comp[k] or comp[k] ~= tbl[k] ) then
if type(v) == "table" then
local result = serialize(tbl[k], comp and comp[k], k, ignored, spacing .. " ")
if result then
match = true
str = str .. result
end
elseif type(v) == "string" then
match = true
str = str .. spacing .. " [\""..k.."\"] = \"".. string.gsub(v, "\\", "\\\\") .."\",\n"
elseif type(v) == "number" then
match = true
str = str .. spacing .. " [\""..k.."\"] = ".. string.gsub(v, "\\", "\\\\") ..",\n"
end
end
end
str = str .. spacing .. "}" .. ( spacing == "" and "" or "," ) .. "\n"
return match and str or nil
end
local function compress(input)
-- based on Rochet2's lzw compression
if type(input) ~= "string" then
return nil
end
local len = strlen(input)
if len <= 1 then
return "u"..input
end
local dict = {}
for i = 0, 255 do
local ic, iic = strchar(i), strchar(i, 0)
dict[ic] = iic
end
local a, b = 0, 1
local result = {"c"}
local resultlen = 1
local n = 2
local word = ""
for i = 1, len do
local c = strsub(input, i, i)
local wc = word..c
if not dict[wc] then
local write = dict[word]
if not write then
return nil
end
result[n] = write
resultlen = resultlen + strlen(write)
n = n+1
if len <= resultlen then
return "u"..input
end
local str = wc
if a >= 256 then
a, b = 0, b+1
if b >= 256 then
dict = {}
b = 1
end
end
dict[str] = strchar(a,b)
a = a+1
word = c
else
word = wc
end
end
result[n] = dict[word]
resultlen = resultlen+strlen(result[n])
n = n+1
if len <= resultlen then
return "u"..input
end
return table.concat(result)
end
local function decompress(input)
-- based on Rochet2's lzw compression
if type(input) ~= "string" or strlen(input) < 1 then
return nil
end
local control = strsub(input, 1, 1)
if control == "u" then
return strsub(input, 2)
elseif control ~= "c" then
return nil
end
input = strsub(input, 2)
local len = strlen(input)
if len < 2 then
return nil
end
local dict = {}
for i = 0, 255 do
local ic, iic = strchar(i), strchar(i, 0)
dict[iic] = ic
end
local a, b = 0, 1
local result = {}
local n = 1
local last = strsub(input, 1, 2)
result[n] = dict[last]
n = n+1
for i = 3, len, 2 do
local code = strsub(input, i, i+1)
local lastStr = dict[last]
if not lastStr then
return nil
end
local toAdd = dict[code]
if toAdd then
result[n] = toAdd
n = n+1
local str = lastStr..strsub(toAdd, 1, 1)
if a >= 256 then
a, b = 0, b+1
if b >= 256 then
dict = {}
b = 1
end
end
dict[strchar(a,b)] = str
a = a+1
else
local str = lastStr..strsub(lastStr, 1, 1)
result[n] = str
n = n+1
if a >= 256 then
a, b = 0, b+1
if b >= 256 then
dict = {}
b = 1
end
end
dict[strchar(a,b)] = str
a = a+1
end
last = code
end
return table.concat(result)
end
local function enc(to_encode)
local index_table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
local bit_pattern = ''
local encoded = ''
local trailing = ''
for i = 1, string.len(to_encode) do
local remaining = tonumber(string.byte(string.sub(to_encode, i, i)))
local bin_bits = ''
for i = 7, 0, -1 do
local current_power = math.pow(2, i)
if remaining >= current_power then
bin_bits = bin_bits .. '1'
remaining = remaining - current_power
else
bin_bits = bin_bits .. '0'
end
end
bit_pattern = bit_pattern .. bin_bits
end
if mod(string.len(bit_pattern), 3) == 2 then
trailing = '=='
bit_pattern = bit_pattern .. '0000000000000000'
elseif mod(string.len(bit_pattern), 3) == 1 then
trailing = '='
bit_pattern = bit_pattern .. '00000000'
end
local count = 0
for i = 1, string.len(bit_pattern), 6 do
local byte = string.sub(bit_pattern, i, i+5)
local offset = tonumber(tonumber(byte, 2))
encoded = encoded .. string.sub(index_table, offset+1, offset+1)
count = count + 1
if count >= 92 then
encoded = encoded .. "\n"
count = 0
end
end
return string.sub(encoded, 1, -1 - string.len(trailing)) .. trailing
end
local function dec(to_decode)
local index_table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
local padded = gsub(to_decode,"%s", "")
local unpadded = gsub(padded,"=", "")
local bit_pattern = ''
local decoded = ''
to_decode = gsub(to_decode,"\n", "")
to_decode = gsub(to_decode," ", "")
for i = 1, string.len(unpadded) do
local char = string.sub(to_decode, i, i)
local offset, _ = string.find(index_table, char)
if offset == nil then return nil end
local remaining = tonumber(offset-1)
local bin_bits = ''
for i = 7, 0, -1 do
local current_power = math.pow(2, i)
if remaining >= current_power then
bin_bits = bin_bits .. '1'
remaining = remaining - current_power
else
bin_bits = bin_bits .. '0'
end
end
bit_pattern = bit_pattern .. string.sub(bin_bits, 3)
end
for i = 1, string.len(bit_pattern), 8 do
local byte = string.sub(bit_pattern, i, i+7)
decoded = decoded .. strchar(tonumber(byte, 2))
end
local padding_length = string.len(padded)-string.len(unpadded)
if (padding_length == 1 or padding_length == 2) then
decoded = string.sub(decoded,1,-2)
end
return decoded
end
do -- Window
local f = CreateFrame("Frame", "pfShare", UIParent)
f:Hide()
f:SetPoint("CENTER", 0, 0)
f:SetWidth(580)
f:SetHeight(420)
f:SetMovable(true)
f:EnableMouse(true)
f:RegisterForDrag("LeftButton")
f:SetScript("OnDragStart", function() f:StartMoving() end)
f:SetScript("OnDragStop", function() f:StopMovingOrSizing() end)
f:SetScript("OnShow", function()
if pfUI.gui and pfUI.gui:IsShown() then
f.hadGUI = true
pfUI.gui:Hide()
else
f.hadGUI = nil
end
end)
f:SetScript("OnHide", function()
if f.hadGUI then
pfUI.gui:Show()
end
end)
CreateBackdrop(f, nil, true, 0.8)
CreateBackdropShadow(f)
table.insert(UISpecialFrames, "pfShare")
do -- Edit Box
f.scroll = pfUI.api.CreateScrollFrame("pfShareScroll", f)
f.scroll:SetPoint("TOPLEFT", f, "TOPLEFT", 10, -30)
f.scroll:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", -10, 50)
f.scroll:SetWidth(560)
f.scroll:SetHeight(400)
f.scroll.backdrop = CreateFrame("Frame", "pfShareScrollBackdrop", f.scroll)
f.scroll.backdrop:SetFrameLevel(1)
f.scroll.backdrop:SetPoint("TOPLEFT", f.scroll, "TOPLEFT", -5, 5)
f.scroll.backdrop:SetPoint("BOTTOMRIGHT", f.scroll, "BOTTOMRIGHT", 5, -5)
pfUI.api.CreateBackdrop(f.scroll.backdrop, nil, true)
f.scroll.text = CreateFrame("EditBox", "pfShareEditBox", f.scroll)
f.scroll.text.bg = f.scroll.text:CreateTexture(nil, "OVERLAY")
f.scroll.text.bg:SetAllPoints(f.scroll.text)
f.scroll.text.bg:SetTexture(1,1,1,.05)
f.scroll.text:SetMultiLine(true)
f.scroll.text:SetWidth(560)
f.scroll.text:SetHeight(400)
f.scroll.text:SetAllPoints(f.scroll)
f.scroll.text:SetTextInsets(15,15,15,15)
f.scroll.text:SetFont(pfUI.media["font:RobotoMono.ttf"], 9)
f.scroll.text:SetAutoFocus(false)
f.scroll.text:SetJustifyH("LEFT")
f.scroll.text:SetScript("OnEscapePressed", function() this:ClearFocus() end)
f.scroll.text:SetScript("OnTextChanged", function()
this:GetParent():UpdateScrollChildRect()
this:GetParent():UpdateScrollState()
local _, error = loadstring(f.scroll.text:GetText())
if error or string.gsub(this:GetText(), " ", "") == "" then
f.loadButton:Disable()
f.loadButton.text:SetTextColor(1,.5,.5,1)
else
f.loadButton:Enable()
f.loadButton.text:SetTextColor(.5,1,.5,1)
end
local trydec = dec(this:GetText())
if string.gsub(this:GetText(), " ", "") == "" then
f.readButton.text:SetText(T["N/A"])
f.readButton:Disable()
elseif not trydec or trydec == "" then
f.readButton:Enable()
f.readButton.text:SetText(T["Encode"])
f.readButton.func = function()
local compressed = enc(compress(f.scroll.text:GetText()))
f.scroll.text:SetText(compressed)
end
else
f.readButton:Enable()
f.readButton.text:SetText(T["Decode"])
f.readButton.func = function()
local uncompressed = decompress(dec(f.scroll.text:GetText()))
f.scroll.text:SetText(uncompressed)
end
end
end)
f.scroll:SetScrollChild(f.scroll.text)
end
do -- button: close
f.closeButton = CreateFrame("Button", "pfShareClose", f)
f.closeButton:SetPoint("TOPRIGHT", -5, -5)
f.closeButton:SetHeight(12)
f.closeButton:SetWidth(12)
f.closeButton.texture = f.closeButton:CreateTexture("pfQuestionDialogCloseTex")
f.closeButton.texture:SetTexture(pfUI.media["img:close"])
f.closeButton.texture:ClearAllPoints()
f.closeButton.texture:SetAllPoints(f.closeButton)
f.closeButton.texture:SetVertexColor(1,.25,.25,1)
pfUI.api.SkinButton(f.closeButton, 1, .5, .5)
f.closeButton:SetScript("OnClick", function()
this:GetParent():Hide()
end)
end
do -- checkbox: ignore positions
f.ignorePosition = CreateFrame("CheckButton", "pfShareIgnorePosition", f, "UICheckButtonTemplate")
f.ignorePosition:SetNormalTexture("")
f.ignorePosition:SetPushedTexture("")
f.ignorePosition:SetHighlightTexture("")
CreateBackdrop(f.ignorePosition, nil, true)
f.ignorePosition:SetWidth(14)
f.ignorePosition:SetHeight(14)
f.ignorePosition:SetPoint("BOTTOMLEFT", 10, 10)
f.ignorePosition:SetChecked()
f.ignorePositionCaption = f.ignorePosition:CreateFontString("Status", "LOW", "GameFontNormal")
f.ignorePositionCaption:SetFont(pfUI.font_default, C.global.font_size + 2, "OUTLINE")
f.ignorePositionCaption:SetPoint("LEFT", f.ignorePosition, "RIGHT", 5, 0)
f.ignorePositionCaption:SetFontObject(GameFontWhite)
f.ignorePositionCaption:SetJustifyH("LEFT")
f.ignorePositionCaption:SetText(T["Ignore Layout"])
end
do -- button: load
f.loadButton = CreateFrame("Button", "pfShareLoad", f)
pfUI.api.SkinButton(f.loadButton)
f.loadButton:SetPoint("BOTTOMRIGHT", -5, 5)
f.loadButton:SetWidth(75)
f.loadButton:SetHeight(25)
f.loadButton.text = f.loadButton:CreateFontString("Caption", "LOW", "GameFontWhite")
f.loadButton.text:SetAllPoints(f.loadButton)
f.loadButton.text:SetFont(pfUI.font_default, pfUI_config.global.font_size, "OUTLINE")
f.loadButton.text:SetText(T["Import"])
f.loadButton:SetScript("OnClick", function()
local ImportConfig, error = loadstring(f.scroll.text:GetText())
if not error and f.scroll.text:GetText() ~= "" then
ImportConfig()
pfUI:LoadConfig()
CreateQuestionDialog(T["Some settings need to reload the UI to take effect.\nDo you want to reloadUI now?"], ReloadUI)
end
end)
end
do -- button: read
f.readButton = CreateFrame("Button", "pfShareDecode", f)
pfUI.api.SkinButton(f.readButton)
f.readButton:SetPoint("RIGHT", f.loadButton, "LEFT", -10, 0)
f.readButton:SetWidth(75)
f.readButton:SetHeight(25)
f.readButton.text = f.readButton:CreateFontString("Caption", "LOW", "GameFontWhite")
f.readButton.text:SetAllPoints(f.readButton)
f.readButton.text:SetFont(pfUI.font_default, pfUI_config.global.font_size, "OUTLINE")
f.readButton.text:SetText(T["N/A"])
f.readButton:SetScript("OnClick", function()
this.func()
end)
end
do -- button: export
f.exportButton = CreateFrame("Button", "pfShareExport", f)
pfUI.api.SkinButton(f.exportButton)
f.exportButton:SetPoint("RIGHT", f.readButton, "LEFT", -10, 0)
f.exportButton:SetWidth(75)
f.exportButton:SetHeight(25)
f.exportButton.text = f.exportButton:CreateFontString("Caption", "LOW", "GameFontWhite")
f.exportButton.text:SetAllPoints(f.exportButton)
f.exportButton.text:SetFont(pfUI.font_default, pfUI_config.global.font_size, "OUTLINE")
f.exportButton.text:SetText(T["Export"])
f.exportButton:SetScript("OnClick", function()
-- generate a default config
local myconfig = CopyTable(pfUI_config)
_G.pfUI_config = {}
pfUI:LoadConfig()
local defconfig = CopyTable(pfUI_config)
-- restore config and references
_G.pfUI_config = CopyTable(myconfig)
C = _G.pfUI_config
local ignored = {}
ignored["position"] = f.ignorePosition:GetChecked()
ignored["disabled"] = f.ignorePosition:GetChecked()
local compressed = enc(compress(serialize(myconfig, defconfig, "pfUI_config", ignored)))
f.scroll.text:SetText(compressed)
f.scroll.text.value = compressed
f.scroll:SetVerticalScroll(0)
end)
end
_G.SLASH_PFEXPORT1, _G.SLASH_PFEXPORT2, _G.SLASH_PFEXPORT3 = "/export", "/import", "/share"
function SlashCmdList.PFEXPORT(msg, editbox)
f:Show()
end
end
end)