AceGUIWidget-MultiLineEditBox.lua 9.87 KB
Newer Older
1
local Type, Version = "MultiLineEditBox", 25
2 3
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
4

5 6 7 8
-- Lua APIs
local pairs = pairs

-- WoW APIs
9
local GetCursorInfo, GetSpellInfo, ClearCursor = GetCursorInfo, GetSpellInfo, ClearCursor
10 11 12 13 14 15 16
local CreateFrame, UIParent = CreateFrame, UIParent
local _G = _G

-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: ACCEPT, ChatFontNormal

nevcairiel's avatar
nevcairiel committed
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
--[[-----------------------------------------------------------------------------
Support functions
-------------------------------------------------------------------------------]]
local function Layout(self)
	self:SetHeight(self.numlines * 14 + (self.disablebutton and 19 or 41) + self.labelHeight)

	if self.labelHeight == 0 then
		self.scrollBar:SetPoint("TOP", self.frame, "TOP", 0, -23)
	else
		self.scrollBar:SetPoint("TOP", self.label, "BOTTOM", 0, -19)
	end

	if self.disablebutton then
		self.scrollBar:SetPoint("BOTTOM", self.frame, "BOTTOM", 0, 21)
		self.scrollBG:SetPoint("BOTTOMLEFT", 0, 4)
	else
		self.scrollBar:SetPoint("BOTTOM", self.button, "TOP", 0, 18)
		self.scrollBG:SetPoint("BOTTOMLEFT", self.button, "TOPLEFT")
	end
end

38 39 40 41 42 43 44 45 46 47
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function OnClick(self)                                                     -- Button
	self = self.obj
	self.editBox:ClearFocus()
	if not self:Fire("OnEnterPressed", self.editBox:GetText()) then
		self.button:Disable()
	end
end
48

49 50 51 52 53 54 55 56 57 58 59 60
local function OnCursorChanged(self, _, y, _, cursorHeight)                      -- EditBox
	self, y = self.obj.scrollFrame, -y
	local offset = self:GetVerticalScroll()
	if y < offset then
		self:SetVerticalScroll(y)
	else
		y = y + cursorHeight - self:GetHeight()
		if y > offset then
			self:SetVerticalScroll(y)
		end
	end
end
61

62 63
local function OnEditFocusLost(self)                                             -- EditBox
	self:HighlightText(0, 0)
64
	self.obj:Fire("OnEditFocusLost")
65
end
66

67 68 69 70 71 72 73
local function OnEnter(self)                                                     -- EditBox / ScrollFrame
	self = self.obj
	if not self.entered then
		self.entered = true
		self:Fire("OnEnter")
	end
end
74

75 76 77 78 79 80 81
local function OnLeave(self)                                                     -- EditBox / ScrollFrame
	self = self.obj
	if self.entered then
		self.entered = nil
		self:Fire("OnLeave")
	end
end
82

83 84 85 86 87
local function OnMouseUp(self)                                                   -- ScrollFrame
	self = self.obj.editBox
	self:SetFocus()
	self:SetCursorPosition(self:GetNumLetters())
end
88

89 90 91
local function OnReceiveDrag(self)                                               -- EditBox / ScrollFrame
	local type, id, info = GetCursorInfo()
	if type == "spell" then
92
		info = GetSpellInfo(id, info)
93 94
	elseif type ~= "item" then
		return
95
	end
96 97 98 99 100 101
	ClearCursor()
	self = self.obj
	local editBox = self.editBox
	if not editBox:HasFocus() then
		editBox:SetFocus()
		editBox:SetCursorPosition(editBox:GetNumLetters())
102
	end
103 104 105 106 107 108 109 110 111 112 113 114 115
	editBox:Insert(info)
	self.button:Enable()
end

local function OnSizeChanged(self, width, height)                                -- ScrollFrame
	self.obj.editBox:SetWidth(width)
end

local function OnTextChanged(self, userInput)                                    -- EditBox
	if userInput then
		self = self.obj
		self:Fire("OnTextChanged", self.editBox:GetText())
		self.button:Enable()
116
	end
117 118 119 120 121 122 123 124 125
end

local function OnTextSet(self)                                                   -- EditBox
	self:HighlightText(0, 0)
	self:SetCursorPosition(self:GetNumLetters())
	self:SetCursorPosition(0)
	self.obj.button:Disable()
end

