WoWInterface SVN MapofAzeroth

[/] [trunk/] [Libs/] [AceGUI-3.0/] [widgets/] [AceGUIWidget-MultiLineEditBox.lua] - Rev 28

Compare with Previous | Blame | View Log

--[[
--Multiline Editbox Widget, Originally by bam

--]]
local assert, error, ipairs, next, pairs, select, tonumber, tostring, type, unpack, pcall, xpcall =
                assert, error, ipairs, next, pairs, select, tonumber, tostring, type, unpack, pcall, xpcall
local getmetatable, setmetatable, rawequal, rawget, rawset, getfenv, setfenv, loadstring, debugstack =
                getmetatable, setmetatable, rawequal, rawget, rawset, getfenv, setfenv, loadstring, debugstack
local math, string, table = math, string, table
local find, format, gmatch, gsub, tolower, match, toupper, join, split, trim =
                string.find, string.format, string.gmatch, string.gsub, string.lower, string.match, string.upper, string.join, string.split, string.trim
local concat, insert, maxn, remove, sort = table.concat, table.insert, table.maxn, table.remove, table.sort
local max, min, abs, ceil, floor = math.max, math.min, math.abs, math.ceil, math.floor

local LibStub = assert(LibStub)

local ChatFontNormal = ChatFontNormal
local ClearCursor = ClearCursor
local CreateFrame = CreateFrame
local GetCursorInfo = GetCursorInfo
local GetSpellName = GetSpellName
local UIParent = UIParent
local UISpecialFrames = UISpecialFrames

-- No global variables after this!

local _G = getfenv()

local AceGUI = LibStub("AceGUI-3.0")

local Version = 10
---------------------
-- Common Elements --
---------------------

local FrameBackdrop = {
        bgFile="Interface\\DialogFrame\\UI-DialogBox-Background",
        edgeFile="Interface\\DialogFrame\\UI-DialogBox-Border",
        tile = true, tileSize = 32, edgeSize = 32,
        insets = { left = 8, right = 8, top = 8, bottom = 8 }
}

local PaneBackdrop      = {

        bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 16, edgeSize = 16,
        insets = { left = 3, right = 3, top = 5, bottom = 3 }
}

local ControlBackdrop    = {
        bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 16, edgeSize = 16,
        insets = { left = 3, right = 3, top = 3, bottom = 3 }
}

