vanilla-wow-addons – Blame information for rev 1

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