Compare with Previous | Blame | View Log
-- ZAM_Notebook © ZAM Network LLC
-- All Rights Reserved
local wm = WINDOW_MANAGER
local em = EVENT_MANAGER
local znb, db, indexPool, currentlyViewing
local tinsert = table.insert
local tremove = table.remove
local defaults = {
anchor = {
a = CENTER,
b = CENTER,
x = 0,
y = 0,
}
}
local function ProtectText(text) --protect against backslashes corrupting our saved variables
return text:gsub([[\]], [[%%92]])
end
local function UnprotectText(text) --convert back to what should be displayed
return text:gsub([[%%92]], [[\]])
end
local buttonCount = 1
local function CreateIndexButton(indexPool)
local button = ZO_ObjectPool_CreateControl("ZAM_NotebookIndex", indexPool, znb.menu.scrollChild)
local anchorBtn = buttonCount == 1 and znb.menu.scrollChild or indexPool:AcquireObject(buttonCount-1)
button:SetAnchor(TOPLEFT, anchorBtn, buttonCount == 1 and TOPLEFT or BOTTOMLEFT)
button:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
button:SetWidth(190)
button:SetHandler("OnClicked", function(self)
znb.titleEdit:SetText(UnprotectText(self.data.title))
znb.edit:SetText(UnprotectText(self.data.text))
currentlyViewing = self.id
znb.save.highlight:SetHidden(true)
znb.selectedHL:SetHidden(false)
znb.selectedHL:ClearAnchors()
znb.selectedHL:SetAnchorFill(self)
end)
buttonCount = buttonCount + 1
return button
end
local function RemoveIndexButton(button)
button:SetHidden(true)
end
local function PopulateScrollList()
local numPages = #db.pages
for i = 1, numPages do
local button = indexPool:AcquireObject(i)
button.data = db.pages[i]
button.id = i
button:SetText(UnprotectText(button.data.title))
button:SetHidden(false)
end
local activePages = indexPool:GetActiveObjectCount()
if activePages > numPages then
for i = numPages+1, activePages do
indexPool:ReleaseObject(i)
end
end
end
local function CreateNotebook()
--main window
znb = wm:CreateTopLevelWindow("ZAM_Notebook")
znb:SetDimensions(800, 650)
znb:SetAnchor(db.anchor.a, GuiRoot, db.anchor.b, db.anchor.x, db.anchor.y)
znb:SetClampedToScreen(true)
znb:SetMouseEnabled(true)
znb:SetMovable(true)
znb:SetHandler("OnReceiveDrag", function(self)
--if not db.locked then
self:StartMoving()
--end
end)
znb:SetHandler("OnMouseUp", function(self)
self:StopMovingOrResizing()
local _,a,_,b,x,y = self:GetAnchor()
db.anchor = {["a"]=a, ["b"]=b, ["x"]=x, ["y"]=y}
end)
--window bg
znb.bg = wm:CreateControl("ZAM_NotebookBG", znb, CT_TEXTURE)
znb.bg:SetTexture("ZAM_Notebook\\NotebookBG.dds")
znb.bg:SetTextureCoords(0, 0.98, 0, 0.85)
znb.bg:SetAnchorFill(znb)
--window title
znb.title = wm:CreateControl("ZAM_NotebookTitle", znb, CT_LABEL)
znb.title:SetAnchor(TOPLEFT, znb, TOPLEFT, 50, 50)
znb.title:SetFont("ZoFontWindowTitle")
znb.title:SetText("ZAM Notebook")
--divider below title
znb.titleDiv = wm:CreateControl("ZAM_NotebookTitleDiv", znb, CT_TEXTURE)
znb.titleDiv:SetDimensions(800, 4)
znb.titleDiv:SetAnchor(TOPLEFT, znb.title, BOTTOMLEFT, -50, 5)
znb.titleDiv:SetTexture("EsoUI\\Art\\Miscellaneous\\centerscreen_topDivider.dds")
--pages menu
znb.menu = wm:CreateControlFromVirtual("ZAM_NotebookMenu", znb, "ZO_ScrollContainer")
znb.menu:SetAnchor(TOPLEFT, znb.titleDiv, BOTTOMLEFT, 70, 30)
znb.menu:SetAnchor(BOTTOMLEFT, znb, BOTTOMLEFT, 70, -60)
znb.menu:SetWidth(200)
znb.menu.scrollChild = znb.menu:GetNamedChild("ScrollChild")
--page selected highlight
znb.selectedHL = wm:CreateControl(nil, znb.menu.scrollChild, CT_TEXTURE)
local selectedHL = znb.selectedHL
selectedHL:SetTexture("EsoUI\\Art\\Buttons\\generic_highlight.dds")
selectedHL:SetHidden(true)
--divider between menu and notebook editbox
znb.divider = wm:CreateControl("ZAM_NotebookDivider", znb, CT_TEXTURE)
znb.divider:SetAnchor(TOPLEFT, znb.menu, TOPRIGHT, 15, -15)
znb.divider:SetAnchor(BOTTOMLEFT, znb.menu, BOTTOMRIGHT)
znb.divider:SetWidth(4)
znb.divider:SetTexture("EsoUI\\Art\\Miscellaneous\\window_edge.dds")
--page title editbox bg
znb.titleEditbg = wm:CreateControlFromVirtual("ZAM_NotebookTitleEditBG", znb, "ZO_EditBackdrop")
znb.titleEditbg:SetDimensions(250, 28)
znb.titleEditbg:SetAnchor(TOPLEFT, znb.divider, TOPRIGHT, 15, 15)
--page title editbox
znb.titleEdit = wm:CreateControlFromVirtual("ZAM_NotebookTitleEdit", znb.titleEditbg, "ZO_DefaultEditForBackdrop")
znb.titleEdit:SetHandler("OnTab", function() znb.edit:TakeFocus() end)
znb.titleEdit:SetHandler("OnEscape", znb.titleEdit.LoseFocus)
--editbox bg
znb.editbg = wm:CreateControlFromVirtual("ZAM_NotebookEditBG", znb, "ZO_EditBackdrop")
znb.editbg:SetDimensions(450, 350)
znb.editbg:SetAnchor(TOPLEFT, znb.titleEditbg, BOTTOMLEFT, 0, 15)
--editbox
znb.edit = wm:CreateControlFromVirtual("ZAM_NotebookEdit", znb.editbg, "ZO_DefaultEditMultiLineForBackdrop")
znb.edit:SetMaxInputChars(3000)
znb.edit:SetHandler("OnTab", function() if IsShiftKeyDown() then znb.titleEdit:TakeFocus() end end)
znb.edit:SetHandler("OnEscape", znb.edit.LoseFocus)
znb.edit:SetHandler("OnMouseWheel", function(self, delta)
if self:HasFocus() then --only set focus to new spots if the editbox is currently in use
local cursorPos = self:GetCursorPosition()
local text = self:GetText()
local textLen = text:len()
local newPos
if delta > 0 then --scrolling up
local reverseText = text:reverse()
local revCursorPos = textLen - cursorPos
local revPos = reverseText:find("\n", revCursorPos+1)
newPos = revPos and textLen - revPos
else --scrolling down
newPos = text:find("\n", cursorPos+1)
end
if newPos then --if we found a new line, then scroll, otherwise don't
self:SetCursorPosition(newPos)
end
end
end)
--run script button
znb.run = wm:CreateControl("ZAM_NotebookRun", znb, CT_BUTTON)
znb.run:SetDimensions(34, 34)
znb.run:SetAnchor(TOPLEFT, znb.editbg, BOTTOMLEFT, 0, 12)
znb.run:SetNormalTexture("EsoUI\\Art\\Buttons\\edit_up.dds")
znb.run:SetPressedTexture("EsoUI\\Art\\Buttons\\edit_down.dds")
znb.run:SetMouseOverTexture("EsoUI\\Art\\Buttons\\edit_over.dds")
znb.run.data = {tooltipText = "Run this page as a Lua script."}
znb.run:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
znb.run:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
--setting to run at startup?
znb.run:SetHandler("OnClicked", function()
local znbScript = zo_loadstring(znb.edit:GetText())
if znbScript then
znbScript()
end
end)
--undo changes button
znb.undo = wm:CreateControl("ZAM_NotebookUndo", znb, CT_BUTTON)
znb.undo:SetDimensions(30, 30)
znb.undo:SetAnchor(LEFT, znb.run, RIGHT, 15, 1)
znb.undo:SetNormalTexture("EsoUI\\Art\\Buttons\\decline_up.dds")
znb.undo:SetPressedTexture("EsoUI\\Art\\Buttons\\decline_down.dds")
znb.undo:SetMouseOverTexture("EsoUI\\Art\\Buttons\\decline_over.dds")
znb.undo.data = {tooltipText = "Undo changes made to this page."}
znb.undo:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
znb.undo:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
znb.undo:SetHandler("OnClicked", function()
if currentlyViewing then
znb.titleEdit:SetText(db.pages[currentlyViewing].title)
znb.edit:SetText(db.pages[currentlyViewing].text)
end
end)
--save changes button
znb.save = wm:CreateControl("ZAM_NotebookSave", znb, CT_BUTTON)
znb.save.highlight = wm:CreateControl("ZAM_NotebookSaveHL", znb.save, CT_TEXTURE)
local highlight = znb.save.highlight
znb.save:SetDimensions(30, 30)
znb.save:SetAnchor(LEFT, znb.undo, RIGHT, 15, 1)
znb.save:SetNormalTexture("EsoUI\\Art\\Buttons\\accept_up.dds")
znb.save:SetPressedTexture("EsoUI\\Art\\Buttons\\accept_down.dds")
znb.save:SetMouseOverTexture("EsoUI\\Art\\Buttons\\accept_over.dds")
znb.save.data = {tooltipText = "Save changes made to this page."}
znb.save:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
znb.save:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
znb.save:SetHandler("OnClicked", function(self)
local titleText = znb.titleEdit:GetText()
if titleText == "" then
znb.titleEdit:SetText("New Page "..#db.pages+1)
titleText = znb.titleEdit:GetText()
end
local pageText = znb.edit:GetText()
--with the changes to how text is stored in saved variables, literal strings work again.
--if pageText:find("%[%[") then
-- error([=[ZAM_Notebook does not support literal strings.
--
-- This would cause a nested literal string error and erase your saved variables data.
-- Please edit your page text before saving to remove the literal string. ( [[...]] )]=], 0)
-- return
--end]]
--so now we need to prevent escaped quotes instead...
--if pageText:find("%\\\"") then
-- error([=[ZAM_Notebook does not support escaped double-quotes.
--
-- Because ESO saved variables currently escape any double-quotes found in their contents,
-- this would cause a malformed table error and erase your saved variables data.
--
-- Please edit your page text before saving to remove the escaped double-quote ( \" ).
-- You may use a single quote instead ( \' ) or change to use a literal string. ( [[ "quote" ]] )]=], 0)
-- return
--end
local safe_pageText = ProtectText(pageText)
local safe_titleText = ProtectText(titleText)
if currentlyViewing == nil then --if this was a new page
tinsert(db.pages, {["title"] = safe_titleText, ["text"]=safe_pageText})
currentlyViewing = #db.pages
znb.selectedHL:SetHidden(false)
znb.selectedHL:ClearAnchors()
self.new = true
else
db.pages[currentlyViewing].title = safe_titleText
db.pages[currentlyViewing].text = safe_pageText
self.new = false
end
PopulateScrollList()
if self.new then
znb.selectedHL:SetAnchorFill(_G["ZAM_NotebookIndex"..currentlyViewing])
end
highlight:SetHidden(true)
end)
highlight:SetAnchor(TOPLEFT, znb.save, TOPLEFT, -15, -15)
highlight:SetAnchor(BOTTOMRIGHT, znb.save, BOTTOMRIGHT, 15, 15)
highlight:SetTexture("EsoUI\\Art\\Miscellaneous\\icon_highlight_pulse.dds")
highlight:SetAlpha(.75)
highlight:SetHidden(true)
znb.titleEdit:SetHandler("OnTextChanged", function(self)
local page = db.pages[currentlyViewing]
if not page or self:GetText() ~= page.title or self:GetText() then
highlight:SetHidden(false)
else
highlight:SetHidden(true)
end
end)
znb.edit:SetHandler("OnTextChanged", function(self)
local page = db.pages[currentlyViewing]
if not page or self:GetText() ~= page.text or self:GetText() then
highlight:SetHidden(false)
else
highlight:SetHidden(true)
end
end)
--close window button
znb.close = wm:CreateControlFromVirtual("ZAM_NotebookClose", znb, "ZO_DefaultTextButton")
znb.close:SetText("Close")
znb.close:SetAnchor(TOPRIGHT, znb.editbg, BOTTOMRIGHT, 0, 15)
znb.close:SetWidth(75)
znb.close:SetHandler("OnClicked", function() znb:SetHidden(true) end)
--new page button
znb.new = wm:CreateControl("ZAM_NotebookNew", znb, CT_BUTTON)
znb.new:SetDimensions(30, 30)
znb.new:SetAnchor(LEFT, znb.titleEditbg, RIGHT, 15, 0)
znb.new:SetNormalTexture("EsoUI\\Art\\Buttons\\pointsplus_up.dds")
znb.new:SetPressedTexture("EsoUI\\Art\\Buttons\\pointsplus_down.dds")
znb.new:SetMouseOverTexture("EsoUI\\Art\\Buttons\\pointsplus_over.dds")
znb.new.data = {tooltipText = "Create a new page."}
znb.new:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
znb.new:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
znb.new:SetHandler("OnClicked", function()
currentlyViewing = nil
znb.titleEdit:SetText("New Page "..#db.pages+1)
znb.titleEdit:SelectAll()
znb.titleEdit:TakeFocus()
znb.edit:Clear()
end)
--delete page button
znb.delete = wm:CreateControl("ZAM_NotebookDelete", znb, CT_BUTTON)
znb.delete:SetDimensions(32, 32)
znb.delete:SetAnchor(LEFT, znb.new, RIGHT, 15, 0)
znb.delete:SetNormalTexture("EsoUI\\Art\\Buttons\\minus_up.dds")
znb.delete:SetPressedTexture("EsoUI\\Art\\Buttons\\minus_down.dds")
znb.delete:SetMouseOverTexture("EsoUI\\Art\\Buttons\\minus_over.dds")
znb.delete.data = {tooltipText = "Delete this page."}
znb.delete:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
znb.delete:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
znb.delete:SetHandler("OnClicked", function()
if currentlyViewing then
tremove(db.pages, currentlyViewing)
currentlyViewing = nil
PopulateScrollList()
znb.save.highlight:SetHidden(true)
znb.selectedHL:SetHidden(true)
end
znb.titleEdit:Clear()
znb.edit:Clear()
highlight:SetHidden(true)
end)
znb:SetHidden(true)
end
--global for keybind
function ZAMNotebookToggleVisibility()
if znb:IsHidden() then
znb:SetHidden(false)
if not SCENE_MANAGER:IsInUIMode() then
SCENE_MANAGER:SetInUIMode(true)
end
else
znb:SetHidden(true)
end
end
local function Initialize()
ZAM_NotebookDB = ZAM_NotebookDB or {}
for k,v in pairs(defaults) do
if type(ZAM_NotebookDB[k]) == "nil" then
ZAM_NotebookDB[k] = v
end
end
ZAM_NotebookDB.pages = ZAM_NotebookDB.pages or {}
db = ZAM_NotebookDB
indexPool = ZO_ObjectPool:New(CreateIndexButton, RemoveIndexButton)
ZO_CreateStringId("SI_BINDING_NAME_ZAM_NOTEBOOK_TOGGLE", "Toggle ZAM Notebook")
SLASH_COMMANDS["/znb"] = ZAMNotebookToggleVisibility
end
em:RegisterForEvent("ZAM_Notebook", EVENT_ADD_ON_LOADED, function(event, addon)
--em:RegisterForEvent("ZAM_Notebook", EVENT_PLAYER_ACTIVATED, function(event, addon)
if addon == "ZAM_Notebook" then
Initialize()
CreateNotebook()
PopulateScrollList()
end
end)