ESOUI SVN ZAMNotebook

[/] [trunk/] [ZAM_Notebook/] [ZAM_Notebook.lua] - Rev 14

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)

Compare with Previous | Blame