126
local function OnVerticalScroll(self, offset)                                    -- ScrollFrame
127 128 129 130
	local editBox = self.obj.editBox
	editBox:SetHitRectInsets(0, 0, offset, editBox:GetHeight() - offset - self:GetHeight())
end

131 132 133 134 135
local function OnShowFocus(frame)
	frame.obj.editBox:SetFocus()
	frame:SetScript("OnShow", nil)
end

136
local function OnEditFocusGained(frame)
137
	AceGUI:SetFocus(frame.obj)
138
	frame.obj:Fire("OnEditFocusGained")
139 140
end

141 142 143 144 145 146
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
	["OnAcquire"] = function(self)
		self.editBox:SetText("")
147
		self:SetDisabled(false)
148
		self:SetWidth(200)
nevcairiel's avatar
nevcairiel committed
149
		self:DisableButton(false)
150 151
		self:SetNumLines()
		self.entered = nil
152
		self:SetMaxLetters(0)
153 154
	end,

155 156 157
	["OnRelease"] = function(self)
		self:ClearFocus()
	end,
158 159 160

	["SetDisabled"] = function(self, disabled)
		local editBox = self.editBox
161
		if disabled then
162 163 164 165 166
			editBox:ClearFocus()
			editBox:EnableMouse(false)
			editBox:SetTextColor(0.5, 0.5, 0.5)
			self.label:SetTextColor(0.5, 0.5, 0.5)
			self.scrollFrame:EnableMouse(false)
167
			self.button:Disable()
168
		else
169 170 171 172
			editBox:EnableMouse(true)
			editBox:SetTextColor(1, 1, 1)
			self.label:SetTextColor(1, 0.82, 0)
			self.scrollFrame:EnableMouse(true)
173
		end
174
	end,
175

176 177
	["SetLabel"] = function(self, text)
		if text and text ~= "" then
178
			self.label:SetText(text)
179 180 181 182 183 184 185
			if self.labelHeight ~= 10 then
				self.labelHeight = 10
				self.label:Show()
			end
		elseif self.labelHeight ~= 0 then
			self.labelHeight = 0
			self.label:Hide()
186
		end
nevcairiel's avatar
nevcairiel committed
187
		Layout(self)
188
	end,
189

190 191 192
	["SetNumLines"] = function(self, value)
		if not value or value < 4 then
			value = 4
193
		end
nevcairiel's avatar
nevcairiel committed
194 195
		self.numlines = value
		Layout(self)
196 197 198 199
	end,

	["SetText"] = function(self, text)
		self.editBox:SetText(text)
200 201
	end,

nevcairiel's avatar
nevcairiel committed
202 203 204 205
	["GetText"] = function(self)
		return self.editBox:GetText()
	end,

206
	["SetMaxLetters"] = function (self, num)
207
		self.editBox:SetMaxLetters(num or 0)
nevcairiel's avatar
nevcairiel committed
208 209 210 211 212 213 214 215 216 217
	end,

	["DisableButton"] = function(self, disabled)
		self.disablebutton = disabled
		if disabled then
			self.button:Hide()
		else
			self.button:Show()
		end
		Layout(self)
218 219 220 221 222 223 224 225 226 227 228 229
	end,
	
	["ClearFocus"] = function(self)
		self.editBox:ClearFocus()
		self.frame:SetScript("OnShow", nil)
	end,

	["SetFocus"] = function(self)
		self.editBox:SetFocus()
		if not self.frame:IsShown() then
			self.frame:SetScript("OnShow", OnShowFocus)
		end
230 231 232 233 234 235 236 237 238 239 240
	end,
	
	["GetCursorPosition"] = function(self)
		return self.editBox:GetCursorPosition()
	end,
	
	["SetCursorPosition"] = function(self, ...)
		return self.editBox:SetCursorPosition(...)
	end,
	
	
241
}
242

243 244 245 246 247 248 249 250 251 252 253 254
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local backdrop = {
	bgFile = [[Interface\Tooltips\UI-Tooltip-Background]],
	edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], edgeSize = 16,
	insets = { left = 4, right = 3, top = 4, bottom = 3 }
}

local function Constructor()
	local frame = CreateFrame("Frame", nil, UIParent)
	frame:Hide()
255
	
256 257 258 259 260 261 262 263 264 265
	local widgetNum = AceGUI:GetNextWidgetNum(Type)

	local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
	label:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, -4)
	label:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, -4)
	label:SetJustifyH("LEFT")
	label:SetText(ACCEPT)
	label:SetHeight(10)

	local button = CreateFrame("Button", ("%s%dButton"):format(Type, widgetNum), frame, "UIPanelButtonTemplate2")
