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: 15611 $
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: 15611 $"
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 'icon', v.icon,
1234 'iconHeight', iconHeight,
1235 'iconWidth', iconWidth,
1236 'hasEditBox', true,
1237 'editBoxText', editBoxText,
1238 'editBoxFunc', editBoxFunc,
1239 'editBoxArg1', editBoxArg1,
1240 'editBoxArg2', editBoxArg2,
1241 'editBoxValidateFunc', editBoxValidateFunc,
1242 'editBoxValidateArg1', editBoxValidateArg1,
1243 'disabled', disabled,
1244 'tooltipTitle', tooltipTitle,
1245 'tooltipText', tooltipText
1246 )
1247 end
1248 elseif v.type == "group" then
1249 self:AddLine(
1250 'text', name,
1251 'hasArrow', true,
1252 'value', k,
1253 'disabled', disabled,
1254 'tooltipTitle', tooltipTitle,
1255 'tooltipText', tooltipText,
1256 'icon', v.icon,
1257 'iconHeight', iconHeight,
1258 'iconWidth', iconWidth
1259 )
1260 elseif v.type == "header" then
1261 if name == "" or not name then
1262 self:AddLine(
1263 'isTitle', true,
1264 'icon', v.icon,
1265 'iconHeight', iconHeight,
1266 'iconWidth', iconWidth
1267 )
1268 else
1269 self:AddLine(
1270 'text', name,
1271 'isTitle', true,
1272 'icon', v.icon,
1273 'iconHeight', iconHeight,
1274 'iconWidth', iconWidth
1275 )
1276 end
1277 end
1278 end
1279 last_order = v.order or 100
1280 end
1281 elseif options.type == "text" and type(options.validate) == "table" then
1282 local current
1283 if type(options.get) == "function" then
1284 current = options.get(passValue)
1285 elseif options.get ~= false then
1286 if not handler[options.get] then
1287 Dewdrop:error("Handler %q not available", options.get)
1288 end
1289 current = handler[options.get](handler, passValue)
1290 end
1291 local indexed = true
1292 for k,v in pairs(options.validate) do
1293 if type(k) ~= "number" then
1294 indexed = false
1295 end
1296 table.insert(values, k)
1297 end
1298 if not indexed then
1299 if not othersort then
1300 othersort = function(alpha, bravo)
1301 return othersort_validate[alpha] < othersort_validate[bravo]
1302 end
1303 end
1304 othersort_validate = options.validate
1305 table.sort(values, othersort)
1306 othersort_validate = nil
1307 end
1308 for _,k in ipairs(values) do
1309 local v = options.validate[k]
1310 if type(k) == "number" then
1311 k = v
1312 end
1313 local func, arg1, arg2
1314 if type(options.set) == "function" then
1315 func = options.set
1316 if passValue ~= nil then
1317 arg1 = passValue
1318 arg2 = k
1319 else
1320 arg1 = k
1321 end
1322 else
1323 if not handler[options.set] then
1324 Dewdrop:error("Handler %q not available", options.set)
1325 end
1326 func = handler[options.set]
1327 arg1 = handler
1328 if passValue ~= nil then
1329 arg2 = passValue
1330 arg3 = k
1331 else
1332 arg2 = k
1333 end
1334 end
1335 local checked = (k == current or (type(k) == "string" and type(current) == "string" and string.lower(k) == string.lower(current)))
1336 self:AddLine(
1337 'text', v,
1338 'func', not checked and func or nil,
1339 'arg1', not checked and arg1 or nil,
1340 'arg2', not checked and arg2 or nil,
1341 'arg3', not checked and arg3 or nil,
1342 'isRadio', true,
1343 'checked', checked,
1344 'tooltipTitle', options.guiName or options.name,
1345 'tooltipText', v
1346 )
1347 end
1348 for k in pairs(values) do
1349 values[k] = nil
1350 end
1351 table_setn(values, 0)
1352 else
1353 return false
1354 end
1355 return true
1356 end
1357  
1358 function Refresh(self, level)
1359 if type(level) == "number" then
1360 level = levels[level]
1361 end
1362 if not level then
1363 return
1364 end
1365 if baseFunc then
1366 Clear(self, level)
1367 currentLevel = level.num
1368 if type(baseFunc) == "table" then
1369 if currentLevel == 1 then
1370 local handler = baseFunc.handler
1371 if handler then
1372 local name = tostring(handler)
1373 if not string.find(name, '^table:') then
1374 name = string.gsub(name, "|c%x%x%x%x%x%x%x%x(.-)|r", "%1")
1375 self:AddLine(
1376 'text', name,
1377 'isTitle', true
1378 )
1379 end
1380 end
1381 -- elseif level.parentText then
1382 -- self:AddLine(
1383 -- 'text', level.parentText,
1384 -- 'tooltipTitle', level.parentTooltipTitle,
1385 -- 'tooltipText', level.parentTooltipText,
1386 -- 'tooltipFunc', level.parentTooltipFunc,
1387 -- 'isTitle', true
1388 -- )
1389 end
1390 self:FeedAceOptionsTable(baseFunc)
1391 if currentLevel == 1 then
1392 self:AddLine(
1393 'text', CLOSE,
1394 'closeWhenClicked', true
1395 )
1396 end
1397 else
1398 -- if level.parentText then
1399 -- self:AddLine(
1400 -- 'text', level.parentText,
1401 -- 'tooltipTitle', level.parentTooltipTitle,
1402 -- 'tooltipText', level.parentTooltipText,
1403 -- 'tooltipFunc', level.parentTooltipFunc,
1404 -- 'isTitle', true
1405 -- )
1406 -- end
1407 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)
1408 end
1409 currentLevel = nil
1410 CheckSize(self, level)
1411 end
1412 end
1413  
1414 function Dewdrop:Refresh(level)
1415 self:argCheck(level, 2, "number")
1416 Refresh(self, levels[level])
1417 end
1418  
1419 function OpenSlider(self, parent)
1420 if not sliderFrame then
1421 sliderFrame = CreateFrame("Frame", nil, UIParent)
1422 sliderFrame:SetWidth(80)
1423 sliderFrame:SetHeight(170)
1424 sliderFrame:SetBackdrop(tmp(
1425 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background",
1426 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border",
1427 'tile', true,
1428 'insets', tmp2(
1429 'left', 5,
1430 'right', 5,
1431 'top', 5,
1432 'bottom', 5
1433 ),
1434 'tileSize', 16,
1435 'edgeSize', 16
1436 ))
1437 sliderFrame:SetFrameStrata("FULLSCREEN_DIALOG")
1438 if sliderFrame.SetTopLevel then
1439 sliderFrame:SetTopLevel(true)
1440 end
1441 sliderFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
1442 sliderFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b)
1443 sliderFrame:EnableMouse(true)
1444 sliderFrame:Hide()
1445 sliderFrame:SetPoint("CENTER", UIParent, "CENTER")
1446 local slider = CreateFrame("Slider", nil, sliderFrame)
1447 sliderFrame.slider = slider
1448 slider:SetOrientation("VERTICAL")
1449 slider:SetMinMaxValues(0, 1)
1450 slider:SetValueStep(0.01)
1451 slider:SetValue(0.5)
1452 slider:SetWidth(16)
1453 slider:SetHeight(128)
1454 slider:SetPoint("LEFT", sliderFrame, "LEFT", 15, 0)
1455 slider:SetBackdrop(tmp(
1456 'bgFile', "Interface\\Buttons\\UI-SliderBar-Background",
1457 'edgeFile', "Interface\\Buttons\\UI-SliderBar-Border",
1458 'tile', true,
1459 'edgeSize', 8,
1460 'tileSize', 8,
1461 'insets', tmp2(
1462 'left', 3,
1463 'right', 3,
1464 'top', 3,
1465 'bottom', 3
1466 )
1467 ))
1468 local texture = slider:CreateTexture()
1469 slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical")
1470 local text = slider:CreateFontString(nil, "ARTWORK")
1471 sliderFrame.topText = text
1472 text:SetFontObject(GameFontGreenSmall)
1473 text:SetText("100%")
1474 text:SetPoint("BOTTOM", slider, "TOP")
1475 local text = slider:CreateFontString(nil, "ARTWORK")
1476 sliderFrame.bottomText = text
1477 text:SetFontObject(GameFontGreenSmall)
1478 text:SetText("0%")
1479 text:SetPoint("TOP", slider, "BOTTOM")
1480 local text = slider:CreateFontString(nil, "ARTWORK")
1481 sliderFrame.currentText = text
1482 text:SetFontObject(GameFontHighlightSmall)
1483 text:SetText("50%")
1484 text:SetPoint("LEFT", slider, "RIGHT")
1485 text:SetPoint("RIGHT", sliderFrame, "RIGHT", -6, 0)
1486 text:SetJustifyH("CENTER")
1487 local changed = false
1488 local inside = false
1489 slider:SetScript("OnValueChanged", function()
1490 if sliderFrame.changing then
1491 return
1492 end
1493 changed = true
1494 local done = false
1495 if sliderFrame.parent then
1496 if sliderFrame.parent.sliderFunc then
1497 local min = sliderFrame.parent.sliderMin or 0
1498 local max = sliderFrame.parent.sliderMax or 1
1499 local step = sliderFrame.parent.sliderStep or (max - min) / 100
1500 local a1,a2,a3,a4 = sliderFrame.parent.sliderArg1, sliderFrame.parent.sliderArg2, sliderFrame.parent.sliderArg3, sliderFrame.parent.sliderArg4
1501 local value = (1 - slider:GetValue()) * (max - min) + min
1502 if step > 0 then
1503 value = math.floor((value - min) / step + 0.5) * step + min
1504 if value > max then
1505 value = max
1506 elseif value < min then
1507 value = min
1508 end
1509 end
1510 local text
1511 if a1 == nil then
1512 text = sliderFrame.parent.sliderFunc(value)
1513 elseif a2 == nil then
1514 text = sliderFrame.parent.sliderFunc(a1, value)
1515 elseif a3 == nil then
1516 text = sliderFrame.parent.sliderFunc(a1, a2, value)
1517 elseif a4 == nil then
1518 text = sliderFrame.parent.sliderFunc(a1, a2, a3, value)
1519 else
1520 text = sliderFrame.parent.sliderFunc(a1, a2, a3, a4, value)
1521 end
1522 if text then
1523 sliderFrame.currentText:SetText(text)
1524 done = true
1525 end
1526 end
1527 end
1528 if not done then
1529 local min = sliderFrame.parent.sliderMin or 0
1530 local max = sliderFrame.parent.sliderMax or 1
1531 local step = sliderFrame.parent.sliderStep or (max - min) / 100
1532 local value = (1 - slider:GetValue()) * (max - min) + min
1533 if step > 0 then
1534 value = math.floor((value - min) / step + 0.5) * step + min
1535 if value > max then
1536 value = max
1537 elseif value < min then
1538 value = min
1539 end
1540 end
1541 if sliderFrame.parent.sliderIsPercent then
1542 sliderFrame.currentText:SetText(string.format("%.0f%%", value * 100))
1543 else
1544 if step < 0.1 then
1545 sliderFrame.currentText:SetText(string.format("%.2f", value))
1546 elseif step < 1 then
1547 sliderFrame.currentText:SetText(string.format("%.1f", value))
1548 else
1549 sliderFrame.currentText:SetText(string.format("%.0f", value))
1550 end
1551 end
1552 end
1553 end)
1554 sliderFrame:SetScript("OnEnter", function()
1555 StopCounting(self, sliderFrame.level)
1556 end)
1557 sliderFrame:SetScript("OnLeave", function()
1558 StartCounting(self, sliderFrame.level)
1559 end)
1560 slider:SetScript("OnMouseDown", function()
1561 sliderFrame.mouseDown = true
1562 end)
1563 slider:SetScript("OnMouseUp", function()
1564 sliderFrame.mouseDown = false
1565 if changed and not inside then
1566 local parent = sliderFrame.parent
1567 for i = 1, sliderFrame.level - 1 do
1568 Refresh(self, levels[i])
1569 end
1570 OpenSlider(self, parent)
1571 end
1572 end)
1573 slider:SetScript("OnEnter", function()
1574 inside = true
1575 StopCounting(self, sliderFrame.level)
1576 end)
1577 slider:SetScript("OnLeave", function()
1578 inside = false
1579 StartCounting(self, sliderFrame.level)
1580 if changed and not sliderFrame.mouseDown then
1581 local parent = sliderFrame.parent
1582 for i = 1, sliderFrame.level - 1 do
1583 Refresh(self, levels[i])
1584 end
1585 OpenSlider(self, parent)
1586 end
1587 end)
1588 end
1589 sliderFrame.parent = parent
1590 sliderFrame.level = parent.level.num + 1
1591 sliderFrame.parentValue = parent.level.value
1592 sliderFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3)
1593 sliderFrame.slider:SetFrameLevel(sliderFrame:GetFrameLevel() + 1)
1594 sliderFrame.changing = true
1595 if not parent.sliderMin or not parent.sliderMax then
1596 return
1597 end
1598  
1599 if parent.arrow then
1600 -- parent.arrow:SetVertexColor(0.2, 0.6, 0)
1601 parent.arrow:SetHeight(24)
1602 parent.arrow:SetWidth(24)
1603 end
1604  
1605 if not parent.sliderValue then
1606 parent.sliderValue = (parent.sliderMin + parent.sliderMax) / 2
1607 end
1608 sliderFrame.slider:SetValue(1 - (parent.sliderValue - parent.sliderMin) / (parent.sliderMax - parent.sliderMin))
1609 sliderFrame.changing = false
1610 sliderFrame.bottomText:SetText(parent.sliderMinText or "0")
1611 sliderFrame.topText:SetText(parent.sliderMaxText or "1")
1612 local text
1613 if parent.sliderFunc then
1614 local a1,a2,a3,a4 = parent.sliderArg1, parent.sliderArg2, parent.sliderArg3, parent.sliderArg4
1615 if a1 == nil then
1616 text = parent.sliderFunc(parent.sliderValue)
1617 elseif a2 == nil then
1618 text = parent.sliderFunc(a1, parent.sliderValue)
1619 elseif a3 == nil then
1620 text = parent.sliderFunc(a1, a2, parent.sliderValue)
1621 elseif a4 == nil then
1622 text = parent.sliderFunc(a1, a2, a3, parent.sliderValue)
1623 else
1624 text = parent.sliderFunc(a1, a2, a3, a4, parent.sliderValue)
1625 end
1626 end
1627 if text then
1628 sliderFrame.currentText:SetText(text)
1629 elseif parent.sliderIsPercent then
1630 sliderFrame.currentText:SetText(string.format("%.0f%%", parent.sliderValue * 100))
1631 else
1632 sliderFrame.currentText:SetText(parent.sliderValue)
1633 end
1634  
1635 local level = parent.level
1636 sliderFrame:Show()
1637 sliderFrame:ClearAllPoints()
1638 if level.lastDirection == "RIGHT" then
1639 if level.lastVDirection == "DOWN" then
1640 sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10)
1641 else
1642 sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10)
1643 end
1644 else
1645 if level.lastVDirection == "DOWN" then
1646 sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10)
1647 else
1648 sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10)
1649 end
1650 end
1651 local dirty
1652 if level.lastDirection == "RIGHT" then
1653 if sliderFrame:GetRight() > GetScreenWidth() then
1654 level.lastDirection = "LEFT"
1655 dirty = true
1656 end
1657 elseif sliderFrame:GetLeft() < 0 then
1658 level.lastDirection = "RIGHT"
1659 dirty = true
1660 end
1661 if level.lastVDirection == "DOWN" then
1662 if sliderFrame:GetBottom() < 0 then
1663 level.lastVDirection = "UP"
1664 dirty = true
1665 end
1666 elseif sliderFrame:GetTop() > GetScreenWidth() then
1667 level.lastVDirection = "DOWN"
1668 dirty = true
1669 end
1670 if dirty then
1671 sliderFrame:ClearAllPoints()
1672 if level.lastDirection == "RIGHT" then
1673 if level.lastVDirection == "DOWN" then
1674 sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10)
1675 else
1676 sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10)
1677 end
1678 else
1679 if level.lastVDirection == "DOWN" then
1680 sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10)
1681 else
1682 sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10)
1683 end
1684 end
1685 end
1686 local left, bottom = sliderFrame:GetLeft(), sliderFrame:GetBottom()
1687 sliderFrame:ClearAllPoints()
1688 sliderFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom)
1689 if mod(level.num, 5) == 0 then
1690 local left, bottom = level:GetLeft(), level:GetBottom()
1691 level:ClearAllPoints()
1692 level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom)
1693 end
1694 end
1695  
1696 function OpenEditBox(self, parent)
1697 if not editBoxFrame then
1698 editBoxFrame = CreateFrame("Frame", nil, UIParent)
1699 editBoxFrame:SetWidth(200)
1700 editBoxFrame:SetHeight(40)
1701 editBoxFrame:SetBackdrop(tmp(
1702 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background",
1703 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border",
1704 'tile', true,
1705 'insets', tmp2(
1706 'left', 5,
1707 'right', 5,
1708 'top', 5,
1709 'bottom', 5
1710 ),
1711 'tileSize', 16,
1712 'edgeSize', 16
1713 ))
1714 editBoxFrame:SetFrameStrata("FULLSCREEN_DIALOG")
1715 if editBoxFrame.SetTopLevel then
1716 editBoxFrame:SetTopLevel(true)
1717 end
1718 editBoxFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
1719 editBoxFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b)
1720 editBoxFrame:EnableMouse(true)
1721 editBoxFrame:Hide()
1722 editBoxFrame:SetPoint("CENTER", UIParent, "CENTER")
1723  
1724 local editBox = CreateFrame("EditBox", nil, editBoxFrame)
1725 editBoxFrame.editBox = editBox
1726 editBox:SetFontObject(ChatFontNormal)
1727 editBox:SetWidth(160)
1728 editBox:SetHeight(13)
1729 editBox:SetPoint("CENTER", editBoxFrame, "CENTER", 0, 0)
1730  
1731 local left = editBox:CreateTexture(nil, "BACKGROUND")
1732 left:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Left")
1733 left:SetTexCoord(0, 100 / 256, 0, 1)
1734 left:SetWidth(100)
1735 left:SetHeight(32)
1736 left:SetPoint("LEFT", editBox, "LEFT", -10, 0)
1737 local right = editBox:CreateTexture(nil, "BACKGROUND")
1738 right:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Right")
1739 right:SetTexCoord(156/256, 1, 0, 1)
1740 right:SetWidth(100)
1741 right:SetHeight(32)
1742 right:SetPoint("RIGHT", editBox, "RIGHT", 10, 0)
1743  
1744 editBox:SetScript("OnEnterPressed", function()
1745 if editBoxFrame.parent and editBoxFrame.parent.editBoxValidateFunc then
1746 local a1,a2,a3,a4 = editBoxFrame.parent.editBoxValidateArg1, editBoxFrame.parent.editBoxValidateArg2, editBoxFrame.parent.editBoxValidateArg3, editBoxFrame.parent.editBoxValidateArg4
1747  
1748 local result
1749 if a1 == nil then
1750 result = editBoxFrame.parent.editBoxValidateFunc(editBox:GetText() or "")
1751 elseif a2 == nil then
1752 result = editBoxFrame.parent.editBoxValidateFunc(a1, editBox:GetText() or "")
1753 elseif a3 == nil then
1754 result = editBoxFrame.parent.editBoxValidateFunc(a1, a2, editBox:GetText() or "")
1755 elseif a4 == nil then
1756 result = editBoxFrame.parent.editBoxValidateFunc(a1, a2, a3, editBox:GetText() or "")
1757 else
1758 result = editBoxFrame.parent.editBoxValidateFunc(a1, a2, a3, a4, editBox:GetText() or "")
1759 end
1760 if not result then
1761 message("Validation error: [" .. tostring(text) .. "]")
1762 return
1763 end
1764 end
1765 if editBoxFrame.parent and editBoxFrame.parent.editBoxFunc then
1766 local a1,a2,a3,a4 = editBoxFrame.parent.editBoxArg1, editBoxFrame.parent.editBoxArg2, editBoxFrame.parent.editBoxArg3, editBoxFrame.parent.editBoxArg4
1767 if a1 == nil then
1768 editBoxFrame.parent.editBoxFunc(editBox:GetText() or "")
1769 elseif a2 == nil then
1770 editBoxFrame.parent.editBoxFunc(a1, editBox:GetText() or "")
1771 elseif a3 == nil then
1772 editBoxFrame.parent.editBoxFunc(a1, a2, editBox:GetText() or "")
1773 elseif a4 == nil then
1774 editBoxFrame.parent.editBoxFunc(a1, a2, a3, editBox:GetText() or "")
1775 else
1776 editBoxFrame.parent.editBoxFunc(a1, a2, a3, a4, editBox:GetText() or "")
1777 end
1778 end
1779 self:Close(editBoxFrame.level)
1780 for i = 1, editBoxFrame.level - 1 do
1781 Refresh(self, levels[i])
1782 end
1783 end)
1784 editBox:SetScript("OnEscapePressed", function()
1785 self:Close(editBoxFrame.level)
1786 end)
1787 local changing = false
1788 local skipNext = false
1789  
1790 function editBox:SpecialSetText(text)
1791 local oldText = editBox:GetText() or ""
1792 if not text then
1793 text = ""
1794 end
1795 if text ~= oldText then
1796 changing = true
1797 self:SetText(text)
1798 changing = false
1799 skipNext = true
1800 end
1801 end
1802  
1803 editBox:SetScript("OnTextChanged", function()
1804 if skipNext then
1805 skipNext = false
1806 elseif not changing and editBoxFrame.parent and editBoxFrame.parent.editBoxChangeFunc then
1807 local a1,a2,a3,a4 = editBoxFrame.parent.editBoxChangeArg1, editBoxFrame.parent.editBoxChangeArg2, editBoxFrame.parent.editBoxChangeArg3, editBoxFrame.parent.editBoxChangeArg4
1808 local text
1809 if a1 == nil then
1810 text = editBoxFrame.parent.editBoxChangeFunc(editBox:GetText() or "")
1811 elseif a2 == nil then
1812 text = editBoxFrame.parent.editBoxChangeFunc(a1, editBox:GetText() or "")
1813 elseif a3 == nil then
1814 text = editBoxFrame.parent.editBoxChangeFunc(a1, a2, editBox:GetText() or "")
1815 elseif a4 == nil then
1816 text = editBoxFrame.parent.editBoxChangeFunc(a1, a2, a3, editBox:GetText() or "")
1817 else
1818 text = editBoxFrame.parent.editBoxChangeFunc(a1, a2, a3, a4, editBox:GetText() or "")
1819 end
1820 if text then
1821 editBox:SpecialSetText(text)
1822 end
1823 end
1824 end)
1825 editBoxFrame:SetScript("OnEnter", function()
1826 StopCounting(self, editBoxFrame.level)
1827 end)
1828 editBoxFrame:SetScript("OnLeave", function()
1829 StartCounting(self, editBoxFrame.level)
1830 end)
1831 editBox:SetScript("OnEnter", function()
1832 StopCounting(self, editBoxFrame.level)
1833 end)
1834 editBox:SetScript("OnLeave", function()
1835 StartCounting(self, editBoxFrame.level)
1836 end)
1837 end
1838 editBoxFrame.parent = parent
1839 editBoxFrame.level = parent.level.num + 1
1840 editBoxFrame.parentValue = parent.level.value
1841 editBoxFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3)
1842 editBoxFrame.editBox:SetFrameLevel(editBoxFrame:GetFrameLevel() + 1)
1843 editBoxFrame.editBox:SpecialSetText(parent.editBoxText)
1844  
1845 if parent.arrow then
1846 -- parent.arrow:SetVertexColor(0.2, 0.6, 0)
1847 parent.arrow:SetHeight(24)
1848 parent.arrow:SetWidth(24)
1849 end
1850  
1851 local level = parent.level
1852 editBoxFrame:Show()
1853 editBoxFrame:ClearAllPoints()
1854 if level.lastDirection == "RIGHT" then
1855 if level.lastVDirection == "DOWN" then
1856 editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10)
1857 else
1858 editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10)
1859 end
1860 else
1861 if level.lastVDirection == "DOWN" then
1862 editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10)
1863 else
1864 editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10)
1865 end
1866 end
1867 local dirty
1868 if level.lastDirection == "RIGHT" then
1869 if editBoxFrame:GetRight() > GetScreenWidth() then
1870 level.lastDirection = "LEFT"
1871 dirty = true
1872 end
1873 elseif editBoxFrame:GetLeft() < 0 then
1874 level.lastDirection = "RIGHT"
1875 dirty = true
1876 end
1877 if level.lastVDirection == "DOWN" then
1878 if editBoxFrame:GetBottom() < 0 then
1879 level.lastVDirection = "UP"
1880 dirty = true
1881 end
1882 elseif editBoxFrame:GetTop() > GetScreenWidth() then
1883 level.lastVDirection = "DOWN"
1884 dirty = true
1885 end
1886 if dirty then
1887 editBoxFrame:ClearAllPoints()
1888 if level.lastDirection == "RIGHT" then
1889 if level.lastVDirection == "DOWN" then
1890 editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10)
1891 else
1892 editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10)
1893 end
1894 else
1895 if level.lastVDirection == "DOWN" then
1896 editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10)
1897 else
1898 editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10)
1899 end
1900 end
1901 end
1902 local left, bottom = editBoxFrame:GetLeft(), editBoxFrame:GetBottom()
1903 editBoxFrame:ClearAllPoints()
1904 editBoxFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom)
1905 if mod(level.num, 5) == 0 then
1906 local left, bottom = level:GetLeft(), level:GetBottom()
1907 level:ClearAllPoints()
1908 level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom)
1909 end
1910 end
1911  
1912 function Dewdrop:IsOpen(parent)
1913 self:argCheck(parent, 2, "table", "nil")
1914 return levels[1] and levels[1]:IsShown() and (not parent or parent == levels[1].parent or parent == levels[1]:GetParent())
1915 end
1916  
1917 function Dewdrop:GetOpenedParent()
1918 return (levels[1] and levels[1]:IsShown()) and (levels[1].parent or levels[1]:GetParent())
1919 end
1920  
1921 function Open(self, parent, func, level, value, point, relativePoint, cursorX, cursorY)
1922 self:Close(level)
1923 if DewdropLib then
1924 local d = DewdropLib:GetInstance('1.0')
1925 local ret, val = pcall(d, IsOpen, d)
1926 if ret and val then
1927 DewdropLib:GetInstance('1.0'):Close()
1928 end
1929 end
1930 parent:GetCenter()
1931 local frame = AcquireLevel(self, level)
1932 if level == 1 then
1933 frame.lastDirection = "RIGHT"
1934 frame.lastVDirection = "DOWN"
1935 else
1936 frame.lastDirection = levels[level - 1].lastDirection
1937 frame.lastVDirection = levels[level - 1].lastVDirection
1938 end
1939 frame:SetFrameStrata("FULLSCREEN_DIALOG")
1940 frame:ClearAllPoints()
1941 frame.parent = parent
1942 frame:SetPoint("LEFT", UIParent, "RIGHT", 10000, 0)
1943 frame:Show()
1944 if level == 1 then
1945 baseFunc = func
1946 end
1947 levels[level].value = value
1948 -- levels[level].parentText = parent.text and parent.text:GetText() or nil
1949 -- levels[level].parentTooltipTitle = parent.tooltipTitle
1950 -- levels[level].parentTooltipText = parent.tooltipText
1951 -- levels[level].parentTooltipFunc = parent.tooltipFunc
1952 if parent.arrow then
1953 -- parent.arrow:SetVertexColor(0.2, 0.6, 0)
1954 parent.arrow:SetHeight(24)
1955 parent.arrow:SetWidth(24)
1956 end
1957 relativePoint = relativePoint or point
1958 Refresh(self, levels[level])
1959 if point or (cursorX and cursorY) then
1960 frame:ClearAllPoints()
1961 if cursorX and cursorY then
1962 local curX, curY = GetScaledCursorPosition()
1963 if curY < GetScreenHeight() / 2 then
1964 point, relativePoint = "BOTTOM", "BOTTOM"
1965 else
1966 point, relativePoint = "TOP", "TOP"
1967 end
1968 if curX < GetScreenWidth() / 2 then
1969 point, relativePoint = point .. "LEFT", relativePoint .. "RIGHT"
1970 else
1971 point, relativePoint = point .. "RIGHT", relativePoint .. "LEFT"
1972 end
1973 end
1974 frame:SetPoint(point, parent, relativePoint)
1975 if cursorX and cursorY then
1976 local left = frame:GetLeft()
1977 local width = frame:GetWidth()
1978 local bottom = frame:GetBottom()
1979 local height = frame:GetHeight()
1980 local curX, curY = GetScaledCursorPosition()
1981 frame:ClearAllPoints()
1982 relativePoint = relativePoint or point
1983 if point == "BOTTOM" or point == "TOP" then
1984 if curX < GetScreenWidth() / 2 then
1985 point = point .. "LEFT"
1986 else
1987 point = point .. "RIGHT"
1988 end
1989 elseif point == "CENTER" then
1990 if curX < GetScreenWidth() / 2 then
1991 point = "LEFT"
1992 else
1993 point = "RIGHT"
1994 end
1995 end
1996 local xOffset, yOffset = 0, 0
1997 if curY > GetScreenHeight() / 2 then
1998 yOffset = -height
1999 end
2000 if curX > GetScreenWidth() / 2 then
2001 xOffset = -width
2002 end
2003 frame:SetPoint(point, parent, relativePoint, curX - left + xOffset, curY - bottom + yOffset)
2004 if level == 1 then
2005 frame.lastDirection = "RIGHT"
2006 end
2007 elseif cursorX then
2008 local left = frame:GetLeft()
2009 local width = frame:GetWidth()
2010 local curX, curY = GetScaledCursorPosition()
2011 frame:ClearAllPoints()
2012 relativePoint = relativePoint or point
2013 if point == "BOTTOM" or point == "TOP" then
2014 if curX < GetScreenWidth() / 2 then
2015 point = point .. "LEFT"
2016 else
2017 point = point .. "RIGHT"
2018 end
2019 elseif point == "CENTER" then
2020 if curX < GetScreenWidth() / 2 then
2021 point = "LEFT"
2022 else
2023 point = "RIGHT"
2024 end
2025 end
2026 frame:SetPoint(point, parent, relativePoint, curX - left - width / 2, 0)
2027 if level == 1 then
2028 frame.lastDirection = "RIGHT"
2029 end
2030 elseif cursorY then
2031 local bottom = frame:GetBottom()
2032 local height = frame:GetHeight()
2033 local curX, curY = GetScaledCursorPosition()
2034 frame:ClearAllPoints()
2035 relativePoint = relativePoint or point
2036 if point == "LEFT" or point == "RIGHT" then
2037 if curX < GetScreenHeight() / 2 then
2038 point = point .. "BOTTOM"
2039 else
2040 point = point .. "TOP"
2041 end
2042 elseif point == "CENTER" then
2043 if curX < GetScreenHeight() / 2 then
2044 point = "BOTTOM"
2045 else
2046 point = "TOP"
2047 end
2048 end
2049 frame:SetPoint(point, parent, relativePoint, 0, curY - bottom - height / 2)
2050 if level == 1 then
2051 frame.lastDirection = "DOWN"
2052 end
2053 end
2054 if (strsub(point, 1, 3) ~= strsub(relativePoint, 1, 3)) then
2055 if frame:GetBottom() < 0 then
2056 local point, parent, relativePoint, x, y = frame:GetPoint(1)
2057 local change = GetScreenHeight() - frame:GetTop()
2058 local otherChange = -frame:GetBottom()
2059 if otherChange < change then
2060 change = otherChange
2061 end
2062 frame:SetPoint(point, parent, relativePoint, x, y + change)
2063 elseif frame:GetTop() > GetScreenHeight() then
2064 local point, parent, relativePoint, x, y = frame:GetPoint(1)
2065 local change = GetScreenHeight() - frame:GetTop()
2066 local otherChange = -frame:GetBottom()
2067 if otherChange < change then
2068 change = otherChange
2069 end
2070 frame:SetPoint(point, parent, relativePoint, x, y + change)
2071 end
2072 end
2073 end
2074 CheckDualMonitor(self, frame)
2075 StartCounting(self, level)
2076 end
2077  
2078 function Dewdrop:IsRegistered(parent)
2079 self:argCheck(parent, 2, "table")
2080 return not not self.registry[parent]
2081 end
2082  
2083 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)
2084 self:argCheck(parent, 2, "table")
2085 if self.registry[parent] then
2086 self:Unregister(parent)
2087 end
2088 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)
2089 if type(info.children) == "table" then
2090 local err, position = validateOptions(info.children)
2091  
2092 if err then
2093 if position then
2094 Dewdrop:error(position .. ": " .. err)
2095 else
2096 Dewdrop:error(err)
2097 end
2098 end
2099 end
2100 self.registry[parent] = info
2101 if not info.dontHook and not self.onceRegistered[parent] then
2102 if parent:HasScript("OnMouseUp") then
2103 local script = parent:GetScript("OnMouseUp")
2104 parent:SetScript("OnMouseUp", function()
2105 if script then
2106 script()
2107 end
2108 if arg1 == "RightButton" and self.registry[parent] then
2109 if self:IsOpen(parent) then
2110 self:Close()
2111 else
2112 self:Open(parent)
2113 end
2114 end
2115 end)
2116 end
2117 if parent:HasScript("OnMouseDown") then
2118 local script = parent:GetScript("OnMouseDown")
2119 parent:SetScript("OnMouseDown", function()
2120 if script then
2121 script()
2122 end
2123 if self.registry[parent] then
2124 self:Close()
2125 end
2126 end)
2127 end
2128 end
2129 self.onceRegistered[parent] = true
2130 end
2131  
2132 function Dewdrop:Unregister(parent)
2133 self:argCheck(parent, 2, "table")
2134 self.registry[parent] = nil
2135 end
2136  
2137 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)
2138 self:argCheck(parent, 2, "table")
2139 local info
2140 if type(k1) == "table" and k1[0] and k1.IsFrameType and self.registry[k1] then
2141 info = tmp()
2142 for k,v in pairs(self.registry[k1]) do
2143 info[k] = v
2144 end
2145 else
2146 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)
2147 if self.registry[parent] then
2148 for k,v in pairs(self.registry[parent]) do
2149 if info[k] == nil then
2150 info[k] = v
2151 end
2152 end
2153 end
2154 end
2155 local point = info.point
2156 local relativePoint = info.relativePoint
2157 local cursorX = info.cursorX
2158 local cursorY = info.cursorY
2159 if type(point) == "function" then
2160 local b
2161 point, b = point(parent)
2162 if b then
2163 relativePoint = b
2164 end
2165 end
2166 if type(relativePoint) == "function" then
2167 relativePoint = relativePoint(parent)
2168 end
2169 Open(self, parent, info.children, 1, nil, point, relativePoint, cursorX, cursorY)
2170 end
2171  
2172 function Clear(self, level)
2173 if level then
2174 if level.buttons then
2175 for i = table.getn(level.buttons), 1, -1 do
2176 ReleaseButton(self, level, i)
2177 end
2178 end
2179 end
2180 end
2181  
2182 function Dewdrop:Close(level)
2183 if DropDownList1:IsShown() then
2184 DropDownList1:Hide()
2185 end
2186 if DewdropLib then
2187 local d = DewdropLib:GetInstance('1.0')
2188 local ret, val = pcall(d, IsOpen, d)
2189 if ret and val then
2190 DewdropLib:GetInstance('1.0'):Close()
2191 end
2192 end
2193 self:argCheck(level, 2, "number", "nil")
2194 if not level then
2195 level = 1
2196 end
2197 if level == 1 and levels[level] then
2198 levels[level].parented = false
2199 end
2200 if level > 1 and levels[level-1].buttons then
2201 local buttons = levels[level-1].buttons
2202 for _,button in ipairs(buttons) do
2203 button.arrow:SetWidth(16)
2204 button.arrow:SetHeight(16)
2205 -- button.arrow:SetVertexColor(1, 1, 1)
2206 end
2207 end
2208 if sliderFrame and sliderFrame.level >= level then
2209 sliderFrame:Hide()
2210 end
2211 if editBoxFrame and editBoxFrame.level >= level then
2212 editBoxFrame:Hide()
2213 end
2214 for i = level, table.getn(levels) do
2215 Clear(self, levels[level])
2216 levels[level]:Hide()
2217 levels[i]:ClearAllPoints()
2218 levels[i]:SetPoint("CENTER", UIParent, "CENTER")
2219 end
2220 end
2221  
2222 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)
2223 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)
2224 local level = info.level or currentLevel
2225 info.level = nil
2226 local button = AcquireButton(self, level)
2227 if not next(info) then
2228 info.disabled = true
2229 end
2230 button.disabled = info.isTitle or info.notClickable or info.disabled
2231 button.isTitle = info.isTitle
2232 button.notClickable = info.notClickable
2233 if button.isTitle then
2234 button.text:SetFontObject(GameFontNormalSmall)
2235 elseif button.notClickable then
2236 button.text:SetFontObject(GameFontHighlightSmall)
2237 elseif button.disabled then
2238 button.text:SetFontObject(GameFontDisableSmall)
2239 else
2240 button.text:SetFontObject(GameFontHighlightSmall)
2241 end
2242 if info.disabled then
2243 button.arrow:SetDesaturated(true)
2244 button.check:SetDesaturated(true)
2245 else
2246 button.arrow:SetDesaturated(false)
2247 button.check:SetDesaturated(false)
2248 end
2249 if info.textR and info.textG and info.textB then
2250 button.textR = info.textR
2251 button.textG = info.textG
2252 button.textB = info.textB
2253 button.text:SetTextColor(button.textR, button.textG, button.textB)
2254 else
2255 button.text:SetTextColor(button.text:GetFontObject():GetTextColor())
2256 end
2257 button.notCheckable = info.notCheckable
2258 button.text:SetPoint("LEFT", button, "LEFT", button.notCheckable and 0 or 24, 0)
2259 button.checked = not info.notCheckable and info.checked
2260 button.isRadio = not info.notCheckable and info.isRadio
2261 if info.isRadio then
2262 button.check:Show()
2263 button.check:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton")
2264 if button.checked then
2265 button.check:SetTexCoord(0.25, 0.5, 0, 1)
2266 button.check:SetVertexColor(1, 1, 1, 1)
2267 else
2268 button.check:SetTexCoord(0, 0.25, 0, 1)
2269 button.check:SetVertexColor(1, 1, 1, 0.5)
2270 end
2271 button.radioHighlight:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton")
2272 button.check:SetWidth(16)
2273 button.check:SetHeight(16)
2274 elseif info.icon then
2275 button.check:Show()
2276 button.check:SetTexture(info.icon)
2277 if info.iconWidth and info.iconHeight then
2278 button.check:SetWidth(info.iconWidth)
2279 button.check:SetHeight(info.iconHeight)
2280 else
2281 button.check:SetWidth(16)
2282 button.check:SetHeight(16)
2283 end
2284 button.check:SetVertexColor(1, 1, 1, 1)
2285 button.check:SetTexCoord(0, 1, 0, 1)
2286 else
2287 if button.checked then
2288 if info.checkIcon then
2289 button.check:SetWidth(16)
2290 button.check:SetHeight(16)
2291 button.check:SetTexture(info.checkIcon)
2292 if string.sub(info.checkIcon, 1, 16) == "Interface\\Icons\\" then
2293 button.check:SetTexCoord(0.05, 0.95, 0.05, 0.95)
2294 else
2295 button.check:SetTexCoord(0, 1, 0, 1)
2296 end
2297 else
2298 button.check:SetWidth(24)
2299 button.check:SetHeight(24)
2300 button.check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
2301 button.check:SetTexCoord(0, 1, 0, 1)
2302 end
2303 button.check:SetVertexColor(1, 1, 1, 1)
2304 else
2305 button.check:SetVertexColor(1, 1, 1, 0)
2306 end
2307 end
2308 if not button.disabled then
2309 button.func = info.func
2310 end
2311 button.hasColorSwatch = info.hasColorSwatch
2312 if button.hasColorSwatch then
2313 button.colorSwatch:Show()
2314 button.colorSwatch.texture:Show()
2315 button.r = info.r or 1
2316 button.g = info.g or 1
2317 button.b = info.b or 1
2318 button.colorSwatch.texture:SetTexture(button.r, button.g, button.b)
2319 button.checked = false
2320 button.func = nil
2321 button.colorFunc = info.colorFunc
2322 button.colorArg1 = info.colorArg1
2323 button.colorArg2 = info.colorArg2
2324 button.colorArg3 = info.colorArg3
2325 button.colorArg4 = info.colorArg4
2326 button.hasOpacity = info.hasOpacity
2327 button.opacity = info.opacity or 1
2328 else
2329 button.colorSwatch:Hide()
2330 button.colorSwatch.texture:Hide()
2331 end
2332 button.hasArrow = not button.hasColorSwatch and (info.value or info.hasSlider or info.hasEditBox) and info.hasArrow
2333 if button.hasArrow then
2334 button.arrow:SetAlpha(1)
2335 if info.hasSlider then
2336 button.hasSlider = true
2337 button.sliderMin = info.sliderMin or 0
2338 button.sliderMax = info.sliderMax or 1
2339 button.sliderStep = info.sliderStep or 0
2340 button.sliderIsPercent = info.sliderIsPercent and true or false
2341 button.sliderMinText = info.sliderMinText or button.sliderIsPercent and string.format("%.0f%%", button.sliderMin * 100) or button.sliderMin
2342 button.sliderMaxText = info.sliderMaxText or button.sliderIsPercent and string.format("%.0f%%", button.sliderMax * 100) or button.sliderMax
2343 button.sliderFunc = info.sliderFunc
2344 button.sliderValue = info.sliderValue
2345 button.sliderArg1 = info.sliderArg1
2346 button.sliderArg2 = info.sliderArg2
2347 button.sliderArg3 = info.sliderArg3
2348 button.sliderArg4 = info.sliderArg4
2349 elseif info.hasEditBox then
2350 button.hasEditBox = true
2351 button.editBoxText = info.editBoxText or ""
2352 button.editBoxFunc = info.editBoxFunc
2353 button.editBoxArg1 = info.editBoxArg1
2354 button.editBoxArg2 = info.editBoxArg2
2355 button.editBoxArg3 = info.editBoxArg3
2356 button.editBoxArg4 = info.editBoxArg4
2357 button.editBoxChangeFunc = info.editBoxChangeFunc
2358 button.editBoxChangeArg1 = info.editBoxChangeArg1
2359 button.editBoxChangeArg2 = info.editBoxChangeArg2
2360 button.editBoxChangeArg3 = info.editBoxChangeArg3
2361 button.editBoxChangeArg4 = info.editBoxChangeArg4
2362 button.editBoxValidateFunc = info.editBoxValidateFunc
2363 button.editBoxValidateArg1 = info.editBoxValidateArg1
2364 button.editBoxValidateArg2 = info.editBoxValidateArg2
2365 button.editBoxValidateArg3 = info.editBoxValidateArg3
2366 button.editBoxValidateArg4 = info.editBoxValidateArg4
2367 else
2368 button.value = info.value
2369 end
2370 else
2371 button.arrow:SetAlpha(0)
2372 end
2373 button.arg1 = info.arg1
2374 button.arg2 = info.arg2
2375 button.arg3 = info.arg3
2376 button.arg4 = info.arg4
2377 button.closeWhenClicked = info.closeWhenClicked
2378 button.textHeight = info.textHeight or UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT or 10
2379 local font,_ = button.text:GetFont()
2380 button.text:SetFont(STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF", button.textHeight)
2381 button:SetHeight(button.textHeight + 6)
2382 button.text:SetPoint("RIGHT", button.arrow, (button.hasColorSwatch or button.hasArrow) and "LEFT" or "RIGHT")
2383 button.text:SetJustifyH(info.justifyH or "LEFT")
2384 button.text:SetText(info.text)
2385 button.tooltipTitle = info.tooltipTitle
2386 button.tooltipText = info.tooltipText
2387 button.tooltipFunc = info.tooltipFunc
2388 button.tooltipArg1 = info.tooltipArg1
2389 button.tooltipArg2 = info.tooltipArg2
2390 button.tooltipArg3 = info.tooltipArg3
2391 button.tooltipArg4 = info.tooltipArg4
2392 if not button.tooltipTitle and not button.tooltipText and not button.tooltipFunc and not info.isTitle then
2393 button.tooltipTitle = info.text
2394 end
2395 if type(button.func) == "string" then
2396 self:assert(type(button.arg1) == "table", "Cannot call method " .. button.func .. " on a non-table")
2397 self:assert(type(button.arg1[button.func]) == "function", "Method " .. button.func .. " nonexistant.")
2398 end
2399 end
2400  
2401 function Dewdrop:InjectAceOptionsTable(handler, options)
2402 self:argCheck(handler, 2, "table")
2403 self:argCheck(options, 3, "table")
2404 if string.lower(tostring(options.type)) ~= "group" then
2405 self:error('Cannot inject into options table argument #3 if its type is not "group"')
2406 end
2407 if options.handler ~= nil and options.handler ~= handler then
2408 self:error("Cannot inject into options table argument #3 if it has a different handler than argument #2")
2409 end
2410 options.handler = handler
2411 local class = handler.class
2412 if not AceLibrary:HasInstance("AceOO-2.0") or not class then
2413 self:error("Cannot retrieve AceOptions tables from a non-object argument #2")
2414 end
2415 while class and class ~= AceLibrary("AceOO-2.0").Class do
2416 if type(class.GetAceOptionsDataTable) == "function" then
2417 local t = class:GetAceOptionsDataTable(handler)
2418 for k,v in pairs(t) do
2419 if type(options.args) ~= "table" then
2420 options.args = {}
2421 end
2422 if options.args[k] == nil then
2423 options.args[k] = v
2424 end
2425 end
2426 end
2427 local mixins = class.mixins
2428 if mixins then
2429 for mixin in pairs(mixins) do
2430 if type(mixin.GetAceOptionsDataTable) == "function" then
2431 local t = mixin:GetAceOptionsDataTable(handler)
2432 for k,v in pairs(t) do
2433 if type(options.args) ~= "table" then
2434 options.args = {}
2435 end
2436 if options.args[k] == nil then
2437 options.args[k] = v
2438 end
2439 end
2440 end
2441 end
2442 end
2443 class = class.super
2444 end
2445 return options
2446 end
2447  
2448 local function activate(self, oldLib, oldDeactivate)
2449 Dewdrop = self
2450 if oldLib and oldLib.registry then
2451 self.registry = oldLib.registry
2452 self.onceRegistered = oldLib.onceRegistered
2453 else
2454 self.registry = {}
2455 self.onceRegistered = {}
2456  
2457 local WorldFrame_OnMouseDown = WorldFrame:GetScript("OnMouseDown")
2458 local WorldFrame_OnMouseUp = WorldFrame:GetScript("OnMouseUp")
2459 local oldX, oldY, clickTime
2460 WorldFrame:SetScript("OnMouseDown", function()
2461 oldX,oldY = GetCursorPosition()
2462 clickTime = GetTime()
2463 if WorldFrame_OnMouseDown then
2464 WorldFrame_OnMouseDown()
2465 end
2466 end)
2467  
2468 WorldFrame:SetScript("OnMouseUp", function()
2469 local x,y = GetCursorPosition()
2470 if not oldX or not oldY or not x or not y or not clickTime then
2471 self:Close()
2472 if WorldFrame_OnMouseUp then
2473 WorldFrame_OnMouseUp()
2474 end
2475 return
2476 end
2477 local d = math.abs(x - oldX) + math.abs(y - oldY)
2478 if d <= 5 and GetTime() - clickTime < 0.5 then
2479 self:Close()
2480 end
2481 if WorldFrame_OnMouseUp then
2482 WorldFrame_OnMouseUp()
2483 end
2484 end)
2485  
2486 if hooksecurefunc then
2487 hooksecurefunc(DropDownList1, "Show", function()
2488 if levels[1] and levels[1]:IsVisible() then
2489 self:Close()
2490 end
2491 end)
2492 else
2493 local DropDownList1_Show = DropDownList1.Show
2494 function DropDownList1.Show(DropDownList1)
2495 if levels[1] and levels[1]:IsVisible() then
2496 self:Close()
2497 end
2498 DropDownList1_Show(DropDownList1)
2499 end
2500 end
2501  
2502 if hooksecurefunc then
2503 hooksecurefunc("HideDropDownMenu", function()
2504 if levels[1] and levels[1]:IsVisible() then
2505 self:Close()
2506 end
2507 end)
2508 else
2509 local old_HideDropDownMenu = HideDropDownMenu
2510 function HideDropDownMenu(num)
2511 if levels[1] and levels[1]:IsVisible() then
2512 self:Close()
2513 end
2514 old_HideDropDownMenu(num)
2515 end
2516 end
2517  
2518 if hooksecurefunc then
2519 hooksecurefunc("CloseDropDownMenus", function()
2520 if levels[1] and levels[1]:IsVisible() then
2521 self:Close()
2522 end
2523 end)
2524 else
2525 local old_CloseDropDownMenus = CloseDropDownMenus
2526 function CloseDropDownMenus(num)
2527 if levels[1] and levels[1]:IsVisible() then
2528 self:Close()
2529 end
2530 old_CloseDropDownMenus(num)
2531 end
2532 end
2533 end
2534 levels = {}
2535 buttons = {}
2536  
2537 if oldDeactivate then
2538 oldDeactivate(oldLib)
2539 end
2540 end
2541  
2542 AceLibrary:Register(Dewdrop, MAJOR_VERSION, MINOR_VERSION, activate)