--------------------------
-- Edit box              --
--------------------------
--[[
        Events :
        OnTextChanged
        OnEnterPressed

]]
do
        local Type = "MultiLineEditBox"

        local MultiLineEditBox = {}

        local function EditBox_OnEnterPressed(this)
                local self = this.obj
                local value = this:GetText()
                local cancel = self:Fire("OnEnterPressed",value)
                if not cancel then
                        self.button:Disable()
                end
        end
        
        local function Button_OnClick(this)
                local editbox = this.obj.editbox
                editbox:ClearFocus()
                EditBox_OnEnterPressed(editbox)
        end
        
        local function EditBox_OnReceiveDrag(this)
                local self = this.obj
                local type, id, info = GetCursorInfo()
                if type == "item" then
                        self:SetText(info)
                        self:Fire("OnEnterPressed",info)
                        ClearCursor()
                elseif type == "spell" then
                        local name, rank = GetSpellName(id, info)
                        if rank and rank:match("%d") then
                                name = name.."("..rank..")"
                        end
                        self:SetText(name)
                        self:Fire("OnEnterPressed",name)
                        ClearCursor()
                end
                --self.button:Disable()
                AceGUI:ClearFocus()
        end
        
        function MultiLineEditBox:OnAcquire()
                self:SetWidth(200)
                self:SetHeight(116)
                self:SetNumLines(4)
                self:SetDisabled(false)
                self:ShowButton(true)
        end
        
        function MultiLineEditBox:OnRelease()
                self.frame:ClearAllPoints()
                self.frame:Hide()
                self:SetDisabled(false)
        end
        
        function MultiLineEditBox:SetDisabled(disabled)
                self.disabled = disabled
                if disabled then
                        self.editbox:EnableMouse(false)
                        self.scrollframe:EnableMouse(false)
                        self.editbox:ClearFocus()
                        self.editbox:SetTextColor(0.5, 0.5, 0.5)
                        self.label:SetTextColor(0.5,0.5,0.5)
                else
                        self.editbox:EnableMouse(true)
                        self.scrollframe:EnableMouse(true)
                        self.editbox:SetTextColor(1, 1, 1)
                        self.label:SetTextColor(1,.82,0)
                end
        end

        function MultiLineEditBox:SetText(text)
                text = text or ""
                local editbox = self.editbox
                local oldText = editbox:GetText()
                local dummy = format(" %s", text)
                self.lasttext = dummy -- prevents OnTextChanged from firing
                editbox:SetText(dummy)
                editbox:HighlightText(0, 1)
                self.lasttext = oldText
                editbox:Insert("")
        end
        
        function MultiLineEditBox:SetLabel(text)
                if (text or "") == "" then
                        self.backdrop:SetPoint("TOPLEFT",self.frame,"TOPLEFT",0,0)
                        self.label:Hide()
                        self.label:SetText("")
                else
                        self.backdrop:SetPoint("TOPLEFT",self.frame,"TOPLEFT",0,-20)
                        self.label:Show()
                        self.label:SetText(text)
                end
        end
        
        function MultiLineEditBox:SetNumLines(number)
                number = number or 4
                self:SetHeight(60 + (14*number))
        end

        function MultiLineEditBox:GetText()
                return self.editbox:GetText()
        end
        
        function MultiLineEditBox:ShowButton(show)
                if show then
                        self.backdrop:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT",0,22)
                        self.button:Show()
                else
                        self.backdrop:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT",0,0)
                        self.button:Hide()
                end
        end

        local function Constructor()
                local frame = CreateFrame("Frame", nil, UIParent)
                local backdrop = CreateFrame("Frame", nil, frame)
                local self = {}
                for k, v in pairs(MultiLineEditBox) do self[k] = v end
                self.type = Type
                self.frame = frame
                self.backdrop = backdrop
                frame.obj = self

                backdrop:SetBackdrop(ControlBackdrop)
                backdrop:SetBackdropColor(0, 0, 0)
                backdrop:SetBackdropBorderColor(0.4, 0.4, 0.4)
        
                backdrop:SetPoint("TOPLEFT",frame,"TOPLEFT",0, -20)
                backdrop:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,22)
                
                local scrollframe = CreateFrame("ScrollFrame", format("%s@%s@%s", Type, "ScrollFrame", tostring(self)), backdrop, "UIPanelScrollFrameTemplate")
                scrollframe:SetPoint("TOPLEFT", 5, -6)
                scrollframe:SetPoint("BOTTOMRIGHT", -28, 6)
                scrollframe.obj = self
                self.scrollframe = scrollframe
                
                --local scrollchild = CreateFrame("Frame", nil, scrollframe)
                --scrollframe:SetScrollChild(scrollchild)
                --scrollchild:SetHeight(2)
                --scrollchild:SetWidth(2)
        
                local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall")
                label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,-2)
                label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,-2)
                label:SetJustifyH("LEFT")
                label:SetHeight(18)
                self.label = label
                        
                local editbox = CreateFrame("EditBox", nil, scrollframe)
                self.editbox = editbox
                editbox.obj = self
                editbox:SetPoint("TOPLEFT")
                editbox:SetPoint("BOTTOMLEFT")
                editbox:SetHeight(50)
                editbox:SetWidth(50)
                editbox:SetMultiLine(true)
                -- editbox:SetMaxLetters(7500)
                editbox:SetTextInsets(5, 5, 3, 3)
                editbox:EnableMouse(true)
                editbox:SetAutoFocus(false)
                editbox:SetFontObject(ChatFontNormal)
                scrollframe:SetScrollChild(editbox)

                local button = CreateFrame("Button",nil,scrollframe,"UIPanelButtonTemplate")
                button:SetWidth(80)
                button:SetHeight(20)
                button:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,2)
                button:SetText(ACCEPT)
                button:SetScript("OnClick", Button_OnClick)
                button:SetFrameLevel(editbox:GetFrameLevel() + 1)
                button:Disable()
                button:Hide()
                self.button = button
                button.obj = self
                
                scrollframe:EnableMouse(true)
                scrollframe:SetScript("OnMouseUp", function() editbox:SetFocus() end)
                scrollframe:SetScript("OnEnter", function(this) this.obj:Fire("OnEnter") end)
                scrollframe:SetScript("OnLeave", function(this) this.obj:Fire("OnLeave") end)
                
                editbox:SetScript("OnEnter", function(this) this.obj:Fire("OnEnter") end)
                editbox:SetScript("OnLeave", function(this) this.obj:Fire("OnLeave") end)
                
                local function FixSize()
                        --scrollchild:SetHeight(scrollframe:GetHeight())
                        --scrollchild:SetWidth(scrollframe:GetWidth())
                        editbox:SetWidth(scrollframe:GetWidth())
                end
                scrollframe:SetScript("OnShow", FixSize)
                scrollframe:SetScript("OnSizeChanged", FixSize)
        
                editbox:SetScript("OnEscapePressed", editbox.ClearFocus)
                editbox:SetScript("OnTextChanged", function(_, ...)
                        scrollframe:UpdateScrollChildRect()
                        local value = editbox:GetText()
                        if value ~= self.lasttext then
                                self:Fire("OnTextChanged", value)
                                self.lasttext = value
                                self.button:Enable()
                        end
                end)
        
                editbox:SetScript("OnReceiveDrag", EditBox_OnReceiveDrag)
                editbox:SetScript("OnMouseDown", EditBox_OnReceiveDrag)
                
                do
                        local cursorOffset, cursorHeight
                        local idleTime
                        local function FixScroll(_, elapsed)
                                if cursorOffset and cursorHeight then
                                        idleTime = 0
                                        local height = scrollframe:GetHeight()
                                        local range = scrollframe:GetVerticalScrollRange()
                                        local scroll = scrollframe:GetVerticalScroll()
                                        local size = height + range
                                        cursorOffset = -cursorOffset
                                        while cursorOffset < scroll do
                                                scroll = scroll - (height / 2)
                                                if scroll < 0 then scroll = 0 end
                                                scrollframe:SetVerticalScroll(scroll)
                                        end
                                        while cursorOffset + cursorHeight > scroll + height and scroll < range do
                                                scroll = scroll + (height / 2)
                                                if scroll > range then scroll = range end
                                                scrollframe:SetVerticalScroll(scroll)
                                        end
                                elseif not idleTime or idleTime > 2 then
                                        frame:SetScript("OnUpdate", nil)
                                        idleTime = nil
                                else
                                        idleTime = idleTime + elapsed
                                end
                                cursorOffset = nil
                        end
                        editbox:SetScript("OnCursorChanged", function(_, x, y, w, h)
                                cursorOffset, cursorHeight = y, h
                                if not idleTime then
                                        frame:SetScript("OnUpdate", FixScroll)
                                end
                        end)
                end
        
                AceGUI:RegisterAsWidget(self)
                return self
        end

        AceGUI:RegisterWidgetType(Type, Constructor, Version)
end



Compare with Previous | Blame