AceGUIWidget-MultiLineEditBox.lua 9.29 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

--[[
--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")

32
local Version = 11
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
---------------------
-- 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
104
		--self.button:Disable()
105
106
107
108
		AceGUI:ClearFocus()
	end
	
	function MultiLineEditBox:OnAcquire()
nevcairiel's avatar
nevcairiel committed
109
110
111
		self:SetWidth(200)
		self:SetHeight(116)
		self:SetNumLines(4)
112
113
114
115
116
117
118
119
120
121
122
123
124
125
		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)
126
			self.scrollframe:EnableMouse(false)
127
128
			self.editbox:ClearFocus()
			self.editbox:SetTextColor(0.5, 0.5, 0.5)
129
			self.label:SetTextColor(0.5,0.5,0.5)
130
			self.button:Disable()
131
132
		else
			self.editbox:EnableMouse(true)
133
			self.scrollframe:EnableMouse(true)
134
			self.editbox:SetTextColor(1, 1, 1)
135
			self.label:SetTextColor(1,.82,0)
136
			self.button:Enable()
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
		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
nevcairiel's avatar
nevcairiel committed
163
164
165
166
167
	
	function MultiLineEditBox:SetNumLines(number)
		number = number or 4
		self:SetHeight(60 + (14*number))
	end
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203

	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
204
		self.scrollframe = scrollframe
205
		
206
207
208
209
		--local scrollchild = CreateFrame("Frame", nil, scrollframe)
		--scrollframe:SetScrollChild(scrollchild)
		--scrollchild:SetHeight(2)
		--scrollchild:SetWidth(2)
210
	
211
212
213
		local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall")
		label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,-2)
		label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,-2)
214
215
216
217
		label:SetJustifyH("LEFT")
		label:SetHeight(18)
		self.label = label
			
218
		local editbox = CreateFrame("EditBox", nil, scrollframe)
219
220
221
		self.editbox = editbox
		editbox.obj = self
		editbox:SetPoint("TOPLEFT")
222
		editbox:SetPoint("BOTTOMLEFT")
223
224
225
226
227
228
229
230
		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)
231
		scrollframe:SetScrollChild(editbox)
232
233
234
235
236
237
238

		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)
nevcairiel's avatar
nevcairiel committed
239
		button:SetFrameLevel(editbox:GetFrameLevel() + 1)
240
241
242
243
244
245
246
247
248
249
250
251
252
253
		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()
254
255
			--scrollchild:SetHeight(scrollframe:GetHeight())
			--scrollchild:SetWidth(scrollframe:GetWidth())
256
257
258
259
260
261
262
263
264
265
			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
266
267
				self:Fire("OnTextChanged", value)
				self.lasttext = value
268
269
270
				if not self.disabled then
					self.button:Enable()
				end
271
272
273
274
275
276
277
278
279
280
			end
		end)
	
		editbox:SetScript("OnReceiveDrag", EditBox_OnReceiveDrag)
		editbox:SetScript("OnMouseDown", EditBox_OnReceiveDrag)
		
		do
			local cursorOffset, cursorHeight
			local idleTime
			local function FixScroll(_, elapsed)
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
				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
303
				end
304
				cursorOffset = nil
305
306
			end
			editbox:SetScript("OnCursorChanged", function(_, x, y, w, h)
307
308
309
310
				cursorOffset, cursorHeight = y, h
				if not idleTime then
					frame:SetScript("OnUpdate", FixScroll)
				end
311
312
313
314
315
316
317
318
319
320
321
322
			end)
		end
	
		AceGUI:RegisterAsWidget(self)
		return self
	end

	AceGUI:RegisterWidgetType(Type, Constructor, Version)
end