Asa@0: Asa@0: --[[ Asa@0: --Multiline Editbox Widget, Originally by bam Asa@0: Asa@0: --]] Asa@0: local AceGUI = LibStub("AceGUI-3.0") Asa@0: Asa@0: -- Lua APIs Asa@0: local format, pairs, tostring = string.format, pairs, tostring Asa@0: Asa@0: -- WoW APIs Asa@0: local GetCursorInfo, ClearCursor, GetSpellName = GetCursorInfo, ClearCursor, GetSpellName Asa@0: local CreateFrame, UIParent = CreateFrame, UIParent Asa@0: Asa@0: -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded Asa@0: -- List them here for Mikk's FindGlobals script Asa@0: -- GLOBALS: ChatFontNormal, ACCEPT Asa@0: Asa@0: local Version = 11 Asa@0: --------------------- Asa@0: -- Common Elements -- Asa@0: --------------------- Asa@0: Asa@0: local FrameBackdrop = { Asa@0: bgFile="Interface\\DialogFrame\\UI-DialogBox-Background", Asa@0: edgeFile="Interface\\DialogFrame\\UI-DialogBox-Border", Asa@0: tile = true, tileSize = 32, edgeSize = 32, Asa@0: insets = { left = 8, right = 8, top = 8, bottom = 8 } Asa@0: } Asa@0: Asa@0: local PaneBackdrop = { Asa@0: Asa@0: bgFile = "Interface\\ChatFrame\\ChatFrameBackground", Asa@0: edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", Asa@0: tile = true, tileSize = 16, edgeSize = 16, Asa@0: insets = { left = 3, right = 3, top = 5, bottom = 3 } Asa@0: } Asa@0: Asa@0: local ControlBackdrop = { Asa@0: bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", Asa@0: edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", Asa@0: tile = true, tileSize = 16, edgeSize = 16, Asa@0: insets = { left = 3, right = 3, top = 3, bottom = 3 } Asa@0: } Asa@0: Asa@0: -------------------------- Asa@0: -- Edit box -- Asa@0: -------------------------- Asa@0: --[[ Asa@0: Events : Asa@0: OnTextChanged Asa@0: OnEnterPressed Asa@0: Asa@0: ]] Asa@0: do Asa@0: local Type = "MultiLineEditBox" Asa@0: Asa@0: local MultiLineEditBox = {} Asa@0: Asa@0: local function EditBox_OnEnterPressed(this) Asa@0: local self = this.obj Asa@0: local value = this:GetText() Asa@0: local cancel = self:Fire("OnEnterPressed",value) Asa@0: if not cancel then Asa@0: self.button:Disable() Asa@0: end Asa@0: end Asa@0: Asa@0: local function Button_OnClick(this) Asa@0: local editbox = this.obj.editbox Asa@0: editbox:ClearFocus() Asa@0: EditBox_OnEnterPressed(editbox) Asa@0: end Asa@0: Asa@0: local function EditBox_OnReceiveDrag(this) Asa@0: local self = this.obj Asa@0: local type, id, info = GetCursorInfo() Asa@0: if type == "item" then Asa@0: self:SetText(info) Asa@0: self:Fire("OnEnterPressed",info) Asa@0: ClearCursor() Asa@0: elseif type == "spell" then Asa@0: local name, rank = GetSpellName(id, info) Asa@0: if rank and rank:match("%d") then Asa@0: name = name.."("..rank..")" Asa@0: end Asa@0: self:SetText(name) Asa@0: self:Fire("OnEnterPressed",name) Asa@0: ClearCursor() Asa@0: end Asa@0: --self.button:Disable() Asa@0: AceGUI:ClearFocus() Asa@0: end Asa@0: Asa@0: function MultiLineEditBox:OnAcquire() Asa@0: self:SetWidth(200) Asa@0: self:SetHeight(116) Asa@0: self:SetNumLines(4) Asa@0: self:SetDisabled(false) Asa@0: self:ShowButton(true) Asa@0: end Asa@0: Asa@0: function MultiLineEditBox:OnRelease() Asa@0: self.frame:ClearAllPoints() Asa@0: self.frame:Hide() Asa@0: self:SetDisabled(false) Asa@0: end Asa@0: Asa@0: function MultiLineEditBox:SetDisabled(disabled) Asa@0: self.disabled = disabled Asa@0: if disabled then Asa@0: self.editbox:EnableMouse(false) Asa@0: self.scrollframe:EnableMouse(false) Asa@0: self.editbox:ClearFocus() Asa@0: self.editbox:SetTextColor(0.5, 0.5, 0.5) Asa@0: self.label:SetTextColor(0.5,0.5,0.5) Asa@0: self.button:Disable() Asa@0: else Asa@0: self.editbox:EnableMouse(true) Asa@0: self.scrollframe:EnableMouse(true) Asa@0: self.editbox:SetTextColor(1, 1, 1) Asa@0: self.label:SetTextColor(1,.82,0) Asa@0: self.button:Enable() Asa@0: end Asa@0: end Asa@0: Asa@0: function MultiLineEditBox:SetText(text) Asa@0: text = text or "" Asa@0: local editbox = self.editbox Asa@0: local oldText = editbox:GetText() Asa@0: local dummy = format(" %s", text) Asa@0: self.lasttext = dummy -- prevents OnTextChanged from firing Asa@0: editbox:SetText(dummy) Asa@0: editbox:HighlightText(0, 1) Asa@0: self.lasttext = oldText Asa@0: editbox:Insert("") Asa@0: end Asa@0: Asa@0: function MultiLineEditBox:SetLabel(text) Asa@0: if (text or "") == "" then Asa@0: self.backdrop:SetPoint("TOPLEFT",self.frame,"TOPLEFT",0,0) Asa@0: self.label:Hide() Asa@0: self.label:SetText("") Asa@0: else Asa@0: self.backdrop:SetPoint("TOPLEFT",self.frame,"TOPLEFT",0,-20) Asa@0: self.label:Show() Asa@0: self.label:SetText(text) Asa@0: end Asa@0: end Asa@0: Asa@0: function MultiLineEditBox:SetNumLines(number) Asa@0: number = number or 4 Asa@0: self:SetHeight(60 + (14*number)) Asa@0: end Asa@0: Asa@0: function MultiLineEditBox:GetText() Asa@0: return self.editbox:GetText() Asa@0: end Asa@0: Asa@0: function MultiLineEditBox:ShowButton(show) Asa@0: if show then Asa@0: self.backdrop:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT",0,22) Asa@0: self.button:Show() Asa@0: else Asa@0: self.backdrop:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT",0,0) Asa@0: self.button:Hide() Asa@0: end Asa@0: end Asa@0: Asa@0: local function Constructor() Asa@0: local frame = CreateFrame("Frame", nil, UIParent) Asa@0: local backdrop = CreateFrame("Frame", nil, frame) Asa@0: local self = {} Asa@0: for k, v in pairs(MultiLineEditBox) do self[k] = v end Asa@0: self.type = Type Asa@0: self.frame = frame Asa@0: self.backdrop = backdrop Asa@0: frame.obj = self Asa@0: Asa@0: backdrop:SetBackdrop(ControlBackdrop) Asa@0: backdrop:SetBackdropColor(0, 0, 0) Asa@0: backdrop:SetBackdropBorderColor(0.4, 0.4, 0.4) Asa@0: Asa@0: backdrop:SetPoint("TOPLEFT",frame,"TOPLEFT",0, -20) Asa@0: backdrop:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,22) Asa@0: Asa@0: local scrollframe = CreateFrame("ScrollFrame", format("%s@%s@%s", Type, "ScrollFrame", tostring(self)), backdrop, "UIPanelScrollFrameTemplate") Asa@0: scrollframe:SetPoint("TOPLEFT", 5, -6) Asa@0: scrollframe:SetPoint("BOTTOMRIGHT", -28, 6) Asa@0: scrollframe.obj = self Asa@0: self.scrollframe = scrollframe Asa@0: Asa@0: --local scrollchild = CreateFrame("Frame", nil, scrollframe) Asa@0: --scrollframe:SetScrollChild(scrollchild) Asa@0: --scrollchild:SetHeight(2) Asa@0: --scrollchild:SetWidth(2) Asa@0: Asa@0: local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall") Asa@0: label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,-2) Asa@0: label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,-2) Asa@0: label:SetJustifyH("LEFT") Asa@0: label:SetHeight(18) Asa@0: self.label = label Asa@0: Asa@0: local editbox = CreateFrame("EditBox", nil, scrollframe) Asa@0: self.editbox = editbox Asa@0: editbox.obj = self Asa@0: editbox:SetPoint("TOPLEFT") Asa@0: editbox:SetPoint("BOTTOMLEFT") Asa@0: editbox:SetHeight(50) Asa@0: editbox:SetWidth(50) Asa@0: editbox:SetMultiLine(true) Asa@0: -- editbox:SetMaxLetters(7500) Asa@0: editbox:SetTextInsets(5, 5, 3, 3) Asa@0: editbox:EnableMouse(true) Asa@0: editbox:SetAutoFocus(false) Asa@0: editbox:SetFontObject(ChatFontNormal) Asa@0: scrollframe:SetScrollChild(editbox) Asa@0: Asa@0: local button = CreateFrame("Button",nil,scrollframe,"UIPanelButtonTemplate") Asa@0: button:SetWidth(80) Asa@0: button:SetHeight(20) Asa@0: button:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,2) Asa@0: button:SetText(ACCEPT) Asa@0: button:SetScript("OnClick", Button_OnClick) Asa@0: button:SetFrameLevel(editbox:GetFrameLevel() + 1) Asa@0: button:Disable() Asa@0: button:Hide() Asa@0: self.button = button Asa@0: button.obj = self Asa@0: Asa@0: scrollframe:EnableMouse(true) Asa@0: scrollframe:SetScript("OnMouseUp", function() editbox:SetFocus() end) Asa@0: scrollframe:SetScript("OnEnter", function(this) this.obj:Fire("OnEnter") end) Asa@0: scrollframe:SetScript("OnLeave", function(this) this.obj:Fire("OnLeave") end) Asa@0: Asa@0: editbox:SetScript("OnEnter", function(this) this.obj:Fire("OnEnter") end) Asa@0: editbox:SetScript("OnLeave", function(this) this.obj:Fire("OnLeave") end) Asa@0: Asa@0: local function FixSize() Asa@0: --scrollchild:SetHeight(scrollframe:GetHeight()) Asa@0: --scrollchild:SetWidth(scrollframe:GetWidth()) Asa@0: editbox:SetWidth(scrollframe:GetWidth()) Asa@0: end Asa@0: scrollframe:SetScript("OnShow", FixSize) Asa@0: scrollframe:SetScript("OnSizeChanged", FixSize) Asa@0: Asa@0: editbox:SetScript("OnEscapePressed", editbox.ClearFocus) Asa@0: editbox:SetScript("OnTextChanged", function(_, ...) Asa@0: scrollframe:UpdateScrollChildRect() Asa@0: local value = editbox:GetText() Asa@0: if value ~= self.lasttext then Asa@0: self:Fire("OnTextChanged", value) Asa@0: self.lasttext = value Asa@0: if not self.disabled then Asa@0: self.button:Enable() Asa@0: end Asa@0: end Asa@0: end) Asa@0: Asa@0: editbox:SetScript("OnReceiveDrag", EditBox_OnReceiveDrag) Asa@0: editbox:SetScript("OnMouseDown", EditBox_OnReceiveDrag) Asa@0: Asa@0: do Asa@0: local cursorOffset, cursorHeight Asa@0: local idleTime Asa@0: local function FixScroll(_, elapsed) Asa@0: if cursorOffset and cursorHeight then Asa@0: idleTime = 0 Asa@0: local height = scrollframe:GetHeight() Asa@0: local range = scrollframe:GetVerticalScrollRange() Asa@0: local scroll = scrollframe:GetVerticalScroll() Asa@0: local size = height + range Asa@0: cursorOffset = -cursorOffset Asa@0: while cursorOffset < scroll do Asa@0: scroll = scroll - (height / 2) Asa@0: if scroll < 0 then scroll = 0 end Asa@0: scrollframe:SetVerticalScroll(scroll) Asa@0: end Asa@0: while cursorOffset + cursorHeight > scroll + height and scroll < range do Asa@0: scroll = scroll + (height / 2) Asa@0: if scroll > range then scroll = range end Asa@0: scrollframe:SetVerticalScroll(scroll) Asa@0: end Asa@0: elseif not idleTime or idleTime > 2 then Asa@0: frame:SetScript("OnUpdate", nil) Asa@0: idleTime = nil Asa@0: else Asa@0: idleTime = idleTime + elapsed Asa@0: end Asa@0: cursorOffset = nil Asa@0: end Asa@0: editbox:SetScript("OnCursorChanged", function(_, x, y, w, h) Asa@0: cursorOffset, cursorHeight = y, h Asa@0: if not idleTime then Asa@0: frame:SetScript("OnUpdate", FixScroll) Asa@0: end Asa@0: end) Asa@0: end Asa@0: Asa@0: AceGUI:RegisterAsWidget(self) Asa@0: return self Asa@0: end Asa@0: Asa@0: AceGUI:RegisterWidgetType(Type, Constructor, Version) Asa@0: end Asa@0: Asa@0: Asa@0: