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