nevcairiel's avatar
nevcairiel committed
266
	button:SetPoint("BOTTOMLEFT", 0, 4)
267 268 269 270 271
	button:SetHeight(22)
	button:SetWidth(label:GetStringWidth() + 24)
	button:SetText(ACCEPT)
	button:SetScript("OnClick", OnClick)
	button:Disable()
272
	
273 274 275 276 277
	local text = button:GetFontString()
	text:ClearAllPoints()
	text:SetPoint("TOPLEFT", button, "TOPLEFT", 5, -5)
	text:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -5, 1)
	text:SetJustifyV("MIDDLE")
278

279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
	local scrollBG = CreateFrame("Frame", nil, frame)
	scrollBG:SetBackdrop(backdrop)
	scrollBG:SetBackdropColor(0, 0, 0)
	scrollBG:SetBackdropBorderColor(0.4, 0.4, 0.4)

	local scrollFrame = CreateFrame("ScrollFrame", ("%s%dScrollFrame"):format(Type, widgetNum), frame, "UIPanelScrollFrameTemplate")

	local scrollBar = _G[scrollFrame:GetName() .. "ScrollBar"]
	scrollBar:ClearAllPoints()
	scrollBar:SetPoint("TOP", label, "BOTTOM", 0, -19)
	scrollBar:SetPoint("BOTTOM", button, "TOP", 0, 18)
	scrollBar:SetPoint("RIGHT", frame, "RIGHT")

	scrollBG:SetPoint("TOPRIGHT", scrollBar, "TOPLEFT", 0, 19)
	scrollBG:SetPoint("BOTTOMLEFT", button, "TOPLEFT")
294

295 296 297 298 299 300 301 302
	scrollFrame:SetPoint("TOPLEFT", scrollBG, "TOPLEFT", 5, -6)
	scrollFrame:SetPoint("BOTTOMRIGHT", scrollBG, "BOTTOMRIGHT", -4, 4)
	scrollFrame:SetScript("OnEnter", OnEnter)
	scrollFrame:SetScript("OnLeave", OnLeave)
	scrollFrame:SetScript("OnMouseUp", OnMouseUp)
	scrollFrame:SetScript("OnReceiveDrag", OnReceiveDrag)
	scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
	scrollFrame:HookScript("OnVerticalScroll", OnVerticalScroll)
303

304
	local editBox = CreateFrame("EditBox", nil, scrollFrame)
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
	editBox:SetAllPoints()
	editBox:SetFontObject(ChatFontNormal)
	editBox:SetMultiLine(true)
	editBox:EnableMouse(true)
	editBox:SetAutoFocus(false)
	editBox:SetCountInvisibleLetters(false)
	editBox:SetScript("OnCursorChanged", OnCursorChanged)
	editBox:SetScript("OnEditFocusLost", OnEditFocusLost)
	editBox:SetScript("OnEnter", OnEnter)
	editBox:SetScript("OnEscapePressed", editBox.ClearFocus)
	editBox:SetScript("OnLeave", OnLeave)
	editBox:SetScript("OnMouseDown", OnReceiveDrag)
	editBox:SetScript("OnReceiveDrag", OnReceiveDrag)
	editBox:SetScript("OnTextChanged", OnTextChanged)
	editBox:SetScript("OnTextSet", OnTextSet)
320
	editBox:SetScript("OnEditFocusGained", OnEditFocusGained)
321
	
322 323 324 325 326 327 328 329 330

	scrollFrame:SetScrollChild(editBox)

	local widget = {
		button      = button,
		editBox     = editBox,
		frame       = frame,
		label       = label,
		labelHeight = 10,
nevcairiel's avatar
nevcairiel committed
331
		numlines    = 4,
332
		scrollBar   = scrollBar,
nevcairiel's avatar
nevcairiel committed
333
		scrollBG    = scrollBG,
334 335 336 337 338 339 340 341
		scrollFrame = scrollFrame,
		type        = Type
	}
	for method, func in pairs(methods) do
		widget[method] = func
	end
	button.obj, editBox.obj, scrollFrame.obj = widget, widget, widget

nevcairiel's avatar
nevcairiel committed
342
	return AceGUI:RegisterAsWidget(widget)
343
end
344

345
AceGUI:RegisterWidgetType(Type, Constructor, Version)