farmbuyer@54
|
1 local Type, Version = "EditBoxDropDown", 5
|
farmbuyer@1
|
2 local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
|
farmbuyer@1
|
3 if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
|
farmbuyer@1
|
4
|
farmbuyer@1
|
5 --[[
|
farmbuyer@1
|
6 This is a from-scratch AceGUI-style implementation of the combination drop-
|
farmbuyer@1
|
7 down editboxes seen in DoTimer's option menus. Typing in the editbox adds
|
farmbuyer@1
|
8 entries to a list; clicking the scrolldown button displays the list in a
|
farmbuyer@1
|
9 dropdown; clicking on an entry in the dropdown removes it from the list.
|
farmbuyer@1
|
10
|
farmbuyer@1
|
11 (This type of widget may actually have a more formal name already. I first
|
farmbuyer@1
|
12 encountered it in DoTimer, so that's what I named it after.)
|
farmbuyer@1
|
13
|
farmbuyer@1
|
14 The implementation does not borrow any of DoTimer's actual code. I've tried
|
farmbuyer@1
|
15 writing this to imitate the look-and-feel of an interface that many players
|
farmbuyer@1
|
16 will find familiar and easy to use.
|
farmbuyer@1
|
17
|
farmbuyer@1
|
18 Version 2 is a rehash to follow the same form of the rest of the AceGUI widgets
|
farmbuyer@1
|
19 after their rewrite, and to work with the new EditBox behavior.
|
farmbuyer@1
|
20
|
farmbuyer@1
|
21 Version 3 adds the EditBoxDropDownOptionControl variant, specifically for use
|
farmbuyer@1
|
22 as a 'dialogControl' in AceConfig option tables. Details follow; the more
|
farmbuyer@54
|
23 disappointing restrictions are because AceConfig never gives the programmer any
|
farmbuyer@1
|
24 direct link to the widgets in use.
|
farmbuyer@1
|
25 - 'desc' option field ignored
|
farmbuyer@1
|
26 - 'name' field may contain an embedded tab ('\t') followed by more text to be
|
farmbuyer@1
|
27 used as the tooltip text when hovering over the editbox field
|
farmbuyer@1
|
28 - 'get' field must be a function, returning a function to be used as the
|
farmbuyer@1
|
29 OnTextEnterPressed callback; this is typically how new entries should be
|
farmbuyer@1
|
30 added to data
|
farmbuyer@1
|
31 - 'values' field must be a function, returning the usual list of entries, PLUS
|
farmbuyer@54
|
32 the callback used for 'get' as a key, e.g.,
|
farmbuyer@1
|
33 values = function()
|
farmbuyer@54
|
34 local ret = build_real_dropdown_table()
|
farmbuyer@54
|
35 ret[get_callback] = true -- assuming "function get_callback (widget, event, text) .... end"
|
farmbuyer@1
|
36 return ret
|
farmbuyer@1
|
37 end
|
farmbuyer@1
|
38 The callback will be immediately removed from the table, but is required to
|
farmbuyer@1
|
39 be present to pass tests in the AceConfig source.
|
farmbuyer@1
|
40 - 'set' receives the key of the dropdown table, but that entry will already be
|
farmbuyer@1
|
41 removed by the time the 'set' function is called
|
farmbuyer@1
|
42
|
farmbuyer@54
|
43 Version 4 was never released.
|
farmbuyer@54
|
44
|
farmbuyer@54
|
45 Version 5 adds the OnDropdownShown callback.
|
farmbuyer@54
|
46
|
farmbuyer@1
|
47
|
farmbuyer@1
|
48 EditBoxDropDown API
|
farmbuyer@1
|
49
|
farmbuyer@1
|
50 :SetLabel(txt)
|
farmbuyer@1
|
51 forwards to the editbox's SetLabel
|
farmbuyer@1
|
52
|
farmbuyer@1
|
53 :SetText(txt)
|
farmbuyer@1
|
54 forwards to the editbox's SetText
|
farmbuyer@1
|
55
|
farmbuyer@1
|
56 :SetEditBoxTooltip(txt)
|
farmbuyer@1
|
57 sets text for the tooltip shown when hovering over the editbox
|
farmbuyer@1
|
58 no default
|
farmbuyer@1
|
59
|
farmbuyer@1
|
60 :SetButtonTooltip(txt)
|
farmbuyer@1
|
61 sets text for the tooltip shown when hovering over the dropdown button
|
farmbuyer@1
|
62 default "Click on entries to remove them."
|
farmbuyer@1
|
63
|
farmbuyer@1
|
64 :SetList(t)
|
farmbuyer@1
|
65 T is a table to be shown in the dropdown list; the values will be displayed
|
farmbuyer@1
|
66 in the dropdown
|
farmbuyer@1
|
67 When entries are clicked, they will be removed from T. T is not copied,
|
farmbuyer@1
|
68 the table is edited "live" before firing the callback below.
|
farmbuyer@1
|
69
|
farmbuyer@1
|
70
|
farmbuyer@1
|
71 EditBoxDropDown Callbacks
|
farmbuyer@1
|
72
|
farmbuyer@1
|
73 OnTextEnterPressed
|
farmbuyer@1
|
74 same as the editbox's OnEnterPressed
|
farmbuyer@1
|
75
|
farmbuyer@1
|
76 OnListItemClicked
|
farmbuyer@1
|
77 similar to a Dropdown widget's OnValueChanged, the key and value from the
|
farmbuyer@1
|
78 table given to :SetList are passed
|
farmbuyer@1
|
79
|
farmbuyer@54
|
80 OnDropdownShown
|
farmbuyer@54
|
81 when the down arrow is clicked to display the list
|
farmbuyer@1
|
82
|
farmbuyer@54
|
83
|
farmbuyer@54
|
84 farmbuyer@gmail.com
|
farmbuyer@1
|
85 ]]
|
farmbuyer@1
|
86
|
farmbuyer@1
|
87 local button_hover_text_default = "Click on entries to remove them."
|
farmbuyer@1
|
88 local maps -- from actual editbox frame back to this widget
|
farmbuyer@1
|
89
|
farmbuyer@1
|
90
|
farmbuyer@1
|
91 local function Menu_OnClick (button, userlist_key, widget)
|
farmbuyer@1
|
92 local v = widget.list[userlist_key]
|
farmbuyer@1
|
93 widget.list[userlist_key] = nil
|
farmbuyer@1
|
94 widget.dropdown.is_on = nil
|
farmbuyer@1
|
95 -- firing these off changes widget contents, must be done last :-(
|
farmbuyer@1
|
96 widget:Fire("OnListItemClicked", userlist_key, v)
|
farmbuyer@1
|
97 widget:Fire("OnValueChanged", userlist_key)
|
farmbuyer@1
|
98 end
|
farmbuyer@1
|
99
|
farmbuyer@1
|
100 local function BuildList (widget)
|
farmbuyer@1
|
101 local ret = {}
|
farmbuyer@1
|
102 if widget.list then for k,v in pairs(widget.list) do
|
farmbuyer@1
|
103 table.insert (ret, {
|
farmbuyer@1
|
104 text = tostring(v) or tostring(k),
|
farmbuyer@1
|
105 func = Menu_OnClick,
|
farmbuyer@1
|
106 arg1 = k,
|
farmbuyer@1
|
107 arg2 = widget,
|
farmbuyer@1
|
108 notCheckable = true,
|
farmbuyer@1
|
109 })
|
farmbuyer@1
|
110 end end
|
farmbuyer@1
|
111 return ret
|
farmbuyer@1
|
112 end
|
farmbuyer@1
|
113
|
farmbuyer@1
|
114
|
farmbuyer@1
|
115 local function ddEditBox_OnMouseEnter (editbox)
|
farmbuyer@1
|
116 if editbox.tooltip_text then
|
farmbuyer@1
|
117 GameTooltip:SetOwner(editbox.frame, "ANCHOR_RIGHT")
|
farmbuyer@1
|
118 GameTooltip:SetText(editbox.tooltip_text, nil, nil, nil, nil, 1)
|
farmbuyer@1
|
119 end
|
farmbuyer@1
|
120 end
|
farmbuyer@1
|
121
|
farmbuyer@1
|
122 local function ddEditBox_OnMouseLeave (editbox_or_button)
|
farmbuyer@1
|
123 GameTooltip:Hide()
|
farmbuyer@1
|
124 end
|
farmbuyer@1
|
125
|
farmbuyer@1
|
126 local function ddEditBox_Clear (editboxframe)
|
farmbuyer@1
|
127 editboxframe:SetText("")
|
farmbuyer@1
|
128 end
|
farmbuyer@1
|
129
|
farmbuyer@1
|
130 local function ddEditBox_Reset (editboxframe) -- :ClearFocus triggers this
|
farmbuyer@1
|
131 editboxframe:SetText(maps[editboxframe].editbox_basetext or "")
|
farmbuyer@1
|
132 end
|
farmbuyer@1
|
133
|
farmbuyer@1
|
134 local function ddEditBox_OnEnterPressed (editbox, _, text)
|
farmbuyer@1
|
135 editbox.obj:Fire("OnTextEnterPressed", text)
|
farmbuyer@1
|
136 ddEditBox_Reset(editbox.editbox)
|
farmbuyer@1
|
137 editbox.editbox:ClearFocus() -- cursor still blinking in there, one more time
|
farmbuyer@1
|
138 end
|
farmbuyer@1
|
139
|
farmbuyer@1
|
140 local function Button_OnClick (button)
|
farmbuyer@1
|
141 local dd = button.obj.dropdown
|
farmbuyer@1
|
142 -- Annoyingly, it's very tedious to find the correct nested frame to use
|
farmbuyer@1
|
143 -- for :IsShown() here. We'll avoid it all by using our own flag.
|
farmbuyer@1
|
144 if dd.is_on then
|
farmbuyer@1
|
145 dd.is_on = nil
|
farmbuyer@1
|
146 HideDropDownMenu(--[[level=]]1) -- EasyMenu always uses top/1 level
|
farmbuyer@1
|
147 else
|
farmbuyer@1
|
148 dd.is_on = true
|
farmbuyer@1
|
149 local t = BuildList(button.obj)
|
farmbuyer@1
|
150 EasyMenu (t, button.obj.dropdown, button.obj.frame, 0, 0, "MENU")
|
farmbuyer@1
|
151 PlaySound("igMainMenuOptionCheckBoxOn")
|
farmbuyer@54
|
152 button.obj:Fire("OnDropdownShown")
|
farmbuyer@1
|
153 end
|
farmbuyer@1
|
154 end
|
farmbuyer@1
|
155
|
farmbuyer@1
|
156 local function Button_OnEnter (button)
|
farmbuyer@1
|
157 if button.tooltip_text then
|
farmbuyer@1
|
158 GameTooltip:SetOwner(button, "ANCHOR_RIGHT")
|
farmbuyer@1
|
159 GameTooltip:SetText(button.tooltip_text, nil, nil, nil, nil, 1)
|
farmbuyer@1
|
160 end
|
farmbuyer@1
|
161 end
|
farmbuyer@1
|
162
|
farmbuyer@1
|
163
|
farmbuyer@54
|
164 --local base_SetWidth = AceGUI.WidgetBase.SetWidth
|
farmbuyer@1
|
165 local methods = {
|
farmbuyer@1
|
166 ["OnAcquire"] = function (self)
|
farmbuyer@1
|
167 self:SetHeight(20)
|
farmbuyer@1
|
168 self:SetWidth(100)
|
farmbuyer@1
|
169 self.button.tooltip_text = button_hover_text_default
|
farmbuyer@1
|
170 self:SetList(nil)
|
farmbuyer@1
|
171 self.editbox:DisableButton(true)
|
farmbuyer@1
|
172
|
farmbuyer@1
|
173 maps = maps or {}
|
farmbuyer@1
|
174 maps[self.editbox.editbox] = self
|
farmbuyer@1
|
175 end,
|
farmbuyer@54
|
176 --[=[
|
farmbuyer@54
|
177 ["SetWidth"] = function (self, width)
|
farmbuyer@54
|
178 print("got",width)
|
farmbuyer@54
|
179 base_SetWidth(self, width)
|
farmbuyer@54
|
180 self.frame.width = width + 45
|
farmbuyer@54
|
181 end,
|
farmbuyer@1
|
182
|
farmbuyer@54
|
183 ["GetWidth"] = function (self)
|
farmbuyer@54
|
184 return self.frame:GetWidth() + 45
|
farmbuyer@54
|
185 end,
|
farmbuyer@54
|
186 ]=]
|
farmbuyer@1
|
187 ["OnRelease"] = function (self)
|
farmbuyer@1
|
188 self.frame:ClearAllPoints()
|
farmbuyer@1
|
189 self.frame:Hide()
|
farmbuyer@1
|
190 self.editbox.tooltip_text = nil
|
farmbuyer@1
|
191 self.button.tooltip_text = nil
|
farmbuyer@1
|
192 self:SetList(nil)
|
farmbuyer@1
|
193 maps[self.editbox.editbox] = nil
|
farmbuyer@1
|
194 end,
|
farmbuyer@1
|
195
|
farmbuyer@1
|
196 ["SetParent"] = function (self, parent)
|
farmbuyer@1
|
197 self.frame:SetParent(nil)
|
farmbuyer@1
|
198 self.frame:SetParent(parent.content)
|
farmbuyer@1
|
199 self.parent = parent
|
farmbuyer@1
|
200 self.editbox:SetParent(parent)
|
farmbuyer@1
|
201 end,
|
farmbuyer@1
|
202
|
farmbuyer@1
|
203 ["SetText"] = function (self, text)
|
farmbuyer@1
|
204 self.editbox_basetext = text
|
farmbuyer@1
|
205 return self.editbox:SetText(text)
|
farmbuyer@1
|
206 end,
|
farmbuyer@1
|
207
|
farmbuyer@1
|
208 ["SetLabel"] = function (self, text)
|
farmbuyer@1
|
209 return self.editbox:SetLabel(text)
|
farmbuyer@1
|
210 end,
|
farmbuyer@1
|
211
|
farmbuyer@1
|
212 ["SetDisabled"] = function (self, disabled)
|
farmbuyer@1
|
213 self.editbox:SetDisabled(disabled)
|
farmbuyer@1
|
214 if disabled then
|
farmbuyer@1
|
215 self.button:Disable()
|
farmbuyer@1
|
216 else
|
farmbuyer@1
|
217 self.button:Enable()
|
farmbuyer@1
|
218 end
|
farmbuyer@1
|
219 end,
|
farmbuyer@1
|
220
|
farmbuyer@1
|
221 ["SetList"] = function (self, list)
|
farmbuyer@1
|
222 self.list = list
|
farmbuyer@1
|
223 end,
|
farmbuyer@1
|
224
|
farmbuyer@1
|
225 ["SetEditBoxTooltip"] = function (self, text)
|
farmbuyer@1
|
226 self.editbox.tooltip_text = text
|
farmbuyer@1
|
227 end,
|
farmbuyer@1
|
228
|
farmbuyer@1
|
229 ["SetButtonTooltip"] = function (self, text)
|
farmbuyer@1
|
230 self.button.tooltip_text = text
|
farmbuyer@1
|
231 end,
|
farmbuyer@1
|
232 }
|
farmbuyer@1
|
233
|
farmbuyer@1
|
234 -- called with the 'name' entry
|
farmbuyer@1
|
235 local function optcontrol_SetLabel (self, text)
|
farmbuyer@1
|
236 local name, desc = ('\t'):split(text)
|
farmbuyer@1
|
237 if desc then
|
farmbuyer@1
|
238 self:SetEditBoxTooltip(desc)
|
farmbuyer@1
|
239 end
|
farmbuyer@1
|
240 self.editbox:SetLabel(name)
|
farmbuyer@1
|
241 end
|
farmbuyer@1
|
242
|
farmbuyer@1
|
243 local function optcontrol_SetValue (self, epcallback)
|
farmbuyer@1
|
244 -- set the callback
|
farmbuyer@1
|
245 self:SetCallback("OnTextEnterPressed", epcallback)
|
farmbuyer@1
|
246 -- remove the fake entry from the values table
|
farmbuyer@1
|
247 self.list[epcallback] = nil
|
farmbuyer@1
|
248 end
|
farmbuyer@1
|
249
|
farmbuyer@1
|
250
|
farmbuyer@1
|
251 local function Constructor(is_option_control)
|
farmbuyer@1
|
252 local num = AceGUI:GetNextWidgetNum(Type)
|
farmbuyer@1
|
253
|
farmbuyer@1
|
254 -- Its frame becomes our widget frame, else its frame is never shown. Gluing
|
farmbuyer@1
|
255 -- them together seems a little evil, but it beats making this widget into a
|
farmbuyer@1
|
256 -- formal containter. Inspired by new-style InteractiveLabel.
|
farmbuyer@1
|
257 local editbox = AceGUI:Create("EditBox")
|
farmbuyer@1
|
258 local frame = editbox.frame
|
farmbuyer@1
|
259 editbox:SetHeight(20)
|
farmbuyer@1
|
260 editbox:SetWidth(100)
|
farmbuyer@54
|
261 --frame:SetWidth(frame:GetWidth()+15)
|
farmbuyer@54
|
262 --frame.width = frame:GetWidth() + 15
|
farmbuyer@1
|
263 editbox:SetCallback("OnEnter", ddEditBox_OnMouseEnter)
|
farmbuyer@1
|
264 editbox:SetCallback("OnLeave", ddEditBox_OnMouseLeave)
|
farmbuyer@1
|
265 editbox:SetCallback("OnEnterPressed", ddEditBox_OnEnterPressed)
|
farmbuyer@1
|
266 editbox.editbox:SetScript("OnEditFocusGained", ddEditBox_Clear)
|
farmbuyer@1
|
267 editbox.editbox:SetScript("OnEditFocusLost", ddEditBox_Reset)
|
farmbuyer@1
|
268 --editbox.editbox:SetScript("OnEscapePressed", ddEditBox_Reset)
|
farmbuyer@1
|
269
|
farmbuyer@1
|
270 local button = CreateFrame("Button", nil, frame)
|
farmbuyer@1
|
271 button:SetHeight(20)
|
farmbuyer@1
|
272 button:SetWidth(24)
|
farmbuyer@1
|
273 button:SetPoint("LEFT", editbox.frame, "RIGHT", 0, 0)
|
farmbuyer@1
|
274 button:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Up")
|
farmbuyer@1
|
275 button:SetPushedTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Down")
|
farmbuyer@1
|
276 button:SetDisabledTexture("Interface\\ChatFrame\\UI-ChatIcon-ScrollDown-Disabled")
|
farmbuyer@1
|
277 button:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight","ADD")
|
farmbuyer@1
|
278 button:SetScript("OnClick", Button_OnClick)
|
farmbuyer@1
|
279 button:SetScript("OnEnter", Button_OnEnter)
|
farmbuyer@1
|
280 button:SetScript("OnLeave", ddEditBox_OnMouseLeave)
|
farmbuyer@1
|
281 button.parent = frame
|
farmbuyer@1
|
282
|
farmbuyer@1
|
283 local dropdown = CreateFrame("Frame", "AceGUI-3.0EditBoxDropDownMenu"..num, nil, "UIDropDownMenuTemplate")
|
farmbuyer@1
|
284 dropdown:Hide()
|
farmbuyer@1
|
285
|
farmbuyer@1
|
286 local widget = {
|
farmbuyer@1
|
287 editbox = editbox,
|
farmbuyer@1
|
288 button = button,
|
farmbuyer@1
|
289 dropdown = dropdown,
|
farmbuyer@1
|
290 frame = frame,
|
farmbuyer@1
|
291 type = Type
|
farmbuyer@1
|
292 }
|
farmbuyer@1
|
293 for method, func in pairs(methods) do
|
farmbuyer@1
|
294 widget[method] = func
|
farmbuyer@1
|
295 end
|
farmbuyer@1
|
296 editbox.obj, button.obj, dropdown.obj = widget, widget, widget
|
farmbuyer@1
|
297 if is_option_control then
|
farmbuyer@1
|
298 widget.is_option_control = true
|
farmbuyer@1
|
299 widget.SetLabel = optcontrol_SetLabel
|
farmbuyer@1
|
300 widget.SetValue = optcontrol_SetValue
|
farmbuyer@1
|
301 end
|
farmbuyer@1
|
302
|
farmbuyer@1
|
303 return AceGUI:RegisterAsWidget(widget)
|
farmbuyer@1
|
304 end
|
farmbuyer@1
|
305
|
farmbuyer@1
|
306 AceGUI:RegisterWidgetType (Type, Constructor, Version)
|
farmbuyer@1
|
307
|
farmbuyer@1
|
308 AceGUI:RegisterWidgetType (Type.."OptionControl", function() return Constructor(true) end, Version)
|
farmbuyer@1
|
309
|