9af4b87c1b9686ded2f5eef7216c54f73d3c14c3
[wowui.git] / OmaRFConfig / libs / AceGUI-3.0 / widgets / AceGUIWidget-MultiLineEditBox.lua
1 local Type, Version = "MultiLineEditBox", 28
2 local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
3 if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
4
5 -- Lua APIs
6 local pairs = pairs
7
8 -- WoW APIs
9 local GetCursorInfo, GetSpellInfo, ClearCursor = GetCursorInfo, GetSpellInfo, ClearCursor
10 local CreateFrame, UIParent = CreateFrame, UIParent
11 local _G = _G
12
13 -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
14 -- List them here for Mikk's FindGlobals script
15 -- GLOBALS: ACCEPT, ChatFontNormal
16
17 --[[-----------------------------------------------------------------------------
18 Support functions
19 -------------------------------------------------------------------------------]]
20
21 if not AceGUIMultiLineEditBoxInsertLink then
22         -- upgradeable hook
23         hooksecurefunc("ChatEdit_InsertLink", function(...) return _G.AceGUIMultiLineEditBoxInsertLink(...) end)
24 end
25
26 function _G.AceGUIMultiLineEditBoxInsertLink(text)
27         for i = 1, AceGUI:GetWidgetCount(Type) do
28                 local editbox = _G[("MultiLineEditBox%uEdit"):format(i)]
29                 if editbox and editbox:IsVisible() and editbox:HasFocus() then
30                         editbox:Insert(text)
31                         return true
32                 end
33         end
34 end
35
36
37 local function Layout(self)
38         self:SetHeight(self.numlines * 14 + (self.disablebutton and 19 or 41) + self.labelHeight)
39
40         if self.labelHeight == 0 then
41                 self.scrollBar:SetPoint("TOP", self.frame, "TOP", 0, -23)
42         else
43                 self.scrollBar:SetPoint("TOP", self.label, "BOTTOM", 0, -19)
44         end
45
46         if self.disablebutton then
47                 self.scrollBar:SetPoint("BOTTOM", self.frame, "BOTTOM", 0, 21)
48                 self.scrollBG:SetPoint("BOTTOMLEFT", 0, 4)
49         else
50                 self.scrollBar:SetPoint("BOTTOM", self.button, "TOP", 0, 18)
51                 self.scrollBG:SetPoint("BOTTOMLEFT", self.button, "TOPLEFT")
52         end
53 end
54
55 --[[-----------------------------------------------------------------------------
56 Scripts
57 -------------------------------------------------------------------------------]]
58 local function OnClick(self)                                                     -- Button
59         self = self.obj
60         self.editBox:ClearFocus()
61         if not self:Fire("OnEnterPressed", self.editBox:GetText()) then
62                 self.button:Disable()
63         end
64 end
65
66 local function OnCursorChanged(self, _, y, _, cursorHeight)                      -- EditBox
67         self, y = self.obj.scrollFrame, -y
68         local offset = self:GetVerticalScroll()
69         if y < offset then
70                 self:SetVerticalScroll(y)
71         else
72                 y = y + cursorHeight - self:GetHeight()
73                 if y > offset then
74                         self:SetVerticalScroll(y)
75                 end
76         end
77 end
78
79 local function OnEditFocusLost(self)                                             -- EditBox
80         self:HighlightText(0, 0)
81         self.obj:Fire("OnEditFocusLost")
82 end
83
84 local function OnEnter(self)                                                     -- EditBox / ScrollFrame
85         self = self.obj
86         if not self.entered then
87                 self.entered = true
88                 self:Fire("OnEnter")
89         end
90 end
91
92 local function OnLeave(self)                                                     -- EditBox / ScrollFrame
93         self = self.obj
94         if self.entered then
95                 self.entered = nil
96                 self:Fire("OnLeave")
97         end
98 end
99
100 local function OnMouseUp(self)                                                   -- ScrollFrame
101         self = self.obj.editBox
102         self:SetFocus()
103         self:SetCursorPosition(self:GetNumLetters())
104 end
105
106 local function OnReceiveDrag(self)                                               -- EditBox / ScrollFrame
107         local type, id, info = GetCursorInfo()
108         if type == "spell" then
109                 info = GetSpellInfo(id, info)
110         elseif type ~= "item" then
111                 return
112         end
113         ClearCursor()
114         self = self.obj
115         local editBox = self.editBox
116         if not editBox:HasFocus() then
117                 editBox:SetFocus()
118                 editBox:SetCursorPosition(editBox:GetNumLetters())
119         end
120         editBox:Insert(info)
121         self.button:Enable()
122 end
123
124 local function OnSizeChanged(self, width, height)                                -- ScrollFrame
125         self.obj.editBox:SetWidth(width)
126 end
127
128 local function OnTextChanged(self, userInput)                                    -- EditBox
129         if userInput then
130                 self = self.obj
131                 self:Fire("OnTextChanged", self.editBox:GetText())
132                 self.button:Enable()
133         end
134 end
135
136 local function OnTextSet(self)                                                   -- EditBox
137         self:HighlightText(0, 0)
138         self:SetCursorPosition(self:GetNumLetters())
139         self:SetCursorPosition(0)
140         self.obj.button:Disable()
141 end
142
143 local function OnVerticalScroll(self, offset)                                    -- ScrollFrame
144         local editBox = self.obj.editBox
145         editBox:SetHitRectInsets(0, 0, offset, editBox:GetHeight() - offset - self:GetHeight())
146 end
147
148 local function OnShowFocus(frame)
149         frame.obj.editBox:SetFocus()
150         frame:SetScript("OnShow", nil)
151 end
152
153 local function OnEditFocusGained(frame)
154         AceGUI:SetFocus(frame.obj)
155         frame.obj:Fire("OnEditFocusGained")
156 end
157
158 --[[-----------------------------------------------------------------------------
159 Methods
160 -------------------------------------------------------------------------------]]
161 local methods = {
162         ["OnAcquire"] = function(self)
163                 self.editBox:SetText("")
164                 self:SetDisabled(false)
165                 self:SetWidth(200)
166                 self:DisableButton(false)
167                 self:SetNumLines()
168                 self.entered = nil
169                 self:SetMaxLetters(0)
170         end,
171
172         ["OnRelease"] = function(self)
173                 self:ClearFocus()
174         end,
175
176         ["SetDisabled"] = function(self, disabled)
177                 local editBox = self.editBox
178                 if disabled then
179                         editBox:ClearFocus()
180                         editBox:EnableMouse(false)
181                         editBox:SetTextColor(0.5, 0.5, 0.5)
182                         self.label:SetTextColor(0.5, 0.5, 0.5)
183                         self.scrollFrame:EnableMouse(false)
184                         self.button:Disable()
185                 else
186                         editBox:EnableMouse(true)
187                         editBox:SetTextColor(1, 1, 1)
188                         self.label:SetTextColor(1, 0.82, 0)
189                         self.scrollFrame:EnableMouse(true)
190                 end
191         end,
192
193         ["SetLabel"] = function(self, text)
194                 if text and text ~= "" then
195                         self.label:SetText(text)
196                         if self.labelHeight ~= 10 then
197                                 self.labelHeight = 10
198                                 self.label:Show()
199                         end
200                 elseif self.labelHeight ~= 0 then
201                         self.labelHeight = 0
202                         self.label:Hide()
203                 end
204                 Layout(self)
205         end,
206
207         ["SetNumLines"] = function(self, value)
208                 if not value or value < 4 then
209                         value = 4
210                 end
211                 self.numlines = value
212                 Layout(self)
213         end,
214
215         ["SetText"] = function(self, text)
216                 self.editBox:SetText(text)
217         end,
218
219         ["GetText"] = function(self)
220                 return self.editBox:GetText()
221         end,
222
223         ["SetMaxLetters"] = function (self, num)
224                 self.editBox:SetMaxLetters(num or 0)
225         end,
226
227         ["DisableButton"] = function(self, disabled)
228                 self.disablebutton = disabled
229                 if disabled then
230                         self.button:Hide()
231                 else
232                         self.button:Show()
233                 end
234                 Layout(self)
235         end,
236         
237         ["ClearFocus"] = function(self)
238                 self.editBox:ClearFocus()
239                 self.frame:SetScript("OnShow", nil)
240         end,
241
242         ["SetFocus"] = function(self)
243                 self.editBox:SetFocus()
244                 if not self.frame:IsShown() then
245                         self.frame:SetScript("OnShow", OnShowFocus)
246                 end
247         end,
248
249         ["HighlightText"] = function(self, from, to)
250                 self.editBox:HighlightText(from, to)
251         end,
252
253         ["GetCursorPosition"] = function(self)
254                 return self.editBox:GetCursorPosition()
255         end,
256         
257         ["SetCursorPosition"] = function(self, ...)
258                 return self.editBox:SetCursorPosition(...)
259         end,
260         
261         
262 }
263
264 --[[-----------------------------------------------------------------------------
265 Constructor
266 -------------------------------------------------------------------------------]]
267 local backdrop = {
268         bgFile = [[Interface\Tooltips\UI-Tooltip-Background]],
269         edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], edgeSize = 16,
270         insets = { left = 4, right = 3, top = 4, bottom = 3 }
271 }
272
273 local function Constructor()
274         local frame = CreateFrame("Frame", nil, UIParent)
275         frame:Hide()
276         
277         local widgetNum = AceGUI:GetNextWidgetNum(Type)
278
279         local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
280         label:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, -4)
281         label:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, -4)
282         label:SetJustifyH("LEFT")
283         label:SetText(ACCEPT)
284         label:SetHeight(10)
285
286         local button = CreateFrame("Button", ("%s%dButton"):format(Type, widgetNum), frame, "UIPanelButtonTemplate")
287         button:SetPoint("BOTTOMLEFT", 0, 4)
288         button:SetHeight(22)
289         button:SetWidth(label:GetStringWidth() + 24)
290         button:SetText(ACCEPT)
291         button:SetScript("OnClick", OnClick)
292         button:Disable()
293         
294         local text = button:GetFontString()
295         text:ClearAllPoints()
296         text:SetPoint("TOPLEFT", button, "TOPLEFT", 5, -5)
297         text:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -5, 1)
298         text:SetJustifyV("MIDDLE")
299
300         local scrollBG = CreateFrame("Frame", nil, frame)
301         scrollBG:SetBackdrop(backdrop)
302         scrollBG:SetBackdropColor(0, 0, 0)
303         scrollBG:SetBackdropBorderColor(0.4, 0.4, 0.4)
304
305         local scrollFrame = CreateFrame("ScrollFrame", ("%s%dScrollFrame"):format(Type, widgetNum), frame, "UIPanelScrollFrameTemplate")
306
307         local scrollBar = _G[scrollFrame:GetName() .. "ScrollBar"]
308         scrollBar:ClearAllPoints()
309         scrollBar:SetPoint("TOP", label, "BOTTOM", 0, -19)
310         scrollBar:SetPoint("BOTTOM", button, "TOP", 0, 18)
311         scrollBar:SetPoint("RIGHT", frame, "RIGHT")
312
313         scrollBG:SetPoint("TOPRIGHT", scrollBar, "TOPLEFT", 0, 19)
314         scrollBG:SetPoint("BOTTOMLEFT", button, "TOPLEFT")
315
316         scrollFrame:SetPoint("TOPLEFT", scrollBG, "TOPLEFT", 5, -6)
317         scrollFrame:SetPoint("BOTTOMRIGHT", scrollBG, "BOTTOMRIGHT", -4, 4)
318         scrollFrame:SetScript("OnEnter", OnEnter)
319         scrollFrame:SetScript("OnLeave", OnLeave)
320         scrollFrame:SetScript("OnMouseUp", OnMouseUp)
321         scrollFrame:SetScript("OnReceiveDrag", OnReceiveDrag)
322         scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
323         scrollFrame:HookScript("OnVerticalScroll", OnVerticalScroll)
324
325         local editBox = CreateFrame("EditBox", ("%s%dEdit"):format(Type, widgetNum), scrollFrame)
326         editBox:SetAllPoints()
327         editBox:SetFontObject(ChatFontNormal)
328         editBox:SetMultiLine(true)
329         editBox:EnableMouse(true)
330         editBox:SetAutoFocus(false)
331         editBox:SetCountInvisibleLetters(false)
332         editBox:SetScript("OnCursorChanged", OnCursorChanged)
333         editBox:SetScript("OnEditFocusLost", OnEditFocusLost)
334         editBox:SetScript("OnEnter", OnEnter)
335         editBox:SetScript("OnEscapePressed", editBox.ClearFocus)
336         editBox:SetScript("OnLeave", OnLeave)
337         editBox:SetScript("OnMouseDown", OnReceiveDrag)
338         editBox:SetScript("OnReceiveDrag", OnReceiveDrag)
339         editBox:SetScript("OnTextChanged", OnTextChanged)
340         editBox:SetScript("OnTextSet", OnTextSet)
341         editBox:SetScript("OnEditFocusGained", OnEditFocusGained)
342         
343
344         scrollFrame:SetScrollChild(editBox)
345
346         local widget = {
347                 button      = button,
348                 editBox     = editBox,
349                 frame       = frame,
350                 label       = label,
351                 labelHeight = 10,
352                 numlines    = 4,
353                 scrollBar   = scrollBar,
354                 scrollBG    = scrollBG,
355                 scrollFrame = scrollFrame,
356                 type        = Type
357         }
358         for method, func in pairs(methods) do
359                 widget[method] = func
360         end
361         button.obj, editBox.obj, scrollFrame.obj = widget, widget, widget
362
363         return AceGUI:RegisterAsWidget(widget)
364 end
365
366 AceGUI:RegisterWidgetType(Type, Constructor, Version)