vanilla-wow-addons – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | --[[ |
2 | Name: Dewdrop-2.0 |
||
3 | Revision: $Rev: 7265 $ |
||
4 | Author(s): ckknight (ckknight@gmail.com) |
||
5 | Website: http://ckknight.wowinterface.com/ |
||
6 | Documentation: http://wiki.wowace.com/index.php/Dewdrop-2.0 |
||
7 | SVN: http://svn.wowace.com/root/trunk/DewdropLib/Dewdrop-2.0 |
||
8 | Description: A library to provide a clean dropdown menu interface. |
||
9 | Dependencies: AceLibrary |
||
10 | ]] |
||
11 | |||
12 | local MAJOR_VERSION = "Dewdrop-2.0" |
||
13 | local MINOR_VERSION = "$Revision: 7265 $" |
||
14 | |||
15 | if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end |
||
16 | if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end |
||
17 | |||
18 | local Dewdrop = {} |
||
19 | |||
20 | local function new(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) |
||
21 | local t = {} |
||
22 | if k1 then t[k1] = v1 |
||
23 | if k2 then t[k2] = v2 |
||
24 | if k3 then t[k3] = v3 |
||
25 | if k4 then t[k4] = v4 |
||
26 | if k5 then t[k5] = v5 |
||
27 | if k6 then t[k6] = v6 |
||
28 | if k7 then t[k7] = v7 |
||
29 | if k8 then t[k8] = v8 |
||
30 | if k9 then t[k9] = v9 |
||
31 | if k10 then t[k10] = v10 |
||
32 | if k11 then t[k11] = v11 |
||
33 | if k12 then t[k12] = v12 |
||
34 | if k13 then t[k13] = v13 |
||
35 | if k14 then t[k14] = v14 |
||
36 | if k15 then t[k15] = v15 |
||
37 | if k16 then t[k16] = v16 |
||
38 | if k17 then t[k17] = v17 |
||
39 | if k18 then t[k18] = v18 |
||
40 | if k19 then t[k19] = v19 |
||
41 | if k20 then t[k20] = v20 |
||
42 | end end end end end end end end end end end end end end end end end end end end |
||
43 | return t |
||
44 | end |
||
45 | local tmp |
||
46 | do |
||
47 | local t |
||
48 | function tmp(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) |
||
49 | for k in pairs(t) do |
||
50 | t[k] = nil |
||
51 | end |
||
52 | if type(k1) == "table" then |
||
53 | for k,v in pairs(k1) do |
||
54 | t[k] = v |
||
55 | end |
||
56 | else |
||
57 | if k1 then t[k1] = v1 |
||
58 | if k2 then t[k2] = v2 |
||
59 | if k3 then t[k3] = v3 |
||
60 | if k4 then t[k4] = v4 |
||
61 | if k5 then t[k5] = v5 |
||
62 | if k6 then t[k6] = v6 |
||
63 | if k7 then t[k7] = v7 |
||
64 | if k8 then t[k8] = v8 |
||
65 | if k9 then t[k9] = v9 |
||
66 | if k10 then t[k10] = v10 |
||
67 | if k11 then t[k11] = v11 |
||
68 | if k12 then t[k12] = v12 |
||
69 | if k13 then t[k13] = v13 |
||
70 | if k14 then t[k14] = v14 |
||
71 | if k15 then t[k15] = v15 |
||
72 | if k16 then t[k16] = v16 |
||
73 | if k17 then t[k17] = v17 |
||
74 | if k18 then t[k18] = v18 |
||
75 | if k19 then t[k19] = v19 |
||
76 | if k20 then t[k20] = v20 |
||
77 | end end end end end end end end end end end end end end end end end end end end |
||
78 | end |
||
79 | return t |
||
80 | end |
||
81 | local x = tmp |
||
82 | function tmp(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) |
||
83 | t = {} |
||
84 | tmp = x |
||
85 | x = nil |
||
86 | return tmp(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) |
||
87 | end |
||
88 | end |
||
89 | local tmp2 |
||
90 | do |
||
91 | local t |
||
92 | function tmp2(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) |
||
93 | for k in pairs(t) do |
||
94 | t[k] = nil |
||
95 | end |
||
96 | if k1 then t[k1] = v1 |
||
97 | if k2 then t[k2] = v2 |
||
98 | if k3 then t[k3] = v3 |
||
99 | if k4 then t[k4] = v4 |
||
100 | if k5 then t[k5] = v5 |
||
101 | if k6 then t[k6] = v6 |
||
102 | if k7 then t[k7] = v7 |
||
103 | if k8 then t[k8] = v8 |
||
104 | if k9 then t[k9] = v9 |
||
105 | if k10 then t[k10] = v10 |
||
106 | if k11 then t[k11] = v11 |
||
107 | if k12 then t[k12] = v12 |
||
108 | if k13 then t[k13] = v13 |
||
109 | if k14 then t[k14] = v14 |
||
110 | if k15 then t[k15] = v15 |
||
111 | if k16 then t[k16] = v16 |
||
112 | if k17 then t[k17] = v17 |
||
113 | if k18 then t[k18] = v18 |
||
114 | if k19 then t[k19] = v19 |
||
115 | if k20 then t[k20] = v20 |
||
116 | end end end end end end end end end end end end end end end end end end end end |
||
117 | return t |
||
118 | end |
||
119 | local x = tmp2 |
||
120 | function tmp2(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) |
||
121 | t = {} |
||
122 | tmp2 = x |
||
123 | x = nil |
||
124 | return tmp2(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) |
||
125 | end |
||
126 | end |
||
127 | local levels |
||
128 | local buttons |
||
129 | |||
130 | local function GetScaledCursorPosition() |
||
131 | local x, y = GetCursorPosition() |
||
132 | local scale = UIParent:GetEffectiveScale() |
||
133 | return x / scale, y / scale |
||
134 | end |
||
135 | |||
136 | local function StartCounting(self, levelNum) |
||
137 | for i = levelNum, table.getn(levels) do |
||
138 | if levels[i] then |
||
139 | levels[i].count = 3 |
||
140 | end |
||
141 | end |
||
142 | end |
||
143 | |||
144 | local function StopCounting(self, level) |
||
145 | for i = level, 1, -1 do |
||
146 | if levels[i] then |
||
147 | levels[i].count = nil |
||
148 | end |
||
149 | end |
||
150 | end |
||
151 | |||
152 | local function OnUpdate(self, arg1) |
||
153 | for _,level in ipairs(levels) do |
||
154 | if level.count then |
||
155 | level.count = level.count - arg1 |
||
156 | if level.count < 0 then |
||
157 | level.count = nil |
||
158 | self:Close(level.num) |
||
159 | end |
||
160 | end |
||
161 | end |
||
162 | end |
||
163 | |||
164 | local function CheckDualMonitor(self, frame) |
||
165 | local ratio = GetScreenWidth() / GetScreenHeight() |
||
166 | if ratio >= 2.4 and frame:GetRight() > GetScreenWidth() / 2 and frame:GetLeft() < GetScreenWidth() / 2 then |
||
167 | local offsetx |
||
168 | if GetCursorPosition() / GetScreenHeight() * 768 < GetScreenWidth() / 2 then |
||
169 | offsetx = GetScreenWidth() / 2 - frame:GetRight() |
||
170 | else |
||
171 | offsetx = GetScreenWidth() / 2 - frame:GetLeft() |
||
172 | end |
||
173 | local point, parent, relativePoint, x, y = frame:GetPoint(1) |
||
174 | frame:SetPoint(point, parent, relativePoint, (x or 0) + offsetx, y or 0) |
||
175 | end |
||
176 | end |
||
177 | |||
178 | local function CheckSize(self, level) |
||
179 | if not level.buttons then |
||
180 | return |
||
181 | end |
||
182 | local height = 20 |
||
183 | for _, button in ipairs(level.buttons) do |
||
184 | height = height + button:GetHeight() |
||
185 | end |
||
186 | level:SetHeight(height) |
||
187 | local width = 160 |
||
188 | for _, button in ipairs(level.buttons) do |
||
189 | local extra = 1 |
||
190 | if button.hasArrow or button.hasColorSwatch then |
||
191 | extra = extra + 16 |
||
192 | end |
||
193 | if not button.notCheckable then |
||
194 | extra = extra + 24 |
||
195 | end |
||
196 | button.text:SetFont(STANDARD_TEXT_FONT, button.textHeight) |
||
197 | if button.text:GetWidth() + extra > width then |
||
198 | width = button.text:GetWidth() + extra |
||
199 | end |
||
200 | end |
||
201 | level:SetWidth(width + 20) |
||
202 | if level:GetLeft() and level:GetRight() and level:GetTop() and level:GetBottom() and (level:GetLeft() < 0 or level:GetRight() > GetScreenWidth() or level:GetTop() > GetScreenHeight() or level:GetBottom() < 0) then |
||
203 | level:ClearAllPoints() |
||
204 | if level.lastDirection == "RIGHT" then |
||
205 | if level.lastVDirection == "DOWN" then |
||
206 | level:SetPoint("TOPLEFT", level.parent or level:GetParent(), "TOPRIGHT", 5, 10) |
||
207 | else |
||
208 | level:SetPoint("BOTTOMLEFT", level.parent or level:GetParent(), "BOTTOMRIGHT", 5, -10) |
||
209 | end |
||
210 | else |
||
211 | if level.lastVDirection == "DOWN" then |
||
212 | level:SetPoint("TOPRIGHT", level.parent or level:GetParent(), "TOPLEFT", -5, 10) |
||
213 | else |
||
214 | level:SetPoint("BOTTOMRIGHT", level.parent or level:GetParent(), "BOTTOMLEFT", -5, -10) |
||
215 | end |
||
216 | end |
||
217 | end |
||
218 | local dirty = false |
||
219 | if not level:GetRight() then |
||
220 | self:Close() |
||
221 | return |
||
222 | end |
||
223 | if level:GetRight() > GetScreenWidth() and level.lastDirection == "RIGHT" then |
||
224 | level.lastDirection = "LEFT" |
||
225 | dirty = true |
||
226 | elseif level:GetLeft() < 0 and level.lastDirection == "LEFT" then |
||
227 | level.lastDirection = "RIGHT" |
||
228 | dirty = true |
||
229 | end |
||
230 | if level:GetTop() > GetScreenHeight() and level.lastVDirection == "UP" then |
||
231 | level.lastVDirection = "DOWN" |
||
232 | dirty = true |
||
233 | elseif level:GetBottom() < 0 and level.lastVDirection == "DOWN" then |
||
234 | level.lastVDirection = "UP" |
||
235 | dirty = true |
||
236 | end |
||
237 | if dirty then |
||
238 | level:ClearAllPoints() |
||
239 | if level.lastDirection == "RIGHT" then |
||
240 | if level.lastVDirection == "DOWN" then |
||
241 | level:SetPoint("TOPLEFT", level.parent or level:GetParent(), "TOPRIGHT", 5, 10) |
||
242 | else |
||
243 | level:SetPoint("BOTTOMLEFT", level.parent or level:GetParent(), "BOTTOMRIGHT", 5, -10) |
||
244 | end |
||
245 | else |
||
246 | if level.lastVDirection == "DOWN" then |
||
247 | level:SetPoint("TOPRIGHT", level.parent or level:GetParent(), "TOPLEFT", -5, 10) |
||
248 | else |
||
249 | level:SetPoint("BOTTOMRIGHT", level.parent or level:GetParent(), "BOTTOMLEFT", -5, -10) |
||
250 | end |
||
251 | end |
||
252 | end |
||
253 | if level:GetTop() > GetScreenHeight() then |
||
254 | local top = level:GetTop() |
||
255 | local point, parent, relativePoint, x, y = level:GetPoint(1) |
||
256 | level:ClearAllPoints() |
||
257 | level:SetPoint(point, parent, relativePoint, x or 0, (y or 0) + GetScreenHeight() - top) |
||
258 | elseif level:GetBottom() < 0 then |
||
259 | local bottom = level:GetBottom() |
||
260 | local point, parent, relativePoint, x, y = level:GetPoint(1) |
||
261 | level:ClearAllPoints() |
||
262 | level:SetPoint(point, parent, relativePoint, x or 0, (y or 0) - bottom) |
||
263 | end |
||
264 | CheckDualMonitor(self, level) |
||
265 | if mod(level.num, 5) == 0 then |
||
266 | local left, bottom = level:GetLeft(), level:GetBottom() |
||
267 | level:ClearAllPoints() |
||
268 | level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) |
||
269 | end |
||
270 | end |
||
271 | |||
272 | local Open |
||
273 | local OpenSlider |
||
274 | local OpenEditBox |
||
275 | local Refresh |
||
276 | local Clear |
||
277 | local function ReleaseButton(self, level, index) |
||
278 | if not level.buttons then |
||
279 | return |
||
280 | end |
||
281 | if not level.buttons[index] then |
||
282 | return |
||
283 | end |
||
284 | local button = level.buttons[index] |
||
285 | button:Hide() |
||
286 | if button.highlight then |
||
287 | button.highlight:Hide() |
||
288 | end |
||
289 | table.remove(level.buttons, index) |
||
290 | table.insert(buttons, button) |
||
291 | for k in pairs(button) do |
||
292 | if k ~= 0 and k ~= "text" and k ~= "check" and k ~= "arrow" and k ~= "colorSwatch" and k ~= "highlight" and k ~= "radioHighlight" then |
||
293 | button[k] = nil |
||
294 | end |
||
295 | end |
||
296 | return true |
||
297 | end |
||
298 | |||
299 | local function Scroll(self, level, down) |
||
300 | if down then |
||
301 | if level:GetBottom() < 0 then |
||
302 | local point, parent, relativePoint, x, y = level:GetPoint(1) |
||
303 | level:SetPoint(point, parent, relativePoint, x, y + 50) |
||
304 | if level:GetBottom() > 0 then |
||
305 | level:SetPoint(point, parent, relativePoint, x, y + 50 - level:GetBottom()) |
||
306 | end |
||
307 | end |
||
308 | else |
||
309 | if level:GetTop() > GetScreenHeight() then |
||
310 | local point, parent, relativePoint, x, y = level:GetPoint(1) |
||
311 | level:SetPoint(point, parent, relativePoint, x, y - 50) |
||
312 | if level:GetTop() < GetScreenHeight() then |
||
313 | level:SetPoint(point, parent, relativePoint, x, y - 50 + GetScreenHeight() - level:GetTop()) |
||
314 | end |
||
315 | end |
||
316 | end |
||
317 | end |
||
318 | |||
319 | local sliderFrame |
||
320 | local editBoxFrame |
||
321 | |||
322 | local function AcquireButton(self, level) |
||
323 | if not levels[level] then |
||
324 | return |
||
325 | end |
||
326 | level = levels[level] |
||
327 | if not level.buttons then |
||
328 | level.buttons = {} |
||
329 | end |
||
330 | local button |
||
331 | if table.getn(buttons) == 0 then |
||
332 | button = CreateFrame("Button") |
||
333 | button:SetFrameStrata("FULLSCREEN_DIALOG") |
||
334 | button:SetHeight(16) |
||
335 | local highlight = button:CreateTexture(nil, "BACKGROUND") |
||
336 | highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight") |
||
337 | button.highlight = highlight |
||
338 | highlight:SetBlendMode("ADD") |
||
339 | highlight:SetAllPoints(button) |
||
340 | highlight:Hide() |
||
341 | local check = button:CreateTexture(nil, "ARTWORK") |
||
342 | button.check = check |
||
343 | check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") |
||
344 | check:SetPoint("CENTER", button, "LEFT", 12, 0) |
||
345 | check:SetWidth(24) |
||
346 | check:SetHeight(24) |
||
347 | local radioHighlight = button:CreateTexture(nil, "ARTWORK") |
||
348 | button.radioHighlight = radioHighlight |
||
349 | radioHighlight:SetTexture("Interface\\Buttons\\UI-RadioButton") |
||
350 | radioHighlight:SetAllPoints(check) |
||
351 | radioHighlight:SetBlendMode("ADD") |
||
352 | radioHighlight:SetTexCoord(0.5, 0.75, 0, 1) |
||
353 | radioHighlight:Hide() |
||
354 | button:SetScript("OnEnter", function() |
||
355 | if (sliderFrame and sliderFrame:IsShown() and sliderFrame.mouseDown and sliderFrame.level == this.level.num + 1) or (editBoxFrame and editBoxFrame:IsShown() and editBoxFrame.mouseDown and editBoxFrame.level == this.level.num + 1) then |
||
356 | for i = 1, this.level.num do |
||
357 | Refresh(self, levels[i]) |
||
358 | end |
||
359 | return |
||
360 | end |
||
361 | self:Close(this.level.num + 1) |
||
362 | if not this.disabled then |
||
363 | if this.hasSlider then |
||
364 | OpenSlider(self, this) |
||
365 | elseif this.hasEditBox then |
||
366 | OpenEditBox(self, this) |
||
367 | elseif this.hasArrow then |
||
368 | Open(self, this, nil, this.level.num + 1, this.value) |
||
369 | end |
||
370 | end |
||
371 | if not this.level then -- button reclaimed |
||
372 | return |
||
373 | end |
||
374 | StopCounting(self, this.level.num + 1) |
||
375 | if not this.disabled then |
||
376 | highlight:Show() |
||
377 | if this.isRadio then |
||
378 | button.radioHighlight:Show() |
||
379 | end |
||
380 | end |
||
381 | if this.tooltipTitle or this.tooltipText then |
||
382 | GameTooltip_SetDefaultAnchor(GameTooltip, this) |
||
383 | local disabled = this.disabled |
||
384 | if this.tooltipTitle then |
||
385 | if disabled then |
||
386 | GameTooltip:SetText(this.tooltipTitle, 0.5, 0.5, 0.5, 1) |
||
387 | else |
||
388 | GameTooltip:SetText(this.tooltipTitle, 1, 1, 1, 1) |
||
389 | end |
||
390 | if this.tooltipText then |
||
391 | if disabled then |
||
392 | GameTooltip:AddLine(this.tooltipText, (NORMAL_FONT_COLOR.r + 0.5) / 2, (NORMAL_FONT_COLOR.g + 0.5) / 2, (NORMAL_FONT_COLOR.b + 0.5) / 2, 1) |
||
393 | else |
||
394 | GameTooltip:AddLine(this.tooltipText, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1) |
||
395 | end |
||
396 | end |
||
397 | else |
||
398 | if disabled then |
||
399 | GameTooltip:SetText(this.tooltipText, 0.5, 0.5, 0.5, 1) |
||
400 | else |
||
401 | GameTooltip:SetText(this.tooltipText, 1, 1, 1, 1) |
||
402 | end |
||
403 | end |
||
404 | GameTooltip:Show() |
||
405 | end |
||
406 | if this.tooltipFunc then |
||
407 | GameTooltip:SetOwner(this, "ANCHOR_NONE") |
||
408 | GameTooltip:SetPoint("TOPLEFT", this, "TOPRIGHT", 5, 0) |
||
409 | this.tooltipFunc(this.tooltipArg1, this.tooltipArg2, this.tooltipArg3, this.tooltipArg4) |
||
410 | GameTooltip:Show() |
||
411 | end |
||
412 | end) |
||
413 | button:SetScript("OnLeave", function() |
||
414 | highlight:Hide() |
||
415 | button.radioHighlight:Hide() |
||
416 | if this.level then |
||
417 | StartCounting(self, this.level.num) |
||
418 | end |
||
419 | GameTooltip:Hide() |
||
420 | end) |
||
421 | button:SetScript("OnClick", function() |
||
422 | if not this.disabled then |
||
423 | if this.hasColorSwatch then |
||
424 | local func = button.colorFunc |
||
425 | local a1,a2,a3,a4 = button.colorArg1, button.colorArg2, button.colorArg3, button.colorArg4 |
||
426 | local hasOpacity = this.hasOpacity |
||
427 | ColorPickerFrame.func = function() |
||
428 | if func then |
||
429 | local r,g,b = ColorPickerFrame:GetColorRGB() |
||
430 | local a = hasOpacity and 1 - OpacitySliderFrame:GetValue() or nil |
||
431 | if a1 == nil then |
||
432 | func(r, g, b, a) |
||
433 | elseif a2 == nil then |
||
434 | func(a1, r, g, b, a) |
||
435 | elseif a3 == nil then |
||
436 | func(a1, a2, r, g, b, a) |
||
437 | elseif a4 == nil then |
||
438 | func(a1, a2, a3, r, g, b, a) |
||
439 | else |
||
440 | func(a1, a2, a3, a4, r, g, b, a) |
||
441 | end |
||
442 | end |
||
443 | end |
||
444 | ColorPickerFrame.hasOpacity = this.hasOpacity |
||
445 | ColorPickerFrame.opacityFunc = ColorPickerFrame.func |
||
446 | ColorPickerFrame.opacity = 1 - this.opacity |
||
447 | ColorPickerFrame:SetColorRGB(this.r, this.g, this.b) |
||
448 | local r, g, b, a = this.r, this.g, this.b, this.opacity |
||
449 | ColorPickerFrame.cancelFunc = function() |
||
450 | if a1 == nil then |
||
451 | func(r, g, b, a) |
||
452 | elseif a2 == nil then |
||
453 | func(a1, r, g, b, a) |
||
454 | elseif a3 == nil then |
||
455 | func(a1, a2, r, g, b, a) |
||
456 | else |
||
457 | func(a1, a2, a3, r, g, b, a) |
||
458 | end |
||
459 | end |
||
460 | self:Close(1) |
||
461 | ShowUIPanel(ColorPickerFrame) |
||
462 | elseif this.func then |
||
463 | local level = button.level |
||
464 | if type(this.func) == "string" then |
||
465 | self:assert(type(this.arg1[this.func]) == "function", "Cannot call method " .. this.func) |
||
466 | this.arg1[this.func](this.arg1, this.arg2, this.arg3, this.arg4) |
||
467 | else |
||
468 | this.func(this.arg1, this.arg2, this.arg3, this.arg4) |
||
469 | end |
||
470 | if this.closeWhenClicked then |
||
471 | self:Close() |
||
472 | elseif level:IsShown() then |
||
473 | for i = 1, level.num do |
||
474 | Refresh(self, levels[i]) |
||
475 | end |
||
476 | end |
||
477 | elseif this.closeWhenClicked then |
||
478 | self:Close() |
||
479 | end |
||
480 | end |
||
481 | end) |
||
482 | local text = button:CreateFontString(nil, "ARTWORK") |
||
483 | button.text = text |
||
484 | text:SetFontObject(GameFontHighlightSmall) |
||
485 | button.text:SetFont(STANDARD_TEXT_FONT, UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT) |
||
486 | button:SetScript("OnMouseDown", function() |
||
487 | if not this.disabled and (this.func or this.colorFunc or this.closeWhenClicked) then |
||
488 | text:SetPoint("LEFT", button, "LEFT", this.notCheckable and 1 or 25, -1) |
||
489 | end |
||
490 | end) |
||
491 | button:SetScript("OnMouseUp", function() |
||
492 | if not this.disabled and (this.func or this.colorFunc or this.closeWhenClicked) then |
||
493 | text:SetPoint("LEFT", button, "LEFT", this.notCheckable and 0 or 24, 0) |
||
494 | end |
||
495 | end) |
||
496 | local arrow = button:CreateTexture(nil, "ARTWORK") |
||
497 | button.arrow = arrow |
||
498 | arrow:SetPoint("RIGHT", button, "RIGHT", 0, 0) |
||
499 | arrow:SetWidth(16) |
||
500 | arrow:SetHeight(16) |
||
501 | arrow:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow") |
||
502 | local colorSwatch = button:CreateTexture(nil, "OVERLAY") |
||
503 | button.colorSwatch = colorSwatch |
||
504 | colorSwatch:SetWidth(20) |
||
505 | colorSwatch:SetHeight(20) |
||
506 | colorSwatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch") |
||
507 | local texture = button:CreateTexture(nil, "OVERLAY") |
||
508 | colorSwatch.texture = texture |
||
509 | texture:SetTexture(1, 1, 1) |
||
510 | texture:SetWidth(11.5) |
||
511 | texture:SetHeight(11.5) |
||
512 | texture:Show() |
||
513 | texture:SetPoint("CENTER", colorSwatch, "CENTER") |
||
514 | colorSwatch:SetPoint("RIGHT", button, "RIGHT", 0, 0) |
||
515 | else |
||
516 | button = buttons[table.getn(buttons)] |
||
517 | table.remove(buttons, table.getn(buttons)) |
||
518 | end |
||
519 | button:ClearAllPoints() |
||
520 | button:SetParent(level) |
||
521 | button:SetFrameStrata(level:GetFrameStrata()) |
||
522 | button:SetFrameLevel(level:GetFrameLevel() + 1) |
||
523 | button:SetPoint("LEFT", level, "LEFT", 10, 0) |
||
524 | button:SetPoint("RIGHT", level, "RIGHT", -10, 0) |
||
525 | if table.getn(level.buttons) == 0 then |
||
526 | button:SetPoint("TOP", level, "TOP", 0, -10) |
||
527 | else |
||
528 | button:SetPoint("TOP", level.buttons[table.getn(level.buttons)], "BOTTOM", 0, 0) |
||
529 | end |
||
530 | button.text:SetPoint("LEFT", button, "LEFT", 24, 0) |
||
531 | button:Show() |
||
532 | button.level = level |
||
533 | table.insert(level.buttons, button) |
||
534 | if not level.parented then |
||
535 | level.parented = true |
||
536 | level:ClearAllPoints() |
||
537 | if level.num == 1 then |
||
538 | if level.parent ~= UIParent then |
||
539 | level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT") |
||
540 | else |
||
541 | level:SetPoint("CENTER", level.parent, "CENTER") |
||
542 | end |
||
543 | else |
||
544 | if level.lastDirection == "RIGHT" then |
||
545 | if level.lastVDirection == "DOWN" then |
||
546 | level:SetPoint("TOPLEFT", level.parent, "TOPRIGHT", 5, 10) |
||
547 | else |
||
548 | level:SetPoint("BOTTOMLEFT", level.parent, "BOTTOMRIGHT", 5, -10) |
||
549 | end |
||
550 | else |
||
551 | if level.lastVDirection == "DOWN" then |
||
552 | level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT", -5, 10) |
||
553 | else |
||
554 | level:SetPoint("BOTTOMRIGHT", level.parent, "BOTTOMLEFT", -5, -10) |
||
555 | end |
||
556 | end |
||
557 | end |
||
558 | level:SetFrameStrata("FULLSCREEN_DIALOG") |
||
559 | end |
||
560 | return button |
||
561 | end |
||
562 | |||
563 | local function AcquireLevel(self, level) |
||
564 | if not levels[level] then |
||
565 | for i = table.getn(levels) + 1, level, -1 do |
||
566 | local i = i |
||
567 | local frame = CreateFrame("Button") |
||
568 | if i == 1 then |
||
569 | local old_CloseWindows = CloseWindows |
||
570 | function CloseWindows(ignoreCenter) |
||
571 | local found = old_CloseWindows(ignoreCenter) |
||
572 | if levels[1]:IsShown() then |
||
573 | self:Close() |
||
574 | return 1 |
||
575 | end |
||
576 | return found |
||
577 | end |
||
578 | end |
||
579 | levels[i] = frame |
||
580 | frame.num = i |
||
581 | frame:SetParent(UIParent) |
||
582 | frame:SetFrameStrata("FULLSCREEN_DIALOG") |
||
583 | frame:Hide() |
||
584 | frame:SetWidth(180) |
||
585 | frame:SetHeight(10) |
||
586 | frame:SetFrameLevel(i * 3) |
||
587 | frame:SetScript("OnHide", function() |
||
588 | self:Close(level + 1) |
||
589 | end) |
||
590 | frame:SetFrameStrata("FULLSCREEN_DIALOG") |
||
591 | if frame.SetTopLevel then |
||
592 | frame:SetTopLevel(true) |
||
593 | end |
||
594 | frame:EnableMouse(true) |
||
595 | frame:EnableMouseWheel(true) |
||
596 | local backdrop = CreateFrame("Frame", nil, frame) |
||
597 | backdrop:SetAllPoints(frame) |
||
598 | backdrop:SetBackdrop(tmp( |
||
599 | 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", |
||
600 | 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", |
||
601 | 'tile', true, |
||
602 | 'insets', tmp2( |
||
603 | 'left', 5, |
||
604 | 'right', 5, |
||
605 | 'top', 5, |
||
606 | 'bottom', 5 |
||
607 | ), |
||
608 | 'tileSize', 16, |
||
609 | 'edgeSize', 16 |
||
610 | )) |
||
611 | backdrop:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) |
||
612 | backdrop:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) |
||
613 | frame:SetScript("OnClick", function() |
||
614 | self:Close(i) |
||
615 | end) |
||
616 | frame:SetScript("OnEnter", function() |
||
617 | StopCounting(self, i) |
||
618 | end) |
||
619 | frame:SetScript("OnLeave", function() |
||
620 | StartCounting(self, i) |
||
621 | end) |
||
622 | frame:SetScript("OnMouseWheel", function() |
||
623 | Scroll(self, frame, arg1 < 0) |
||
624 | end) |
||
625 | if i == 1 then |
||
626 | frame:SetScript("OnUpdate", function() |
||
627 | OnUpdate(self, arg1) |
||
628 | end) |
||
629 | levels[1].lastDirection = "RIGHT" |
||
630 | levels[1].lastVDirection = "DOWN" |
||
631 | else |
||
632 | levels[i].lastDirection = levels[i - 1].lastDirection |
||
633 | levels[i].lastVDirection = levels[i - 1].lastVDirection |
||
634 | end |
||
635 | end |
||
636 | end |
||
637 | return levels[level] |
||
638 | end |
||
639 | |||
640 | local function checkValidate(validateFunc, func, arg1, arg2, arg3) |
||
641 | local text |
||
642 | if arg3 ~= nil then |
||
643 | text = arg3 |
||
644 | elseif arg2 ~= nil then |
||
645 | text = arg2 |
||
646 | else |
||
647 | text = arg1 |
||
648 | end |
||
649 | if not validateFunc(text) then |
||
650 | DEFAULT_CHAT_FRAME:AddMessage("|cffffff7fValidation error: [|r" .. tostring(text) .. "|cffffff7f]|r") |
||
651 | else |
||
652 | func(arg1, arg2, arg3) |
||
653 | end |
||
654 | end |
||
655 | |||
656 | local function validateOptions(options, position, baseOptions, fromPass) |
||
657 | if not baseOptions then |
||
658 | baseOptions = options |
||
659 | end |
||
660 | if type(options) ~= "table" then |
||
661 | return "Options must be a table.", position |
||
662 | end |
||
663 | local kind = options.type |
||
664 | if type(kind) ~= "string" then |
||
665 | return '"type" must be a string.', position |
||
666 | elseif kind ~= "group" and kind ~= "range" and kind ~= "text" and kind ~= "execute" and kind ~= "toggle" and kind ~= "color" and kind ~= "header" then |
||
667 | return '"type" must either be "range", "text", "group", "toggle", "execute", "color", or "header".', position |
||
668 | end |
||
669 | if options.aliases then |
||
670 | if type(options.aliases) ~= "table" and type(options.aliases) ~= "string" then |
||
671 | return '"alias" must be a table or string', position |
||
672 | end |
||
673 | end |
||
674 | if not fromPass then |
||
675 | if kind == "execute" then |
||
676 | if type(options.func) ~= "string" and type(options.func) ~= "function" then |
||
677 | return '"func" must be a string or function', position |
||
678 | end |
||
679 | elseif kind == "range" or kind == "text" or kind == "toggle" then |
||
680 | if type(options.set) ~= "string" and type(options.set) ~= "function" then |
||
681 | return '"set" must be a string or function', position |
||
682 | end |
||
683 | if kind == "text" and options.get == false then |
||
684 | elseif type(options.get) ~= "string" and type(options.get) ~= "function" then |
||
685 | return '"get" must be a string or function', position |
||
686 | end |
||
687 | elseif kind == "group" and options.pass then |
||
688 | if options.pass ~= true then |
||
689 | return '"pass" must be either nil, true, or false', position |
||
690 | end |
||
691 | if not options.func then |
||
692 | if type(options.set) ~= "string" and type(options.set) ~= "function" then |
||
693 | return '"set" must be a string or function', position |
||
694 | end |
||
695 | if type(options.get) ~= "string" and type(options.get) ~= "function" then |
||
696 | return '"get" must be a string or function', position |
||
697 | end |
||
698 | elseif type(options.func) ~= "string" and type(options.func) ~= "function" then |
||
699 | return '"func" must be a string or function', position |
||
700 | end |
||
701 | end |
||
702 | else |
||
703 | if kind == "group" then |
||
704 | return 'cannot have "type" = "group" as a subgroup of a passing group', position |
||
705 | end |
||
706 | end |
||
707 | if options ~= baseOptions then |
||
708 | if kind == "header" then |
||
709 | elseif type(options.desc) ~= "string" then |
||
710 | return '"desc" must be a string', position |
||
711 | elseif string.len(options.desc) == 0 then |
||
712 | return '"desc" cannot be a 0-length string', position |
||
713 | end |
||
714 | end |
||
715 | if options ~= baseOptions or kind == "range" or kind == "text" or kind == "toggle" or kind == "color" then |
||
716 | if options.type == "header" and not options.cmdName and not options.name then |
||
717 | elseif options.cmdName then |
||
718 | if type(options.cmdName) ~= "string" then |
||
719 | return '"cmdName" must be a string or nil', position |
||
720 | elseif string.len(options.cmdName) == 0 then |
||
721 | return '"cmdName" cannot be a 0-length string', position |
||
722 | end |
||
723 | if type(options.guiName) ~= "string" then |
||
724 | if not options.guiNameIsMap then |
||
725 | return '"guiName" must be a string or nil', position |
||
726 | end |
||
727 | elseif string.len(options.guiName) == 0 then |
||
728 | return '"guiName" cannot be a 0-length string', position |
||
729 | end |
||
730 | else |
||
731 | if type(options.name) ~= "string" then |
||
732 | return '"name" must be a string', position |
||
733 | elseif string.len(options.name) == 0 then |
||
734 | return '"name" cannot be a 0-length string', position |
||
735 | end |
||
736 | end |
||
737 | end |
||
738 | if options.guiNameIsMap then |
||
739 | if type(options.guiNameIsMap) ~= "boolean" then |
||
740 | return '"guiNameIsMap" must be a boolean or nil', position |
||
741 | elseif options.type ~= "toggle" then |
||
742 | return 'if "guiNameIsMap" is true, then "type" must be set to \'toggle\'', position |
||
743 | elseif type(options.map) ~= "table" then |
||
744 | return '"map" must be a table', position |
||
745 | end |
||
746 | end |
||
747 | if options.message and type(options.message) ~= "string" then |
||
748 | return '"message" must be a string or nil', position |
||
749 | end |
||
750 | if options.error and type(options.error) ~= "string" then |
||
751 | return '"error" must be a string or nil', position |
||
752 | end |
||
753 | if options.current and type(options.current) ~= "string" then |
||
754 | return '"current" must be a string or nil', position |
||
755 | end |
||
756 | if options.order then |
||
757 | if type(options.order) ~= "number" or (-1 < options.order and options.order < 0.999) then |
||
758 | return '"order" must be a non-zero number or nil', position |
||
759 | end |
||
760 | end |
||
761 | if options.disabled then |
||
762 | if type(options.disabled) ~= "function" and type(options.disabled) ~= "string" and options.disabled ~= true then |
||
763 | return '"disabled" must be a function, string, or boolean', position |
||
764 | end |
||
765 | end |
||
766 | if options.cmdHidden then |
||
767 | if type(options.cmdHidden) ~= "function" and type(options.cmdHidden) ~= "string" and options.cmdHidden ~= true then |
||
768 | return '"cmdHidden" must be a function, string, or boolean', position |
||
769 | end |
||
770 | end |
||
771 | if options.guiHidden then |
||
772 | if type(options.guiHidden) ~= "function" and type(options.guiHidden) ~= "string" and options.guiHidden ~= true then |
||
773 | return '"guiHidden" must be a function, string, or boolean', position |
||
774 | end |
||
775 | end |
||
776 | if options.hidden then |
||
777 | if type(options.hidden) ~= "function" and type(options.hidden) ~= "string" and options.hidden ~= true then |
||
778 | return '"hidden" must be a function, string, or boolean', position |
||
779 | end |
||
780 | end |
||
781 | if kind == "text" then |
||
782 | if type(options.validate) == "table" then |
||
783 | local t = options.validate |
||
784 | local iTable = nil |
||
785 | for k,v in pairs(t) do |
||
786 | if type(k) == "number" then |
||
787 | if iTable == nil then |
||
788 | iTable = true |
||
789 | elseif not iTable then |
||
790 | return '"validate" must either have all keys be indexed numbers or strings', position |
||
791 | elseif k < 1 or k > table.getn(t) then |
||
792 | return '"validate" numeric keys must be indexed properly. >= 1 and <= table.getn', position |
||
793 | end |
||
794 | else |
||
795 | if iTable == nil then |
||
796 | iTable = false |
||
797 | elseif iTable then |
||
798 | return '"validate" must either have all keys be indexed numbers or strings', position |
||
799 | end |
||
800 | end |
||
801 | if type(v) ~= "string" then |
||
802 | return '"validate" values must all be strings', position |
||
803 | end |
||
804 | end |
||
805 | else |
||
806 | if type(options.usage) ~= "string" then |
||
807 | return '"usage" must be a string', position |
||
808 | elseif options.validate and type(options.validate) ~= "string" and type(options.validate) ~= "function" then |
||
809 | return '"validate" must be a string, function, or table', position |
||
810 | end |
||
811 | end |
||
812 | elseif kind == "range" then |
||
813 | if options.min or options.max then |
||
814 | if type(options.min) ~= "number" then |
||
815 | return '"min" must be a number', position |
||
816 | elseif type(options.max) ~= "number" then |
||
817 | return '"max" must be a number', position |
||
818 | elseif options.min >= options.max then |
||
819 | return '"min" must be less than "max"', position |
||
820 | end |
||
821 | end |
||
822 | if options.step then |
||
823 | if type(options.step) ~= "number" then |
||
824 | return '"step" must be a number', position |
||
825 | elseif options.step < 0 then |
||
826 | return '"step" must be nonnegative', position |
||
827 | end |
||
828 | end |
||
829 | if options.isPercent and options.isPercent ~= true then |
||
830 | return '"isPercent" must either be nil, true, or false', position |
||
831 | end |
||
832 | elseif kind == "toggle" then |
||
833 | if options.map then |
||
834 | if type(options.map) ~= "table" then |
||
835 | return '"map" must be a table', position |
||
836 | elseif type(options.map[true]) ~= "string" then |
||
837 | return '"map[true]" must be a string', position |
||
838 | elseif type(options.map[false]) ~= "string" then |
||
839 | return '"map[false]" must be a string', position |
||
840 | end |
||
841 | end |
||
842 | elseif kind == "color" then |
||
843 | if options.hasAlpha and options.hasAlpha ~= true then |
||
844 | return '"hasAlpha" must be nil, true, or false', position |
||
845 | end |
||
846 | elseif kind == "group" then |
||
847 | if options.pass and options.pass ~= true then |
||
848 | return '"pass" must be nil, true, or false', position |
||
849 | end |
||
850 | if type(options.args) ~= "table" then |
||
851 | return '"args" must be a table', position |
||
852 | end |
||
853 | for k,v in pairs(options.args) do |
||
854 | if type(k) ~= "string" then |
||
855 | return '"args" keys must be strings', position |
||
856 | elseif string.find(k, "%s") then |
||
857 | return string.format('"args" keys must not include spaces. %q is not appropriate.', k), position |
||
858 | elseif string.len(k) == 0 then |
||
859 | return '"args" keys must not be 0-length strings.', position |
||
860 | end |
||
861 | if type(v) ~= "table" then |
||
862 | return '"args" values must be tables', position and position .. "." .. k or k |
||
863 | end |
||
864 | local newposition |
||
865 | if position then |
||
866 | newposition = position .. ".args." .. k |
||
867 | else |
||
868 | newposition = "args." .. k |
||
869 | end |
||
870 | local err, pos = validateOptions(v, newposition, baseOptions, options.pass) |
||
871 | if err then |
||
872 | return err, pos |
||
873 | end |
||
874 | end |
||
875 | end |
||
876 | end |
||
877 | |||
878 | local validatedOptions |
||
879 | |||
880 | local values |
||
881 | local mysort_args |
||
882 | local mysort |
||
883 | local othersort |
||
884 | local othersort_validate |
||
885 | |||
886 | local baseFunc, currentLevel |
||
887 | |||
888 | function Dewdrop:FeedAceOptionsTable(options, difference) |
||
889 | self:argCheck(options, 2, "table") |
||
890 | self:argCheck(difference, 3, "nil", "number") |
||
891 | self:assert(currentLevel, "Cannot call `FeedAceOptionsTable' outside of a Dewdrop declaration") |
||
892 | if not difference then |
||
893 | difference = 0 |
||
894 | end |
||
895 | if not validatedOptions then |
||
896 | validatedOptions = {} |
||
897 | end |
||
898 | if not validatedOptions[options] then |
||
899 | local err, position = validateOptions(options) |
||
900 | |||
901 | if err then |
||
902 | if position then |
||
903 | Dewdrop:error(position .. ": " .. err) |
||
904 | else |
||
905 | Dewdrop:error(err) |
||
906 | end |
||
907 | end |
||
908 | |||
909 | validatedOptions[options] = true |
||
910 | end |
||
911 | local level = levels[currentLevel] |
||
912 | self:assert(level, "Improper level given") |
||
913 | if not values then |
||
914 | values = {} |
||
915 | else |
||
916 | for k,v in pairs(values) do |
||
917 | values[k] = nil |
||
918 | end |
||
919 | table.setn(values, 0) |
||
920 | end |
||
921 | |||
922 | local current = level |
||
923 | while current do |
||
924 | if current.num == difference + 1 then |
||
925 | break |
||
926 | end |
||
927 | table.insert(values, current.value) |
||
928 | current = levels[current.num - 1] |
||
929 | end |
||
930 | |||
931 | local realOptions = options |
||
932 | local handler = options.handler |
||
933 | local passTable |
||
934 | local passValue |
||
935 | while table.getn(values) > 0 do |
||
936 | passTable = options.pass and current or nil |
||
937 | local value = table.remove(values) |
||
938 | options = options.args and options.args[value] |
||
939 | if not options then |
||
940 | return |
||
941 | end |
||
942 | handler = options.handler or handler |
||
943 | passValue = passTable and value or nil |
||
944 | end |
||
945 | |||
946 | if options.type == "group" then |
||
947 | for k in pairs(options.args) do |
||
948 | table.insert(values, k) |
||
949 | end |
||
950 | if not mysort then |
||
951 | mysort = function(a, b) |
||
952 | local alpha, bravo = mysort_args[a], mysort_args[b] |
||
953 | local alpha_order = alpha.order or 100 |
||
954 | local bravo_order = bravo.order or 100 |
||
955 | local alpha_name = alpha.guiName or alpha.name |
||
956 | local bravo_name = bravo.guiName or bravo.name |
||
957 | if alpha_order == bravo_order then |
||
958 | if not alpha_name then |
||
959 | return true |
||
960 | elseif not bravo_name then |
||
961 | return false |
||
962 | else |
||
963 | return alpha_name < bravo_name |
||
964 | end |
||
965 | else |
||
966 | if alpha_order < 0 then |
||
967 | if bravo_order > 0 then |
||
968 | return false |
||
969 | end |
||
970 | else |
||
971 | if bravo_order < 0 then |
||
972 | return true |
||
973 | end |
||
974 | end |
||
975 | return alpha_order < bravo_order |
||
976 | end |
||
977 | end |
||
978 | end |
||
979 | mysort_args = options.args |
||
980 | table.sort(values, mysort) |
||
981 | mysort_args = nil |
||
982 | local hasBoth = table.getn(values) >= 1 and (options.args[values[1]].order or 100) > 0 and (options.args[values[table.getn(values)]].order or 100) < 0 |
||
983 | local last_order = 1 |
||
984 | for _,k in ipairs(values) do |
||
985 | local v = options.args[k] |
||
986 | local handler = v.handler or handler |
||
987 | if hasBoth and last_order > 0 and (v.order or 100) < 0 then |
||
988 | hasBoth = false |
||
989 | self:AddLine() |
||
990 | end |
||
991 | local hidden, disabled = v.guiHidden or v.hidden, v.disabled |
||
992 | if type(hidden) == "function" then |
||
993 | hidden = hidden() |
||
994 | elseif type(hidden) == "string" then |
||
995 | hidden = handler[hidden](handler) |
||
996 | end |
||
997 | if not hidden then |
||
998 | if type(disabled) == "function" then |
||
999 | disabled = disabled() |
||
1000 | elseif type(disabled) == "string" then |
||
1001 | disabled = handler[disabled](handler) |
||
1002 | end |
||
1003 | local name = v.guiName or v.name |
||
1004 | local desc = v.desc |
||
1005 | local tooltipTitle, tooltipText |
||
1006 | tooltipTitle = name |
||
1007 | if name ~= desc then |
||
1008 | tooltipText = desc |
||
1009 | end |
||
1010 | if v.type == "toggle" then |
||
1011 | local checked |
||
1012 | if type(v.get) == "function" then |
||
1013 | checked = v.get(passValue) |
||
1014 | else |
||
1015 | if not handler[v.get] then |
||
1016 | Dewdrop:error("Handler %q not available", v.get) |
||
1017 | end |
||
1018 | checked = handler[v.get](handler, passValue) |
||
1019 | end |
||
1020 | local func, arg1, arg2, arg3 |
||
1021 | if type(v.set) == "function" then |
||
1022 | func = v.set |
||
1023 | if passValue ~= nil then |
||
1024 | arg1 = passValue |
||
1025 | arg2 = not checked |
||
1026 | else |
||
1027 | arg1 = not checked |
||
1028 | end |
||
1029 | else |
||
1030 | if not handler[v.set] then |
||
1031 | Dewdrop:error("Handler %q not available", v.set) |
||
1032 | end |
||
1033 | func = handler[v.set] |
||
1034 | arg1 = handler |
||
1035 | if passValue ~= nil then |
||
1036 | arg2 = passValue |
||
1037 | arg3 = not checked |
||
1038 | else |
||
1039 | arg2 = not checked |
||
1040 | end |
||
1041 | end |
||
1042 | if v.guiNameIsMap then |
||
1043 | checked = checked and true or false |
||
1044 | name = string.gsub(tostring(v.map and v.map[checked]), "|c%x%x%x%x%x%x%x%x(.-)|r", "%1") |
||
1045 | checked = nil |
||
1046 | end |
||
1047 | self:AddLine( |
||
1048 | 'text', name, |
||
1049 | 'checked', checked, |
||
1050 | 'func', func, |
||
1051 | 'arg1', arg1, |
||
1052 | 'arg2', arg2, |
||
1053 | 'arg3', arg3, |
||
1054 | 'disabled', disabled, |
||
1055 | 'tooltipTitle', tooltipTitle, |
||
1056 | 'tooltipText', tooltipText |
||
1057 | ) |
||
1058 | elseif v.type == "execute" then |
||
1059 | local func, arg1, arg2 |
||
1060 | if type(v.func) == "function" then |
||
1061 | func = v.func |
||
1062 | arg1 = passValue |
||
1063 | else |
||
1064 | if not handler[v.func] then |
||
1065 | Dewdrop:error("Handler %q not available", v.func) |
||
1066 | end |
||
1067 | func = handler[v.func] |
||
1068 | arg1 = handler |
||
1069 | arg2 = passValue |
||
1070 | end |
||
1071 | self:AddLine( |
||
1072 | 'text', name, |
||
1073 | 'checked', checked, |
||
1074 | 'func', func, |
||
1075 | 'arg1', arg1, |
||
1076 | 'arg2', arg2, |
||
1077 | 'disabled', disabled, |
||
1078 | 'tooltipTitle', tooltipTitle, |
||
1079 | 'tooltipText', tooltipText |
||
1080 | ) |
||
1081 | elseif v.type == "range" then |
||
1082 | local sliderValue |
||
1083 | if type(v.get) == "function" then |
||
1084 | sliderValue = v.get(passValue) |
||
1085 | else |
||
1086 | if not handler[v.get] then |
||
1087 | Dewdrop:error("Handler %q not available", v.get) |
||
1088 | end |
||
1089 | sliderValue = handler[v.get](handler, passValue) |
||
1090 | end |
||
1091 | local sliderFunc, sliderArg1, sliderArg2 |
||
1092 | if type(v.set) == "function" then |
||
1093 | sliderFunc = v.set |
||
1094 | sliderArg1 = passValue |
||
1095 | else |
||
1096 | if not handler[v.set] then |
||
1097 | Dewdrop:error("Handler %q not available", v.set) |
||
1098 | end |
||
1099 | sliderFunc = handler[v.set] |
||
1100 | sliderArg1 = handler |
||
1101 | sliderArg2 = passValue |
||
1102 | end |
||
1103 | self:AddLine( |
||
1104 | 'text', name, |
||
1105 | 'hasArrow', true, |
||
1106 | 'hasSlider', true, |
||
1107 | 'sliderMin', v.min or 0, |
||
1108 | 'sliderMax', v.max or 1, |
||
1109 | 'sliderStep', v.step or 0, |
||
1110 | 'sliderIsPercent', v.isPercent or false, |
||
1111 | 'sliderValue', sliderValue, |
||
1112 | 'sliderFunc', sliderFunc, |
||
1113 | 'sliderArg1', sliderArg1, |
||
1114 | 'sliderArg2', sliderArg2, |
||
1115 | 'disabled', disabled, |
||
1116 | 'tooltipTitle', tooltipTitle, |
||
1117 | 'tooltipText', tooltipText |
||
1118 | ) |
||
1119 | elseif v.type == "color" then |
||
1120 | local r,g,b,a |
||
1121 | if type(v.get) == "function" then |
||
1122 | r,g,b,a = v.get(passValue) |
||
1123 | else |
||
1124 | if not handler[v.get] then |
||
1125 | Dewdrop:error("Handler %q not available", v.get) |
||
1126 | end |
||
1127 | r,g,b,a = handler[v.get](handler, passValue) |
||
1128 | end |
||
1129 | local colorFunc, colorArg1, colorArg2 |
||
1130 | if type(v.set) == "function" then |
||
1131 | colorFunc = v.set |
||
1132 | colorArg1 = passValue |
||
1133 | else |
||
1134 | if not handler[v.set] then |
||
1135 | Dewdrop:error("Handler %q not available", v.set) |
||
1136 | end |
||
1137 | colorFunc = handler[v.set] |
||
1138 | colorArg1 = handler |
||
1139 | colorArg2 = passValue |
||
1140 | end |
||
1141 | self:AddLine( |
||
1142 | 'text', name, |
||
1143 | 'hasArrow', true, |
||
1144 | 'hasColorSwatch', true, |
||
1145 | 'r', r, |
||
1146 | 'g', g, |
||
1147 | 'b', b, |
||
1148 | 'opacity', v.hasAlpha and a or nil, |
||
1149 | 'hasOpacity', v.hasAlpha, |
||
1150 | 'colorFunc', colorFunc, |
||
1151 | 'colorArg1', colorArg1, |
||
1152 | 'colorArg2', colorArg2, |
||
1153 | 'disabled', disabled, |
||
1154 | 'tooltipTitle', tooltipTitle, |
||
1155 | 'tooltipText', tooltipText |
||
1156 | ) |
||
1157 | elseif v.type == "text" then |
||
1158 | if type(v.validate) == "table" then |
||
1159 | self:AddLine( |
||
1160 | 'text', name, |
||
1161 | 'hasArrow', true, |
||
1162 | 'value', k, |
||
1163 | 'disabled', disabled, |
||
1164 | 'tooltipTitle', tooltipTitle, |
||
1165 | 'tooltipText', tooltipText |
||
1166 | ) |
||
1167 | else |
||
1168 | local editBoxText |
||
1169 | if type(v.get) == "function" then |
||
1170 | editBoxText = v.get(passValue) |
||
1171 | elseif v.get == false then |
||
1172 | editBoxText = nil |
||
1173 | else |
||
1174 | if not handler[v.get] then |
||
1175 | Dewdrop:error("Handler %q not available", v.get) |
||
1176 | end |
||
1177 | editBoxText = handler[v.get](handler, passValue) |
||
1178 | end |
||
1179 | local editBoxFunc, editBoxArg1, editBoxArg2 |
||
1180 | if type(v.set) == "function" then |
||
1181 | editBoxFunc = v.set |
||
1182 | editBoxArg1 = passValue |
||
1183 | else |
||
1184 | if not handler[v.set] then |
||
1185 | Dewdrop:error("Handler %q not available", v.set) |
||
1186 | end |
||
1187 | editBoxFunc = handler[v.set] |
||
1188 | editBoxArg1 = handler |
||
1189 | editBoxArg2 = passValue |
||
1190 | end |
||
1191 | |||
1192 | local editBoxValidateFunc, editBoxValidateArg1 |
||
1193 | |||
1194 | if v.validate then |
||
1195 | if type(v.validate) == "function" then |
||
1196 | editBoxValidateFunc = v.validate |
||
1197 | else |
||
1198 | if not handler[v.validate] then |
||
1199 | Dewdrop:error("Handler %q not available", v.validate) |
||
1200 | end |
||
1201 | editBoxValidateFunc = handler[v.validate] |
||
1202 | editBoxValidateArg1 = handler |
||
1203 | end |
||
1204 | end |
||
1205 | |||
1206 | self:AddLine( |
||
1207 | 'text', name, |
||
1208 | 'hasArrow', true, |
||
1209 | 'hasEditBox', true, |
||
1210 | 'editBoxText', editBoxText, |
||
1211 | 'editBoxFunc', editBoxFunc, |
||
1212 | 'editBoxArg1', editBoxArg1, |
||
1213 | 'editBoxArg2', editBoxArg2, |
||
1214 | 'editBoxValidateFunc', editBoxValidateFunc, |
||
1215 | 'editBoxValidateArg1', editBoxValidateArg1, |
||
1216 | 'disabled', disabled, |
||
1217 | 'tooltipTitle', tooltipTitle, |
||
1218 | 'tooltipText', tooltipText |
||
1219 | ) |
||
1220 | end |
||
1221 | elseif v.type == "group" then |
||
1222 | self:AddLine( |
||
1223 | 'text', name, |
||
1224 | 'hasArrow', true, |
||
1225 | 'value', k, |
||
1226 | 'disabled', disabled, |
||
1227 | 'tooltipTitle', tooltipTitle, |
||
1228 | 'tooltipText', tooltipText |
||
1229 | ) |
||
1230 | elseif v.type == "header" then |
||
1231 | if name == "" or not name then |
||
1232 | self:AddLine() |
||
1233 | else |
||
1234 | self:AddLine( |
||
1235 | 'text', name, |
||
1236 | 'isTitle', true |
||
1237 | ) |
||
1238 | end |
||
1239 | end |
||
1240 | end |
||
1241 | last_order = v.order or 100 |
||
1242 | end |
||
1243 | elseif options.type == "text" and type(options.validate) == "table" then |
||
1244 | local current |
||
1245 | if type(options.get) == "function" then |
||
1246 | current = options.get(passValue) |
||
1247 | else |
||
1248 | if not handler[options.get] then |
||
1249 | Dewdrop:error("Handler %q not available", options.get) |
||
1250 | end |
||
1251 | current = handler[options.get](handler, passValue) |
||
1252 | end |
||
1253 | local indexed = true |
||
1254 | for k,v in pairs(options.validate) do |
||
1255 | if type(k) ~= "number" then |
||
1256 | indexed = false |
||
1257 | end |
||
1258 | table.insert(values, k) |
||
1259 | end |
||
1260 | if not indexed then |
||
1261 | if not othersort then |
||
1262 | othersort = function(alpha, bravo) |
||
1263 | return othersort_validate[alpha] < othersort_validate[bravo] |
||
1264 | end |
||
1265 | end |
||
1266 | othersort_validate = options.validate |
||
1267 | table.sort(values, othersort) |
||
1268 | othersort_validate = nil |
||
1269 | end |
||
1270 | for _,k in ipairs(values) do |
||
1271 | local v = options.validate[k] |
||
1272 | if type(k) == "number" then |
||
1273 | k = v |
||
1274 | end |
||
1275 | local func, arg1, arg2 |
||
1276 | if type(options.set) == "function" then |
||
1277 | func = options.set |
||
1278 | if passValue ~= nil then |
||
1279 | arg1 = passValue |
||
1280 | arg2 = k |
||
1281 | else |
||
1282 | arg1 = k |
||
1283 | end |
||
1284 | else |
||
1285 | if not handler[options.set] then |
||
1286 | Dewdrop:error("Handler %q not available", options.set) |
||
1287 | end |
||
1288 | func = handler[options.set] |
||
1289 | arg1 = handler |
||
1290 | if passValue ~= nil then |
||
1291 | arg2 = passValue |
||
1292 | arg3 = k |
||
1293 | else |
||
1294 | arg2 = k |
||
1295 | end |
||
1296 | end |
||
1297 | local checked = (k == current or (type(k) == "string" and type(current) == "string" and string.lower(k) == string.lower(current))) |
||
1298 | self:AddLine( |
||
1299 | 'text', v, |
||
1300 | 'func', not checked and func or nil, |
||
1301 | 'arg1', not checked and arg1 or nil, |
||
1302 | 'arg2', not checked and arg2 or nil, |
||
1303 | 'arg3', not checked and arg3 or nil, |
||
1304 | 'isRadio', true, |
||
1305 | 'checked', checked, |
||
1306 | 'tooltipTitle', options.guiName or options.name, |
||
1307 | 'tooltipText', v |
||
1308 | ) |
||
1309 | end |
||
1310 | for k in pairs(values) do |
||
1311 | values[k] = nil |
||
1312 | end |
||
1313 | table.setn(values, 0) |
||
1314 | else |
||
1315 | self:assert(false) |
||
1316 | end |
||
1317 | return true |
||
1318 | end |
||
1319 | |||
1320 | function Refresh(self, level) |
||
1321 | if type(level) == "number" then |
||
1322 | level = levels[level] |
||
1323 | end |
||
1324 | if not level then |
||
1325 | return |
||
1326 | end |
||
1327 | if baseFunc then |
||
1328 | Clear(self, level) |
||
1329 | currentLevel = level.num |
||
1330 | if type(baseFunc) == "table" then |
||
1331 | if currentLevel == 1 then |
||
1332 | local handler = baseFunc.handler |
||
1333 | if handler then |
||
1334 | local name = tostring(handler) |
||
1335 | if not string.find(name, '^table:') then |
||
1336 | name = string.gsub(name, "|c%x%x%x%x%x%x%x%x(.-)|r", "%1") |
||
1337 | self:AddLine( |
||
1338 | 'text', name, |
||
1339 | 'isTitle', true |
||
1340 | ) |
||
1341 | end |
||
1342 | end |
||
1343 | end |
||
1344 | self:FeedAceOptionsTable(baseFunc) |
||
1345 | if currentLevel == 1 then |
||
1346 | self:AddLine( |
||
1347 | 'text', CLOSE, |
||
1348 | 'closeWhenClicked', true |
||
1349 | ) |
||
1350 | end |
||
1351 | else |
||
1352 | baseFunc(currentLevel, level.value, levels[level.num - 1] and levels[level.num - 1].value, levels[level.num - 2] and levels[level.num - 2].value, levels[level.num - 3] and levels[level.num - 3].value, levels[level.num - 4] and levels[level.num - 4].value) |
||
1353 | end |
||
1354 | currentLevel = nil |
||
1355 | CheckSize(self, level) |
||
1356 | end |
||
1357 | end |
||
1358 | |||
1359 | function Dewdrop:Refresh(level) |
||
1360 | self:argCheck(level, 2, "number") |
||
1361 | Refresh(self, levels[level]) |
||
1362 | end |
||
1363 | |||
1364 | function OpenSlider(self, parent) |
||
1365 | if not sliderFrame then |
||
1366 | sliderFrame = CreateFrame("Frame", nil, UIParent) |
||
1367 | sliderFrame:SetWidth(80) |
||
1368 | sliderFrame:SetHeight(170) |
||
1369 | sliderFrame:SetBackdrop(tmp( |
||
1370 | 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", |
||
1371 | 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", |
||
1372 | 'tile', true, |
||
1373 | 'insets', tmp2( |
||
1374 | 'left', 5, |
||
1375 | 'right', 5, |
||
1376 | 'top', 5, |
||
1377 | 'bottom', 5 |
||
1378 | ), |
||
1379 | 'tileSize', 16, |
||
1380 | 'edgeSize', 16 |
||
1381 | )) |
||
1382 | sliderFrame:SetFrameStrata("FULLSCREEN_DIALOG") |
||
1383 | if sliderFrame.SetTopLevel then |
||
1384 | sliderFrame:SetTopLevel(true) |
||
1385 | end |
||
1386 | sliderFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) |
||
1387 | sliderFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) |
||
1388 | sliderFrame:EnableMouse(true) |
||
1389 | sliderFrame:Hide() |
||
1390 | sliderFrame:SetPoint("CENTER", UIParent, "CENTER") |
||
1391 | local slider = CreateFrame("Slider", nil, sliderFrame) |
||
1392 | sliderFrame.slider = slider |
||
1393 | slider:SetOrientation("VERTICAL") |
||
1394 | slider:SetMinMaxValues(0, 1) |
||
1395 | slider:SetValueStep(0.01) |
||
1396 | slider:SetValue(0.5) |
||
1397 | slider:SetWidth(16) |
||
1398 | slider:SetHeight(128) |
||
1399 | slider:SetPoint("LEFT", sliderFrame, "LEFT", 15, 0) |
||
1400 | slider:SetBackdrop(tmp( |
||
1401 | 'bgFile', "Interface\\Buttons\\UI-SliderBar-Background", |
||
1402 | 'edgeFile', "Interface\\Buttons\\UI-SliderBar-Border", |
||
1403 | 'tile', true, |
||
1404 | 'edgeSize', 8, |
||
1405 | 'tileSize', 8, |
||
1406 | 'insets', tmp2( |
||
1407 | 'left', 3, |
||
1408 | 'right', 3, |
||
1409 | 'top', 3, |
||
1410 | 'bottom', 3 |
||
1411 | ) |
||
1412 | )) |
||
1413 | local texture = slider:CreateTexture() |
||
1414 | slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical") |
||
1415 | local text = slider:CreateFontString(nil, "ARTWORK") |
||
1416 | sliderFrame.topText = text |
||
1417 | text:SetFontObject(GameFontGreenSmall) |
||
1418 | text:SetText("100%") |
||
1419 | text:SetPoint("BOTTOM", slider, "TOP") |
||
1420 | local text = slider:CreateFontString(nil, "ARTWORK") |
||
1421 | sliderFrame.bottomText = text |
||
1422 | text:SetFontObject(GameFontGreenSmall) |
||
1423 | text:SetText("0%") |
||
1424 | text:SetPoint("TOP", slider, "BOTTOM") |
||
1425 | local text = slider:CreateFontString(nil, "ARTWORK") |
||
1426 | sliderFrame.currentText = text |
||
1427 | text:SetFontObject(GameFontHighlightSmall) |
||
1428 | text:SetText("50%") |
||
1429 | text:SetPoint("LEFT", slider, "RIGHT") |
||
1430 | text:SetPoint("RIGHT", sliderFrame, "RIGHT", -6, 0) |
||
1431 | text:SetJustifyH("CENTER") |
||
1432 | local changed = false |
||
1433 | local inside = false |
||
1434 | slider:SetScript("OnValueChanged", function() |
||
1435 | if sliderFrame.changing then |
||
1436 | return |
||
1437 | end |
||
1438 | changed = true |
||
1439 | local done = false |
||
1440 | if sliderFrame.parent then |
||
1441 | if sliderFrame.parent.sliderFunc then |
||
1442 | local min = sliderFrame.parent.sliderMin or 0 |
||
1443 | local max = sliderFrame.parent.sliderMax or 1 |
||
1444 | local step = sliderFrame.parent.sliderStep or (max - min) / 100 |
||
1445 | local a1,a2,a3,a4 = sliderFrame.parent.sliderArg1, sliderFrame.parent.sliderArg2, sliderFrame.parent.sliderArg3, sliderFrame.parent.sliderArg4 |
||
1446 | local value = (1 - slider:GetValue()) * (max - min) + min |
||
1447 | if step > 0 then |
||
1448 | value = math.floor((value - min) / step + 0.5) * step + min |
||
1449 | if value > max then |
||
1450 | value = max |
||
1451 | elseif value < min then |
||
1452 | value = min |
||
1453 | end |
||
1454 | end |
||
1455 | local text |
||
1456 | if a1 == nil then |
||
1457 | text = sliderFrame.parent.sliderFunc(value) |
||
1458 | elseif a2 == nil then |
||
1459 | text = sliderFrame.parent.sliderFunc(a1, value) |
||
1460 | elseif a3 == nil then |
||
1461 | text = sliderFrame.parent.sliderFunc(a1, a2, value) |
||
1462 | elseif a4 == nil then |
||
1463 | text = sliderFrame.parent.sliderFunc(a1, a2, a3, value) |
||
1464 | else |
||
1465 | text = sliderFrame.parent.sliderFunc(a1, a2, a3, a4, value) |
||
1466 | end |
||
1467 | if text then |
||
1468 | sliderFrame.currentText:SetText(text) |
||
1469 | done = true |
||
1470 | end |
||
1471 | end |
||
1472 | end |
||
1473 | if not done then |
||
1474 | local min = sliderFrame.parent.sliderMin or 0 |
||
1475 | local max = sliderFrame.parent.sliderMax or 1 |
||
1476 | local step = sliderFrame.parent.sliderStep or (max - min) / 100 |
||
1477 | local value = (1 - slider:GetValue()) * (max - min) + min |
||
1478 | if step > 0 then |
||
1479 | value = math.floor((value - min) / step + 0.5) * step + min |
||
1480 | if value > max then |
||
1481 | value = max |
||
1482 | elseif value < min then |
||
1483 | value = min |
||
1484 | end |
||
1485 | end |
||
1486 | if sliderFrame.parent.sliderIsPercent then |
||
1487 | sliderFrame.currentText:SetText(string.format("%.0f%%", value * 100)) |
||
1488 | else |
||
1489 | if step < 0.1 then |
||
1490 | sliderFrame.currentText:SetText(string.format("%.2f", value)) |
||
1491 | elseif step < 1 then |
||
1492 | sliderFrame.currentText:SetText(string.format("%.1f", value)) |
||
1493 | else |
||
1494 | sliderFrame.currentText:SetText(string.format("%.0f", value)) |
||
1495 | end |
||
1496 | end |
||
1497 | end |
||
1498 | end) |
||
1499 | sliderFrame:SetScript("OnEnter", function() |
||
1500 | StopCounting(self, sliderFrame.level) |
||
1501 | end) |
||
1502 | sliderFrame:SetScript("OnLeave", function() |
||
1503 | StartCounting(self, sliderFrame.level) |
||
1504 | end) |
||
1505 | slider:SetScript("OnMouseDown", function() |
||
1506 | sliderFrame.mouseDown = true |
||
1507 | end) |
||
1508 | slider:SetScript("OnMouseUp", function() |
||
1509 | sliderFrame.mouseDown = false |
||
1510 | if changed and not inside then |
||
1511 | local parent = sliderFrame.parent |
||
1512 | for i = 1, sliderFrame.level - 1 do |
||
1513 | Refresh(self, levels[i]) |
||
1514 | end |
||
1515 | OpenSlider(self, parent) |
||
1516 | end |
||
1517 | end) |
||
1518 | slider:SetScript("OnEnter", function() |
||
1519 | inside = true |
||
1520 | StopCounting(self, sliderFrame.level) |
||
1521 | end) |
||
1522 | slider:SetScript("OnLeave", function() |
||
1523 | inside = false |
||
1524 | StartCounting(self, sliderFrame.level) |
||
1525 | if changed and not sliderFrame.mouseDown then |
||
1526 | local parent = sliderFrame.parent |
||
1527 | for i = 1, sliderFrame.level - 1 do |
||
1528 | Refresh(self, levels[i]) |
||
1529 | end |
||
1530 | OpenSlider(self, parent) |
||
1531 | end |
||
1532 | end) |
||
1533 | end |
||
1534 | sliderFrame.parent = parent |
||
1535 | sliderFrame.level = parent.level.num + 1 |
||
1536 | sliderFrame.parentValue = parent.level.value |
||
1537 | sliderFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3) |
||
1538 | sliderFrame.slider:SetFrameLevel(sliderFrame:GetFrameLevel() + 1) |
||
1539 | sliderFrame.changing = true |
||
1540 | if not parent.sliderMin or not parent.sliderMax then |
||
1541 | return |
||
1542 | end |
||
1543 | if not parent.sliderValue then |
||
1544 | parent.sliderValue = (parent.sliderMin + parent.sliderMax) / 2 |
||
1545 | end |
||
1546 | sliderFrame.slider:SetValue(1 - (parent.sliderValue - parent.sliderMin) / (parent.sliderMax - parent.sliderMin)) |
||
1547 | sliderFrame.changing = false |
||
1548 | sliderFrame.bottomText:SetText(parent.sliderMinText or "0") |
||
1549 | sliderFrame.topText:SetText(parent.sliderMaxText or "1") |
||
1550 | local text |
||
1551 | if parent.sliderFunc then |
||
1552 | local a1,a2,a3,a4 = parent.sliderArg1, parent.sliderArg2, parent.sliderArg3, parent.sliderArg4 |
||
1553 | if a1 == nil then |
||
1554 | text = parent.sliderFunc(parent.sliderValue) |
||
1555 | elseif a2 == nil then |
||
1556 | text = parent.sliderFunc(a1, parent.sliderValue) |
||
1557 | elseif a3 == nil then |
||
1558 | text = parent.sliderFunc(a1, a2, parent.sliderValue) |
||
1559 | elseif a4 == nil then |
||
1560 | text = parent.sliderFunc(a1, a2, a3, parent.sliderValue) |
||
1561 | else |
||
1562 | text = parent.sliderFunc(a1, a2, a3, a4, parent.sliderValue) |
||
1563 | end |
||
1564 | end |
||
1565 | if text then |
||
1566 | sliderFrame.currentText:SetText(text) |
||
1567 | elseif parent.sliderIsPercent then |
||
1568 | sliderFrame.currentText:SetText(string.format("%.0f%%", parent.sliderValue * 100)) |
||
1569 | else |
||
1570 | sliderFrame.currentText:SetText(parent.sliderValue) |
||
1571 | end |
||
1572 | |||
1573 | local level = parent.level |
||
1574 | sliderFrame:Show() |
||
1575 | sliderFrame:ClearAllPoints() |
||
1576 | if level.lastDirection == "RIGHT" then |
||
1577 | if level.lastVDirection == "DOWN" then |
||
1578 | sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) |
||
1579 | else |
||
1580 | sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) |
||
1581 | end |
||
1582 | else |
||
1583 | if level.lastVDirection == "DOWN" then |
||
1584 | sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) |
||
1585 | else |
||
1586 | sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) |
||
1587 | end |
||
1588 | end |
||
1589 | local dirty |
||
1590 | if level.lastDirection == "RIGHT" then |
||
1591 | if sliderFrame:GetRight() > GetScreenWidth() then |
||
1592 | level.lastDirection = "LEFT" |
||
1593 | dirty = true |
||
1594 | end |
||
1595 | elseif sliderFrame:GetLeft() < 0 then |
||
1596 | level.lastDirection = "RIGHT" |
||
1597 | dirty = true |
||
1598 | end |
||
1599 | if level.lastVDirection == "DOWN" then |
||
1600 | if sliderFrame:GetBottom() < 0 then |
||
1601 | level.lastVDirection = "UP" |
||
1602 | dirty = true |
||
1603 | end |
||
1604 | elseif sliderFrame:GetTop() > GetScreenWidth() then |
||
1605 | level.lastVDirection = "DOWN" |
||
1606 | dirty = true |
||
1607 | end |
||
1608 | if dirty then |
||
1609 | sliderFrame:ClearAllPoints() |
||
1610 | if level.lastDirection == "RIGHT" then |
||
1611 | if level.lastVDirection == "DOWN" then |
||
1612 | sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) |
||
1613 | else |
||
1614 | sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) |
||
1615 | end |
||
1616 | else |
||
1617 | if level.lastVDirection == "DOWN" then |
||
1618 | sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) |
||
1619 | else |
||
1620 | sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) |
||
1621 | end |
||
1622 | end |
||
1623 | end |
||
1624 | local left, bottom = sliderFrame:GetLeft(), sliderFrame:GetBottom() |
||
1625 | sliderFrame:ClearAllPoints() |
||
1626 | sliderFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) |
||
1627 | if mod(level.num, 5) == 0 then |
||
1628 | local left, bottom = level:GetLeft(), level:GetBottom() |
||
1629 | level:ClearAllPoints() |
||
1630 | level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) |
||
1631 | end |
||
1632 | end |
||
1633 | |||
1634 | function OpenEditBox(self, parent) |
||
1635 | if not editBoxFrame then |
||
1636 | editBoxFrame = CreateFrame("Frame", nil, UIParent) |
||
1637 | editBoxFrame:SetWidth(200) |
||
1638 | editBoxFrame:SetHeight(40) |
||
1639 | editBoxFrame:SetBackdrop(tmp( |
||
1640 | 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background", |
||
1641 | 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border", |
||
1642 | 'tile', true, |
||
1643 | 'insets', tmp2( |
||
1644 | 'left', 5, |
||
1645 | 'right', 5, |
||
1646 | 'top', 5, |
||
1647 | 'bottom', 5 |
||
1648 | ), |
||
1649 | 'tileSize', 16, |
||
1650 | 'edgeSize', 16 |
||
1651 | )) |
||
1652 | editBoxFrame:SetFrameStrata("FULLSCREEN_DIALOG") |
||
1653 | if editBoxFrame.SetTopLevel then |
||
1654 | editBoxFrame:SetTopLevel(true) |
||
1655 | end |
||
1656 | editBoxFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b) |
||
1657 | editBoxFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) |
||
1658 | editBoxFrame:EnableMouse(true) |
||
1659 | editBoxFrame:Hide() |
||
1660 | editBoxFrame:SetPoint("CENTER", UIParent, "CENTER") |
||
1661 | |||
1662 | local editBox = CreateFrame("EditBox", nil, editBoxFrame) |
||
1663 | editBoxFrame.editBox = editBox |
||
1664 | editBox:SetFontObject(ChatFontNormal) |
||
1665 | editBox:SetWidth(160) |
||
1666 | editBox:SetHeight(13) |
||
1667 | editBox:SetPoint("CENTER", editBoxFrame, "CENTER", 0, 0) |
||
1668 | |||
1669 | local left = editBox:CreateTexture(nil, "BACKGROUND") |
||
1670 | left:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Left") |
||
1671 | left:SetTexCoord(0, 100 / 256, 0, 1) |
||
1672 | left:SetWidth(100) |
||
1673 | left:SetHeight(32) |
||
1674 | left:SetPoint("LEFT", editBox, "LEFT", -10, 0) |
||
1675 | local right = editBox:CreateTexture(nil, "BACKGROUND") |
||
1676 | right:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Right") |
||
1677 | right:SetTexCoord(156/256, 1, 0, 1) |
||
1678 | right:SetWidth(100) |
||
1679 | right:SetHeight(32) |
||
1680 | right:SetPoint("RIGHT", editBox, "RIGHT", 10, 0) |
||
1681 | |||
1682 | editBox:SetScript("OnEnterPressed", function() |
||
1683 | if editBoxFrame.parent and editBoxFrame.parent.editBoxValidateFunc then |
||
1684 | local a1,a2,a3,a4 = editBoxFrame.parent.editBoxValidateArg1, editBoxFrame.parent.editBoxValidateArg2, editBoxFrame.parent.editBoxValidateArg3, editBoxFrame.parent.editBoxValidateArg4 |
||
1685 | |||
1686 | local result |
||
1687 | if a1 == nil then |
||
1688 | result = editBoxFrame.parent.editBoxValidateFunc(editBox:GetText() or "") |
||
1689 | elseif a2 == nil then |
||
1690 | result = editBoxFrame.parent.editBoxValidateFunc(a1, editBox:GetText() or "") |
||
1691 | elseif a3 == nil then |
||
1692 | result = editBoxFrame.parent.editBoxValidateFunc(a1, a2, editBox:GetText() or "") |
||
1693 | elseif a4 == nil then |
||
1694 | result = editBoxFrame.parent.editBoxValidateFunc(a1, a2, a3, editBox:GetText() or "") |
||
1695 | else |
||
1696 | result = editBoxFrame.parent.editBoxValidateFunc(a1, a2, a3, a4, editBox:GetText() or "") |
||
1697 | end |
||
1698 | if not result then |
||
1699 | message("Validation error: [" .. tostring(text) .. "]") |
||
1700 | return |
||
1701 | end |
||
1702 | end |
||
1703 | if editBoxFrame.parent and editBoxFrame.parent.editBoxFunc then |
||
1704 | local a1,a2,a3,a4 = editBoxFrame.parent.editBoxArg1, editBoxFrame.parent.editBoxArg2, editBoxFrame.parent.editBoxArg3, editBoxFrame.parent.editBoxArg4 |
||
1705 | if a1 == nil then |
||
1706 | editBoxFrame.parent.editBoxFunc(editBox:GetText() or "") |
||
1707 | elseif a2 == nil then |
||
1708 | editBoxFrame.parent.editBoxFunc(a1, editBox:GetText() or "") |
||
1709 | elseif a3 == nil then |
||
1710 | editBoxFrame.parent.editBoxFunc(a1, a2, editBox:GetText() or "") |
||
1711 | elseif a4 == nil then |
||
1712 | editBoxFrame.parent.editBoxFunc(a1, a2, a3, editBox:GetText() or "") |
||
1713 | else |
||
1714 | editBoxFrame.parent.editBoxFunc(a1, a2, a3, a4, editBox:GetText() or "") |
||
1715 | end |
||
1716 | end |
||
1717 | self:Close(editBoxFrame.level) |
||
1718 | for i = 1, editBoxFrame.level - 1 do |
||
1719 | Refresh(self, levels[i]) |
||
1720 | end |
||
1721 | end) |
||
1722 | editBox:SetScript("OnEscapePressed", function() |
||
1723 | self:Close(editBoxFrame.level) |
||
1724 | end) |
||
1725 | local changing = false |
||
1726 | local skipNext = false |
||
1727 | |||
1728 | function editBox:SpecialSetText(text) |
||
1729 | local oldText = editBox:GetText() or "" |
||
1730 | if not text then |
||
1731 | text = "" |
||
1732 | end |
||
1733 | if text ~= oldText then |
||
1734 | changing = true |
||
1735 | self:SetText(text) |
||
1736 | changing = false |
||
1737 | skipNext = true |
||
1738 | end |
||
1739 | end |
||
1740 | |||
1741 | editBox:SetScript("OnTextChanged", function() |
||
1742 | if skipNext then |
||
1743 | skipNext = false |
||
1744 | elseif not changing and editBoxFrame.parent and editBoxFrame.parent.editBoxChangeFunc then |
||
1745 | local a1,a2,a3,a4 = editBoxFrame.parent.editBoxChangeArg1, editBoxFrame.parent.editBoxChangeArg2, editBoxFrame.parent.editBoxChangeArg3, editBoxFrame.parent.editBoxChangeArg4 |
||
1746 | local text |
||
1747 | if a1 == nil then |
||
1748 | text = editBoxFrame.parent.editBoxChangeFunc(editBox:GetText() or "") |
||
1749 | elseif a2 == nil then |
||
1750 | text = editBoxFrame.parent.editBoxChangeFunc(a1, editBox:GetText() or "") |
||
1751 | elseif a3 == nil then |
||
1752 | text = editBoxFrame.parent.editBoxChangeFunc(a1, a2, editBox:GetText() or "") |
||
1753 | elseif a4 == nil then |
||
1754 | text = editBoxFrame.parent.editBoxChangeFunc(a1, a2, a3, editBox:GetText() or "") |
||
1755 | else |
||
1756 | text = editBoxFrame.parent.editBoxChangeFunc(a1, a2, a3, a4, editBox:GetText() or "") |
||
1757 | end |
||
1758 | if text then |
||
1759 | editBox:SpecialSetText(text) |
||
1760 | end |
||
1761 | end |
||
1762 | end) |
||
1763 | editBoxFrame:SetScript("OnEnter", function() |
||
1764 | StopCounting(self, editBoxFrame.level) |
||
1765 | end) |
||
1766 | editBoxFrame:SetScript("OnLeave", function() |
||
1767 | StartCounting(self, editBoxFrame.level) |
||
1768 | end) |
||
1769 | editBox:SetScript("OnEnter", function() |
||
1770 | StopCounting(self, editBoxFrame.level) |
||
1771 | end) |
||
1772 | editBox:SetScript("OnLeave", function() |
||
1773 | StartCounting(self, editBoxFrame.level) |
||
1774 | end) |
||
1775 | end |
||
1776 | editBoxFrame.parent = parent |
||
1777 | editBoxFrame.level = parent.level.num + 1 |
||
1778 | editBoxFrame.parentValue = parent.level.value |
||
1779 | editBoxFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3) |
||
1780 | editBoxFrame.editBox:SetFrameLevel(editBoxFrame:GetFrameLevel() + 1) |
||
1781 | editBoxFrame.editBox:SpecialSetText(parent.editBoxText) |
||
1782 | |||
1783 | local level = parent.level |
||
1784 | editBoxFrame:Show() |
||
1785 | editBoxFrame:ClearAllPoints() |
||
1786 | if level.lastDirection == "RIGHT" then |
||
1787 | if level.lastVDirection == "DOWN" then |
||
1788 | editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) |
||
1789 | else |
||
1790 | editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) |
||
1791 | end |
||
1792 | else |
||
1793 | if level.lastVDirection == "DOWN" then |
||
1794 | editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) |
||
1795 | else |
||
1796 | editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) |
||
1797 | end |
||
1798 | end |
||
1799 | local dirty |
||
1800 | if level.lastDirection == "RIGHT" then |
||
1801 | if editBoxFrame:GetRight() > GetScreenWidth() then |
||
1802 | level.lastDirection = "LEFT" |
||
1803 | dirty = true |
||
1804 | end |
||
1805 | elseif editBoxFrame:GetLeft() < 0 then |
||
1806 | level.lastDirection = "RIGHT" |
||
1807 | dirty = true |
||
1808 | end |
||
1809 | if level.lastVDirection == "DOWN" then |
||
1810 | if editBoxFrame:GetBottom() < 0 then |
||
1811 | level.lastVDirection = "UP" |
||
1812 | dirty = true |
||
1813 | end |
||
1814 | elseif editBoxFrame:GetTop() > GetScreenWidth() then |
||
1815 | level.lastVDirection = "DOWN" |
||
1816 | dirty = true |
||
1817 | end |
||
1818 | if dirty then |
||
1819 | editBoxFrame:ClearAllPoints() |
||
1820 | if level.lastDirection == "RIGHT" then |
||
1821 | if level.lastVDirection == "DOWN" then |
||
1822 | editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10) |
||
1823 | else |
||
1824 | editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10) |
||
1825 | end |
||
1826 | else |
||
1827 | if level.lastVDirection == "DOWN" then |
||
1828 | editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10) |
||
1829 | else |
||
1830 | editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10) |
||
1831 | end |
||
1832 | end |
||
1833 | end |
||
1834 | local left, bottom = editBoxFrame:GetLeft(), editBoxFrame:GetBottom() |
||
1835 | editBoxFrame:ClearAllPoints() |
||
1836 | editBoxFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) |
||
1837 | if mod(level.num, 5) == 0 then |
||
1838 | local left, bottom = level:GetLeft(), level:GetBottom() |
||
1839 | level:ClearAllPoints() |
||
1840 | level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom) |
||
1841 | end |
||
1842 | end |
||
1843 | |||
1844 | function Dewdrop:IsOpen(parent) |
||
1845 | self:argCheck(parent, 2, "table", "nil") |
||
1846 | return levels[1] and levels[1]:IsShown() and (not parent or parent == levels[1].parent or parent == levels[1]:GetParent()) |
||
1847 | end |
||
1848 | |||
1849 | function Dewdrop:GetOpenedParent() |
||
1850 | return (levels[1] and levels[1]:IsShown()) and (levels[1].parent or levels[1]:GetParent()) |
||
1851 | end |
||
1852 | |||
1853 | function Open(self, parent, func, level, value, point, relativePoint, cursorX, cursorY) |
||
1854 | self:Close(level) |
||
1855 | if DewdropLib then |
||
1856 | local d = DewdropLib:GetInstance('1.0') |
||
1857 | local ret, val = pcall(d, IsOpen, d) |
||
1858 | if ret and val then |
||
1859 | DewdropLib:GetInstance('1.0'):Close() |
||
1860 | end |
||
1861 | end |
||
1862 | parent:GetCenter() |
||
1863 | local frame = AcquireLevel(self, level) |
||
1864 | if level == 1 then |
||
1865 | frame.lastDirection = "RIGHT" |
||
1866 | frame.lastVDirection = "DOWN" |
||
1867 | else |
||
1868 | frame.lastDirection = levels[level - 1].lastDirection |
||
1869 | frame.lastVDirection = levels[level - 1].lastVDirection |
||
1870 | end |
||
1871 | frame:SetFrameStrata("FULLSCREEN_DIALOG") |
||
1872 | frame:ClearAllPoints() |
||
1873 | frame.parent = parent |
||
1874 | frame:SetPoint("LEFT", UIParent, "RIGHT", 10000, 0) |
||
1875 | frame:Show() |
||
1876 | if level == 1 then |
||
1877 | baseFunc = func |
||
1878 | end |
||
1879 | levels[level].value = value |
||
1880 | relativePoint = relativePoint or point |
||
1881 | Refresh(self, levels[level]) |
||
1882 | if point or (cursorX and cursorY) then |
||
1883 | frame:ClearAllPoints() |
||
1884 | if cursorX and cursorY then |
||
1885 | local curX, curY = GetScaledCursorPosition() |
||
1886 | if curY < GetScreenHeight() / 2 then |
||
1887 | point, relativePoint = "BOTTOM", "BOTTOM" |
||
1888 | else |
||
1889 | point, relativePoint = "TOP", "TOP" |
||
1890 | end |
||
1891 | if curX < GetScreenWidth() / 2 then |
||
1892 | point, relativePoint = point .. "LEFT", relativePoint .. "RIGHT" |
||
1893 | else |
||
1894 | point, relativePoint = point .. "RIGHT", relativePoint .. "LEFT" |
||
1895 | end |
||
1896 | end |
||
1897 | frame:SetPoint(point, parent, relativePoint) |
||
1898 | if cursorX and cursorY then |
||
1899 | local left = frame:GetLeft() |
||
1900 | local width = frame:GetWidth() |
||
1901 | local bottom = frame:GetBottom() |
||
1902 | local height = frame:GetHeight() |
||
1903 | local curX, curY = GetScaledCursorPosition() |
||
1904 | frame:ClearAllPoints() |
||
1905 | relativePoint = relativePoint or point |
||
1906 | if point == "BOTTOM" or point == "TOP" then |
||
1907 | if curX < GetScreenWidth() / 2 then |
||
1908 | point = point .. "LEFT" |
||
1909 | else |
||
1910 | point = point .. "RIGHT" |
||
1911 | end |
||
1912 | elseif point == "CENTER" then |
||
1913 | if curX < GetScreenWidth() / 2 then |
||
1914 | point = "LEFT" |
||
1915 | else |
||
1916 | point = "RIGHT" |
||
1917 | end |
||
1918 | end |
||
1919 | local xOffset, yOffset = 0, 0 |
||
1920 | if curY > GetScreenHeight() / 2 then |
||
1921 | yOffset = -height |
||
1922 | end |
||
1923 | if curX > GetScreenWidth() / 2 then |
||
1924 | xOffset = -width |
||
1925 | end |
||
1926 | frame:SetPoint(point, parent, relativePoint, curX - left + xOffset, curY - bottom + yOffset) |
||
1927 | if level == 1 then |
||
1928 | frame.lastDirection = "RIGHT" |
||
1929 | end |
||
1930 | elseif cursorX then |
||
1931 | local left = frame:GetLeft() |
||
1932 | local width = frame:GetWidth() |
||
1933 | local curX, curY = GetScaledCursorPosition() |
||
1934 | frame:ClearAllPoints() |
||
1935 | relativePoint = relativePoint or point |
||
1936 | if point == "BOTTOM" or point == "TOP" then |
||
1937 | if curX < GetScreenWidth() / 2 then |
||
1938 | point = point .. "LEFT" |
||
1939 | else |
||
1940 | point = point .. "RIGHT" |
||
1941 | end |
||
1942 | elseif point == "CENTER" then |
||
1943 | if curX < GetScreenWidth() / 2 then |
||
1944 | point = "LEFT" |
||
1945 | else |
||
1946 | point = "RIGHT" |
||
1947 | end |
||
1948 | end |
||
1949 | frame:SetPoint(point, parent, relativePoint, curX - left - width / 2, 0) |
||
1950 | if level == 1 then |
||
1951 | frame.lastDirection = "RIGHT" |
||
1952 | end |
||
1953 | elseif cursorY then |
||
1954 | local bottom = frame:GetBottom() |
||
1955 | local height = frame:GetHeight() |
||
1956 | local curX, curY = GetScaledCursorPosition() |
||
1957 | frame:ClearAllPoints() |
||
1958 | relativePoint = relativePoint or point |
||
1959 | if point == "LEFT" or point == "RIGHT" then |
||
1960 | if curX < GetScreenHeight() / 2 then |
||
1961 | point = point .. "BOTTOM" |
||
1962 | else |
||
1963 | point = point .. "TOP" |
||
1964 | end |
||
1965 | elseif point == "CENTER" then |
||
1966 | if curX < GetScreenHeight() / 2 then |
||
1967 | point = "BOTTOM" |
||
1968 | else |
||
1969 | point = "TOP" |
||
1970 | end |
||
1971 | end |
||
1972 | frame:SetPoint(point, parent, relativePoint, 0, curY - bottom - height / 2) |
||
1973 | if level == 1 then |
||
1974 | frame.lastDirection = "DOWN" |
||
1975 | end |
||
1976 | end |
||
1977 | if (strsub(point, 1, 3) ~= strsub(relativePoint, 1, 3)) then |
||
1978 | if frame:GetBottom() < 0 then |
||
1979 | local point, parent, relativePoint, x, y = frame:GetPoint(1) |
||
1980 | local change = GetScreenHeight() - frame:GetTop() |
||
1981 | local otherChange = -frame:GetBottom() |
||
1982 | if otherChange < change then |
||
1983 | change = otherChange |
||
1984 | end |
||
1985 | frame:SetPoint(point, parent, relativePoint, x, y + change) |
||
1986 | elseif frame:GetTop() > GetScreenHeight() then |
||
1987 | local point, parent, relativePoint, x, y = frame:GetPoint(1) |
||
1988 | local change = GetScreenHeight() - frame:GetTop() |
||
1989 | local otherChange = -frame:GetBottom() |
||
1990 | if otherChange < change then |
||
1991 | change = otherChange |
||
1992 | end |
||
1993 | frame:SetPoint(point, parent, relativePoint, x, y + change) |
||
1994 | end |
||
1995 | end |
||
1996 | end |
||
1997 | CheckDualMonitor(self, frame) |
||
1998 | StartCounting(self, level) |
||
1999 | end |
||
2000 | |||
2001 | function Dewdrop:IsRegistered(parent) |
||
2002 | self:argCheck(parent, 2, "table") |
||
2003 | return not not self.registry[parent] |
||
2004 | end |
||
2005 | |||
2006 | function Dewdrop:Register(parent, k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) |
||
2007 | self:argCheck(parent, 2, "table") |
||
2008 | if self.registry[parent] then |
||
2009 | self:Unregister(parent) |
||
2010 | end |
||
2011 | local info = new(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) |
||
2012 | if type(info.children) == "table" then |
||
2013 | local err, position = validateOptions(info.children) |
||
2014 | |||
2015 | if err then |
||
2016 | if position then |
||
2017 | Dewdrop:error(position .. ": " .. err) |
||
2018 | else |
||
2019 | Dewdrop:error(err) |
||
2020 | end |
||
2021 | end |
||
2022 | end |
||
2023 | self.registry[parent] = info |
||
2024 | if not info.dontHook and not self.onceRegistered[parent] then |
||
2025 | if parent:HasScript("OnMouseUp") then |
||
2026 | local script = parent:GetScript("OnMouseUp") |
||
2027 | parent:SetScript("OnMouseUp", function() |
||
2028 | if script then |
||
2029 | script() |
||
2030 | end |
||
2031 | if arg1 == "RightButton" and self.registry[parent] then |
||
2032 | if self:IsOpen(parent) then |
||
2033 | self:Close() |
||
2034 | else |
||
2035 | self:Open(parent) |
||
2036 | end |
||
2037 | end |
||
2038 | end) |
||
2039 | end |
||
2040 | if parent:HasScript("OnMouseDown") then |
||
2041 | local script = parent:GetScript("OnMouseDown") |
||
2042 | parent:SetScript("OnMouseDown", function() |
||
2043 | if script then |
||
2044 | script() |
||
2045 | end |
||
2046 | if self.registry[parent] then |
||
2047 | self:Close() |
||
2048 | end |
||
2049 | end) |
||
2050 | end |
||
2051 | end |
||
2052 | self.onceRegistered[parent] = true |
||
2053 | end |
||
2054 | |||
2055 | function Dewdrop:Unregister(parent) |
||
2056 | self:argCheck(parent, 2, "table") |
||
2057 | self.registry[parent] = nil |
||
2058 | end |
||
2059 | |||
2060 | function Dewdrop:Open(parent, k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) |
||
2061 | self:argCheck(parent, 2, "table") |
||
2062 | local info |
||
2063 | if type(k1) == "table" and k1[0] and k1.IsFrameType and self.registry[k1] then |
||
2064 | info = tmp() |
||
2065 | for k,v in pairs(self.registry[k1]) do |
||
2066 | info[k] = v |
||
2067 | end |
||
2068 | else |
||
2069 | info = tmp(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) |
||
2070 | if self.registry[parent] then |
||
2071 | for k,v in pairs(self.registry[parent]) do |
||
2072 | if info[k] == nil then |
||
2073 | info[k] = v |
||
2074 | end |
||
2075 | end |
||
2076 | end |
||
2077 | end |
||
2078 | local point = info.point |
||
2079 | local relativePoint = info.relativePoint |
||
2080 | local cursorX = info.cursorX |
||
2081 | local cursorY = info.cursorY |
||
2082 | if type(point) == "function" then |
||
2083 | local b |
||
2084 | point, b = point(parent) |
||
2085 | if b then |
||
2086 | relativePoint = b |
||
2087 | end |
||
2088 | end |
||
2089 | if type(relativePoint) == "function" then |
||
2090 | relativePoint = relativePoint(parent) |
||
2091 | end |
||
2092 | Open(self, parent, info.children, 1, nil, point, relativePoint, cursorX, cursorY) |
||
2093 | end |
||
2094 | |||
2095 | function Clear(self, level) |
||
2096 | if level then |
||
2097 | if level.buttons then |
||
2098 | for i = table.getn(level.buttons), 1, -1 do |
||
2099 | ReleaseButton(self, level, i) |
||
2100 | end |
||
2101 | end |
||
2102 | end |
||
2103 | end |
||
2104 | |||
2105 | function Dewdrop:Close(level) |
||
2106 | if DropDownList1:IsShown() then |
||
2107 | DropDownList1:Hide() |
||
2108 | end |
||
2109 | if DewdropLib then |
||
2110 | local d = DewdropLib:GetInstance('1.0') |
||
2111 | local ret, val = pcall(d, IsOpen, d) |
||
2112 | if ret and val then |
||
2113 | DewdropLib:GetInstance('1.0'):Close() |
||
2114 | end |
||
2115 | end |
||
2116 | self:argCheck(level, 2, "number", "nil") |
||
2117 | if not level then |
||
2118 | level = 1 |
||
2119 | end |
||
2120 | if level == 1 and levels[level] then |
||
2121 | levels[level].parented = false |
||
2122 | end |
||
2123 | if sliderFrame and sliderFrame.level >= level then |
||
2124 | sliderFrame:Hide() |
||
2125 | end |
||
2126 | if editBoxFrame and editBoxFrame.level >= level then |
||
2127 | editBoxFrame:Hide() |
||
2128 | end |
||
2129 | for i = level, table.getn(levels) do |
||
2130 | Clear(self, levels[level]) |
||
2131 | levels[level]:Hide() |
||
2132 | levels[i]:ClearAllPoints() |
||
2133 | levels[i]:SetPoint("CENTER", UIParent, "CENTER") |
||
2134 | end |
||
2135 | end |
||
2136 | |||
2137 | function Dewdrop:AddLine(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) |
||
2138 | local info = tmp(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20) |
||
2139 | local level = info.level or currentLevel |
||
2140 | info.level = nil |
||
2141 | local button = AcquireButton(self, level) |
||
2142 | if not next(info) then |
||
2143 | info.disabled = true |
||
2144 | end |
||
2145 | button.disabled = info.isTitle or info.notClickable or info.disabled |
||
2146 | button.isTitle = info.isTitle |
||
2147 | button.notClickable = info.notClickable |
||
2148 | if button.isTitle then |
||
2149 | button.text:SetFontObject(GameFontNormalSmall) |
||
2150 | elseif button.notClickable then |
||
2151 | button.text:SetFontObject(GameFontHighlightSmall) |
||
2152 | elseif button.disabled then |
||
2153 | button.text:SetFontObject(GameFontDisableSmall) |
||
2154 | else |
||
2155 | button.text:SetFontObject(GameFontHighlightSmall) |
||
2156 | end |
||
2157 | if info.disabled then |
||
2158 | button.arrow:SetDesaturated(true) |
||
2159 | button.check:SetDesaturated(true) |
||
2160 | else |
||
2161 | button.arrow:SetDesaturated(false) |
||
2162 | button.check:SetDesaturated(false) |
||
2163 | end |
||
2164 | if info.textR and info.textG and info.textB then |
||
2165 | button.textR = info.textR |
||
2166 | button.textG = info.textG |
||
2167 | button.textB = info.textB |
||
2168 | button.text:SetTextColor(button.textR, button.textG, button.textB) |
||
2169 | else |
||
2170 | button.text:SetTextColor(button.text:GetFontObject():GetTextColor()) |
||
2171 | end |
||
2172 | button.notCheckable = info.notCheckable |
||
2173 | button.text:SetPoint("LEFT", button, "LEFT", button.notCheckable and 0 or 24, 0) |
||
2174 | button.checked = not info.notCheckable and info.checked |
||
2175 | button.isRadio = not info.notCheckable and info.isRadio |
||
2176 | if info.isRadio then |
||
2177 | button.check:Show() |
||
2178 | button.check:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton") |
||
2179 | if button.checked then |
||
2180 | button.check:SetTexCoord(0.25, 0.5, 0, 1) |
||
2181 | button.check:SetVertexColor(1, 1, 1, 1) |
||
2182 | else |
||
2183 | button.check:SetTexCoord(0, 0.25, 0, 1) |
||
2184 | button.check:SetVertexColor(1, 1, 1, 0.5) |
||
2185 | end |
||
2186 | button.radioHighlight:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton") |
||
2187 | button.check:SetWidth(16) |
||
2188 | button.check:SetHeight(16) |
||
2189 | else |
||
2190 | if button.checked then |
||
2191 | if info.checkIcon then |
||
2192 | button.check:SetWidth(16) |
||
2193 | button.check:SetHeight(16) |
||
2194 | button.check:SetTexture(info.checkIcon) |
||
2195 | if string.sub(info.checkIcon, 1, 16) == "Interface\\Icons\\" then |
||
2196 | button.check:SetTexCoord(0.05, 0.95, 0.05, 0.95) |
||
2197 | else |
||
2198 | button.check:SetTexCoord(0, 1, 0, 1) |
||
2199 | end |
||
2200 | else |
||
2201 | button.check:SetWidth(24) |
||
2202 | button.check:SetHeight(24) |
||
2203 | button.check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check") |
||
2204 | button.check:SetTexCoord(0, 1, 0, 1) |
||
2205 | end |
||
2206 | button.check:SetVertexColor(1, 1, 1, 1) |
||
2207 | else |
||
2208 | button.check:SetVertexColor(1, 1, 1, 0) |
||
2209 | end |
||
2210 | end |
||
2211 | if not button.disabled then |
||
2212 | button.func = info.func |
||
2213 | end |
||
2214 | button.hasColorSwatch = info.hasColorSwatch |
||
2215 | if button.hasColorSwatch then |
||
2216 | button.colorSwatch:Show() |
||
2217 | button.colorSwatch.texture:Show() |
||
2218 | button.r = info.r or 1 |
||
2219 | button.g = info.g or 1 |
||
2220 | button.b = info.b or 1 |
||
2221 | button.colorSwatch.texture:SetTexture(button.r, button.g, button.b) |
||
2222 | button.checked = false |
||
2223 | button.func = nil |
||
2224 | button.colorFunc = info.colorFunc |
||
2225 | button.colorArg1 = info.colorArg1 |
||
2226 | button.colorArg2 = info.colorArg2 |
||
2227 | button.colorArg3 = info.colorArg3 |
||
2228 | button.colorArg4 = info.colorArg4 |
||
2229 | button.hasOpacity = info.hasOpacity |
||
2230 | button.opacity = info.opacity or 1 |
||
2231 | else |
||
2232 | button.colorSwatch:Hide() |
||
2233 | button.colorSwatch.texture:Hide() |
||
2234 | end |
||
2235 | button.hasArrow = not button.hasColorSwatch and (info.value or info.hasSlider or info.hasEditBox) and info.hasArrow |
||
2236 | if button.hasArrow then |
||
2237 | button.arrow:SetAlpha(1) |
||
2238 | if info.hasSlider then |
||
2239 | button.hasSlider = true |
||
2240 | button.sliderMin = info.sliderMin or 0 |
||
2241 | button.sliderMax = info.sliderMax or 1 |
||
2242 | button.sliderStep = info.sliderStep or 0 |
||
2243 | button.sliderIsPercent = info.sliderIsPercent and true or false |
||
2244 | button.sliderMinText = info.sliderMinText or button.sliderIsPercent and string.format("%.0f%%", button.sliderMin * 100) or button.sliderMin |
||
2245 | button.sliderMaxText = info.sliderMaxText or button.sliderIsPercent and string.format("%.0f%%", button.sliderMax * 100) or button.sliderMax |
||
2246 | button.sliderFunc = info.sliderFunc |
||
2247 | button.sliderValue = info.sliderValue |
||
2248 | button.sliderArg1 = info.sliderArg1 |
||
2249 | button.sliderArg2 = info.sliderArg2 |
||
2250 | button.sliderArg3 = info.sliderArg3 |
||
2251 | button.sliderArg4 = info.sliderArg4 |
||
2252 | elseif info.hasEditBox then |
||
2253 | button.hasEditBox = true |
||
2254 | button.editBoxText = info.editBoxText or "" |
||
2255 | button.editBoxFunc = info.editBoxFunc |
||
2256 | button.editBoxArg1 = info.editBoxArg1 |
||
2257 | button.editBoxArg2 = info.editBoxArg2 |
||
2258 | button.editBoxArg3 = info.editBoxArg3 |
||
2259 | button.editBoxArg4 = info.editBoxArg4 |
||
2260 | button.editBoxChangeFunc = info.editBoxChangeFunc |
||
2261 | button.editBoxChangeArg1 = info.editBoxChangeArg1 |
||
2262 | button.editBoxChangeArg2 = info.editBoxChangeArg2 |
||
2263 | button.editBoxChangeArg3 = info.editBoxChangeArg3 |
||
2264 | button.editBoxChangeArg4 = info.editBoxChangeArg4 |
||
2265 | button.editBoxValidateFunc = info.editBoxValidateFunc |
||
2266 | button.editBoxValidateArg1 = info.editBoxValidateArg1 |
||
2267 | button.editBoxValidateArg2 = info.editBoxValidateArg2 |
||
2268 | button.editBoxValidateArg3 = info.editBoxValidateArg3 |
||
2269 | button.editBoxValidateArg4 = info.editBoxValidateArg4 |
||
2270 | else |
||
2271 | button.value = info.value |
||
2272 | end |
||
2273 | else |
||
2274 | button.arrow:SetAlpha(0) |
||
2275 | end |
||
2276 | button.arg1 = info.arg1 |
||
2277 | button.arg2 = info.arg2 |
||
2278 | button.arg3 = info.arg3 |
||
2279 | button.arg4 = info.arg4 |
||
2280 | button.closeWhenClicked = info.closeWhenClicked |
||
2281 | button.textHeight = info.textHeight or UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT or 10 |
||
2282 | local font,_ = button.text:GetFont() |
||
2283 | button.text:SetFont(STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF", button.textHeight) |
||
2284 | button:SetHeight(button.textHeight + 6) |
||
2285 | button.text:SetPoint("RIGHT", button.arrow, (button.hasColorSwatch or button.hasArrow) and "LEFT" or "RIGHT") |
||
2286 | button.text:SetJustifyH(info.justifyH or "LEFT") |
||
2287 | button.text:SetText(info.text) |
||
2288 | button.tooltipTitle = info.tooltipTitle |
||
2289 | button.tooltipText = info.tooltipText |
||
2290 | button.tooltipFunc = info.tooltipFunc |
||
2291 | button.tooltipArg1 = info.tooltipArg1 |
||
2292 | button.tooltipArg2 = info.tooltipArg2 |
||
2293 | button.tooltipArg3 = info.tooltipArg3 |
||
2294 | button.tooltipArg4 = info.tooltipArg4 |
||
2295 | if not button.tooltipTitle and not button.tooltipText and not button.tooltipFunc and not info.isTitle then |
||
2296 | button.tooltipTitle = info.text |
||
2297 | end |
||
2298 | if type(button.func) == "string" then |
||
2299 | self:assert(type(button.arg1) == "table", "Cannot call method " .. button.func .. " on a non-table") |
||
2300 | self:assert(type(button.arg1[button.func]) == "function", "Method " .. button.func .. " nonexistant.") |
||
2301 | end |
||
2302 | end |
||
2303 | |||
2304 | function Dewdrop:InjectAceOptionsTable(handler, options) |
||
2305 | self:argCheck(handler, 2, "table") |
||
2306 | self:argCheck(options, 3, "table") |
||
2307 | if string.lower(tostring(options.type)) ~= "group" then |
||
2308 | self:error('Cannot inject into options table argument #3 if its type is not "group"') |
||
2309 | end |
||
2310 | if options.handler ~= nil and options.handler ~= handler then |
||
2311 | self:error("Cannot inject into options table argument #3 if it has a different handler than argument #2") |
||
2312 | end |
||
2313 | options.handler = handler |
||
2314 | local class = handler.class |
||
2315 | if not AceLibrary:HasInstance("AceOO-2.0") or not class then |
||
2316 | self:error("Cannot retrieve AceOptions tables from a non-object argument #2") |
||
2317 | end |
||
2318 | while class and class ~= AceLibrary("AceOO-2.0").Class do |
||
2319 | if type(class.GetAceOptionsDataTable) == "function" then |
||
2320 | local t = class:GetAceOptionsDataTable(handler) |
||
2321 | for k,v in pairs(t) do |
||
2322 | if type(options.args) ~= "table" then |
||
2323 | options.args = {} |
||
2324 | end |
||
2325 | if options.args[k] == nil then |
||
2326 | options.args[k] = v |
||
2327 | end |
||
2328 | end |
||
2329 | end |
||
2330 | local mixins = class.mixins |
||
2331 | if mixins then |
||
2332 | for mixin in pairs(mixins) do |
||
2333 | if type(mixin.GetAceOptionsDataTable) == "function" then |
||
2334 | local t = mixin:GetAceOptionsDataTable(handler) |
||
2335 | for k,v in pairs(t) do |
||
2336 | if type(options.args) ~= "table" then |
||
2337 | options.args = {} |
||
2338 | end |
||
2339 | if options.args[k] == nil then |
||
2340 | options.args[k] = v |
||
2341 | end |
||
2342 | end |
||
2343 | end |
||
2344 | end |
||
2345 | end |
||
2346 | class = class.super |
||
2347 | end |
||
2348 | return options |
||
2349 | end |
||
2350 | |||
2351 | local function activate(self, oldLib, oldDeactivate) |
||
2352 | Dewdrop = self |
||
2353 | if oldLib and oldLib.registry then |
||
2354 | self.registry = oldLib.registry |
||
2355 | self.onceRegistered = oldLib.onceRegistered |
||
2356 | else |
||
2357 | self.registry = {} |
||
2358 | self.onceRegistered = {} |
||
2359 | |||
2360 | local WorldFrame_OnMouseDown = WorldFrame:GetScript("OnMouseDown") |
||
2361 | local WorldFrame_OnMouseUp = WorldFrame:GetScript("OnMouseUp") |
||
2362 | local oldX, oldY, clickTime |
||
2363 | WorldFrame:SetScript("OnMouseDown", function() |
||
2364 | oldX,oldY = GetCursorPosition() |
||
2365 | clickTime = GetTime() |
||
2366 | if WorldFrame_OnMouseDown then |
||
2367 | WorldFrame_OnMouseDown() |
||
2368 | end |
||
2369 | end) |
||
2370 | |||
2371 | WorldFrame:SetScript("OnMouseUp", function() |
||
2372 | local x,y = GetCursorPosition() |
||
2373 | if not oldX or not oldY or not x or not y or not clickTime then |
||
2374 | self:Close() |
||
2375 | if WorldFrame_OnMouseUp then |
||
2376 | WorldFrame_OnMouseUp() |
||
2377 | end |
||
2378 | return |
||
2379 | end |
||
2380 | local d = math.abs(x - oldX) + math.abs(y - oldY) |
||
2381 | if d <= 5 and GetTime() - clickTime < 0.5 then |
||
2382 | self:Close() |
||
2383 | end |
||
2384 | if WorldFrame_OnMouseUp then |
||
2385 | WorldFrame_OnMouseUp() |
||
2386 | end |
||
2387 | end) |
||
2388 | |||
2389 | local DropDownList1_Show = DropDownList1.Show |
||
2390 | function DropDownList1.Show(DropDownList1) |
||
2391 | if levels[1] and levels[1]:IsVisible() then |
||
2392 | self:Close() |
||
2393 | end |
||
2394 | DropDownList1_Show(DropDownList1) |
||
2395 | end |
||
2396 | |||
2397 | local old_HideDropDownMenu = HideDropDownMenu |
||
2398 | function HideDropDownMenu(num) |
||
2399 | if levels[1] and levels[1]:IsVisible() then |
||
2400 | self:Close() |
||
2401 | end |
||
2402 | old_HideDropDownMenu(num) |
||
2403 | end |
||
2404 | |||
2405 | local old_CloseDropDownMenus = CloseDropDownMenus |
||
2406 | function CloseDropDownMenus(num) |
||
2407 | if levels[1] and levels[1]:IsVisible() then |
||
2408 | self:Close() |
||
2409 | end |
||
2410 | old_CloseDropDownMenus(num) |
||
2411 | end |
||
2412 | end |
||
2413 | levels = {} |
||
2414 | buttons = {} |
||
2415 | |||
2416 | if oldDeactivate then |
||
2417 | oldDeactivate(oldLib) |
||
2418 | end |
||
2419 | end |
||
2420 | |||
2421 | AceLibrary:Register(Dewdrop, MAJOR_VERSION, MINOR_VERSION, activate) |