vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 local MAJOR_VERSION = "1.0"
2 local MINOR_VERSION = tonumber(string.sub("$Revision: 6288 $", 12, -3))
3 if DewdropLib and DewdropLib.versions[MAJOR_VERSION] and DewdropLib.versions[MAJOR_VERSION].minor >= MINOR_VERSION then
4 return
5 end
6  
7 -------------IRIEL'S-STUB-CODE--------------
8 local stub = {};
9  
10 -- Instance replacement method, replace contents of old with that of new
11 function stub:ReplaceInstance(old, new)
12 for k,v in pairs(old) do old[k]=nil; end
13 for k,v in pairs(new) do old[k]=v; end
14 end
15  
16 -- Get a new copy of the stub
17 function stub:NewStub()
18 local newStub = {};
19 self:ReplaceInstance(newStub, self);
20 newStub.lastVersion = '';
21 newStub.versions = {};
22 return newStub;
23 end
24  
25 -- Get instance version
26 function stub:GetInstance(version)
27 if (not version) then version = self.lastVersion; end
28 local versionData = self.versions[version];
29 if (not versionData) then
30 message("Cannot find library instance with version '"
31 .. version .. "'");
32 return;
33 end
34 return versionData.instance;
35 end
36  
37 -- Register new instance
38 function stub:Register(newInstance)
39 local version,minor = newInstance:GetLibraryVersion();
40 self.lastVersion = version;
41 local versionData = self.versions[version];
42 if (not versionData) then
43 -- This one is new!
44 versionData = { instance = newInstance,
45 minor = minor,
46 old = {}
47 };
48 self.versions[version] = versionData;
49 newInstance:LibActivate(self);
50 return newInstance;
51 end
52 if (minor <= versionData.minor) then
53 -- This one is already obsolete
54 if (newInstance.LibDiscard) then
55 newInstance:LibDiscard();
56 end
57 return versionData.instance;
58 end
59 -- This is an update
60 local oldInstance = versionData.instance;
61 local oldList = versionData.old;
62 versionData.instance = newInstance;
63 versionData.minor = minor;
64 local skipCopy = newInstance:LibActivate(self, oldInstance, oldList);
65 table.insert(oldList, oldInstance);
66 if (not skipCopy) then
67 for i, old in ipairs(oldList) do
68 self:ReplaceInstance(old, newInstance);
69 end
70 end
71 return newInstance;
72 end
73  
74 -- Bind stub to global scope if it's not already there
75 if (not DewdropLib) then
76 DewdropLib = stub:NewStub();
77 end
78  
79 -- Nil stub for garbage collection
80 stub = nil;
81 -----------END-IRIEL'S-STUB-CODE------------
82  
83 local function assert(condition, message)
84 if not condition then
85 local stack = debugstack()
86 local first = string.gsub(stack, "\n.*", "")
87 local file = string.gsub(first, "^(.*\\.*).lua:%d+: .*", "%1")
88 file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
89 if not message then
90 local _,_,second = string.find(stack, "\n(.-)\n")
91 message = "assertion failed! " .. second
92 end
93 message = "DewdropLib: " .. message
94 local i = 1
95 for s in string.gfind(stack, "\n([^\n]*)") do
96 i = i + 1
97 if not string.find(s, file .. "%.lua:%d+:") then
98 error(message, i)
99 return
100 end
101 end
102 error(message, 2)
103 return
104 end
105 return condition
106 end
107  
108 local function argCheck(arg, num, kind, kind2, kind3, kind4)
109 if tostring(type(arg)) ~= kind then
110 if kind2 then
111 if tostring(type(arg)) ~= kind2 then
112 if kind3 then
113 if tostring(type(arg)) ~= kind3 then
114 if kind4 then
115 if tostring(type(arg)) ~= kind4 then
116 local _,_,func = string.find(debugstack(), "\n.-`(.-)'\n")
117 assert(false, format("Bad argument #%d to `%s' (%s, %s, %s, or %s expected, got %s)", num, func, kind, kind2, kind3, kind4, type(arg)))
118 end
119 else
120 local _,_,func = string.find(debugstack(), "\n.-`(.-)'\n")
121 assert(false, format("Bad argument #%d to `%s' (%s, %s, or %s expected, got %s)", num, func, kind, kind2, kind3, type(arg)))
122 end
123 end
124 else
125 local _,_,func = string.find(debugstack(), "\n.-`(.-)'\n")
126 assert(false, format("Bad argument #%d to `%s' (%s or %s expected, got %s)", num, func, kind, kind2, type(arg)))
127 end
128 end
129 else
130 local _,_,func = string.find(debugstack(), "\n.-`(.-)'\n")
131 assert(false, format("Bad argument #%d to `%s' (%s expected, got %s)", num, func, kind, type(arg)))
132 end
133 end
134 end
135  
136 local lib = {}
137 local ipairs = ipairs
138 local tinsert = table.insert
139 local tremove = table.remove
140 local tgetn = table.getn
141 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)
142 local t = {}
143 if k1 then t[k1] = v1
144 if k2 then t[k2] = v2
145 if k3 then t[k3] = v3
146 if k4 then t[k4] = v4
147 if k5 then t[k5] = v5
148 if k6 then t[k6] = v6
149 if k7 then t[k7] = v7
150 if k8 then t[k8] = v8
151 if k9 then t[k9] = v9
152 if k10 then t[k10] = v10
153 if k11 then t[k11] = v11
154 if k12 then t[k12] = v12
155 if k13 then t[k13] = v13
156 if k14 then t[k14] = v14
157 if k15 then t[k15] = v15
158 if k16 then t[k16] = v16
159 if k17 then t[k17] = v17
160 if k18 then t[k18] = v18
161 if k19 then t[k19] = v19
162 if k20 then t[k20] = v20
163 end end end end end end end end end end end end end end end end end end end end
164 return t
165 end
166 local tmp
167 do
168 local t
169 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)
170 for k in pairs(t) do
171 t[k] = nil
172 end
173 if k1 then t[k1] = v1
174 if k2 then t[k2] = v2
175 if k3 then t[k3] = v3
176 if k4 then t[k4] = v4
177 if k5 then t[k5] = v5
178 if k6 then t[k6] = v6
179 if k7 then t[k7] = v7
180 if k8 then t[k8] = v8
181 if k9 then t[k9] = v9
182 if k10 then t[k10] = v10
183 if k11 then t[k11] = v11
184 if k12 then t[k12] = v12
185 if k13 then t[k13] = v13
186 if k14 then t[k14] = v14
187 if k15 then t[k15] = v15
188 if k16 then t[k16] = v16
189 if k17 then t[k17] = v17
190 if k18 then t[k18] = v18
191 if k19 then t[k19] = v19
192 if k20 then t[k20] = v20
193 end end end end end end end end end end end end end end end end end end end end
194 return t
195 end
196 local x = tmp
197 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)
198 t = {}
199 tmp = x
200 x = nil
201 return tmp(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20)
202 end
203 end
204 local tmp2
205 do
206 local t
207 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)
208 for k in pairs(t) do
209 t[k] = nil
210 end
211 if k1 then t[k1] = v1
212 if k2 then t[k2] = v2
213 if k3 then t[k3] = v3
214 if k4 then t[k4] = v4
215 if k5 then t[k5] = v5
216 if k6 then t[k6] = v6
217 if k7 then t[k7] = v7
218 if k8 then t[k8] = v8
219 if k9 then t[k9] = v9
220 if k10 then t[k10] = v10
221 if k11 then t[k11] = v11
222 if k12 then t[k12] = v12
223 if k13 then t[k13] = v13
224 if k14 then t[k14] = v14
225 if k15 then t[k15] = v15
226 if k16 then t[k16] = v16
227 if k17 then t[k17] = v17
228 if k18 then t[k18] = v18
229 if k19 then t[k19] = v19
230 if k20 then t[k20] = v20
231 end end end end end end end end end end end end end end end end end end end end
232 return t
233 end
234 local x = tmp2
235 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)
236 t = {}
237 tmp2 = x
238 x = nil
239 return tmp2(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5, k6, v6, k7, v7, k8, v8, k9, v9, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16, k17, v17, k18, v18, k19, v19, k20, v20)
240 end
241 end
242 --local levels
243 local buttons
244  
245 function lib:GetLibraryVersion()
246 return MAJOR_VERSION, MINOR_VERSION
247 end
248  
249 function lib:LibActivate(stub, oldLib, oldList)
250 if oldLib and oldLib.registry then
251 self.registry = oldLib.registry
252 self.onceRegistered = oldLib.onceRegistered
253 else
254 self.registry = {}
255 self.onceRegistered = {}
256  
257 local WorldFrame_OnMouseDown = WorldFrame:GetScript("OnMouseDown")
258 local WorldFrame_OnMouseUp = WorldFrame:GetScript("OnMouseUp")
259 local oldX, oldY, clickTime
260 WorldFrame:SetScript("OnMouseDown", function()
261 oldX,oldY = GetCursorPosition()
262 clickTime = GetTime()
263 if WorldFrame_OnMouseDown then
264 WorldFrame_OnMouseDown()
265 end
266 end)
267  
268 WorldFrame:SetScript("OnMouseUp", function()
269 local x,y = GetCursorPosition()
270 if not oldX or not oldY or not x or not y or not clickTime then
271 self:Close()
272 if WorldFrame_OnMouseUp then
273 WorldFrame_OnMouseUp()
274 end
275 return
276 end
277 local d = math.abs(x - oldX) + math.abs(y - oldY)
278 if d <= 5 and GetTime() - clickTime < 0.5 then
279 self:Close()
280 end
281 if WorldFrame_OnMouseUp then
282 WorldFrame_OnMouseUp()
283 end
284 end)
285  
286 local DropDownList1_Show = DropDownList1.Show
287 function DropDownList1.Show(DropDownList1)
288 if levels[1] and levels[1]:IsVisible() then
289 self:Close()
290 end
291 DropDownList1_Show(DropDownList1)
292 end
293  
294 local old_HideDropDownMenu = HideDropDownMenu
295 function HideDropDownMenu(num)
296 if levels[1] and levels[1]:IsVisible() then
297 self:Close()
298 end
299 old_HideDropDownMenu(num)
300 end
301  
302 local old_CloseDropDownMenus = CloseDropDownMenus
303 function CloseDropDownMenus(num)
304 if levels[1] and levels[1]:IsVisible() then
305 self:Close()
306 end
307 old_CloseDropDownMenus(num)
308 end
309 end
310 levels = {}
311 buttons = {}
312 end
313  
314 function lib:LibDeactivate(stub)
315 levels = nil
316 buttons = nil
317 end
318  
319 local function StartCounting(self, levelNum)
320 for i = levelNum, tgetn(levels) do
321 if levels[i] then
322 levels[i].count = 3
323 end
324 end
325 end
326  
327 local function StopCounting(self, level)
328 for i = level, 1, -1 do
329 if levels[i] then
330 levels[i].count = nil
331 end
332 end
333 end
334  
335 local function OnUpdate(self, arg1)
336 for _,level in ipairs(levels) do
337 if level.count then
338 level.count = level.count - arg1
339 if level.count < 0 then
340 level.count = nil
341 self:Close(level.num)
342 end
343 end
344 end
345 end
346  
347 local function CheckDualMonitor(self, frame)
348 local ratio = GetScreenWidth() / GetScreenHeight()
349 if ratio >= 2.4 and frame:GetRight() > GetScreenWidth() / 2 and frame:GetLeft() < GetScreenWidth() / 2 then
350 local offsetx
351 if GetCursorPosition() / GetScreenHeight() * 768 < GetScreenWidth() / 2 then
352 offsetx = GetScreenWidth() / 2 - frame:GetRight()
353 else
354 offsetx = GetScreenWidth() / 2 - frame:GetLeft()
355 end
356 local point, parent, relativePoint, x, y = frame:GetPoint(1)
357 frame:SetPoint(point, parent, relativePoint, (x or 0) + offsetx, y or 0)
358 end
359 end
360  
361 local function CheckSize(self, level)
362 if not level.buttons then
363 return
364 end
365 local height = 20
366 for _, button in ipairs(level.buttons) do
367 height = height + button:GetHeight()
368 end
369 level:SetHeight(height)
370 local width = 160
371 for _, button in ipairs(level.buttons) do
372 local extra = 1
373 if button.hasArrow or button.hasColorSwatch then
374 extra = extra + 16
375 end
376 if not button.notCheckable then
377 extra = extra + 24
378 end
379 button.text:SetFont(STANDARD_TEXT_FONT, button.textHeight)
380 if button.text:GetWidth() + extra > width then
381 width = button.text:GetWidth() + extra
382 end
383 end
384 level:SetWidth(width + 20)
385 if level:GetLeft() and level:GetTop() and level:GetLeft() < 0 or level:GetRight() > GetScreenWidth() or level:GetTop() > GetScreenHeight() or level:GetBottom() < 0 then
386 level:ClearAllPoints()
387 if level.lastDirection == "RIGHT" then
388 if level.lastVDirection == "DOWN" then
389 level:SetPoint("TOPLEFT", level.parent or level:GetParent(), "TOPRIGHT", 5, 10)
390 else
391 level:SetPoint("BOTTOMLEFT", level.parent or level:GetParent(), "BOTTOMRIGHT", 5, -10)
392 end
393 else
394 if level.lastVDirection == "DOWN" then
395 level:SetPoint("TOPRIGHT", level.parent or level:GetParent(), "TOPLEFT", -5, 10)
396 else
397 level:SetPoint("BOTTOMRIGHT", level.parent or level:GetParent(), "BOTTOMLEFT", -5, -10)
398 end
399 end
400 end
401 local dirty = false
402 if not level:GetRight() then
403 self:Close()
404 return
405 end
406 if level:GetRight() > GetScreenWidth() and level.lastDirection == "RIGHT" then
407 level.lastDirection = "LEFT"
408 dirty = true
409 elseif level:GetLeft() < 0 and level.lastDirection == "LEFT" then
410 level.lastDirection = "RIGHT"
411 dirty = true
412 end
413 if level:GetTop() > GetScreenHeight() and level.lastVDirection == "UP" then
414 level.lastVDirection = "DOWN"
415 dirty = true
416 elseif level:GetBottom() < 0 and level.lastVDirection == "DOWN" then
417 level.lastVDirection = "UP"
418 dirty = true
419 end
420 if dirty then
421 level:ClearAllPoints()
422 if level.lastDirection == "RIGHT" then
423 if level.lastVDirection == "DOWN" then
424 level:SetPoint("TOPLEFT", level.parent or level:GetParent(), "TOPRIGHT", 5, 10)
425 else
426 level:SetPoint("BOTTOMLEFT", level.parent or level:GetParent(), "BOTTOMRIGHT", 5, -10)
427 end
428 else
429 if level.lastVDirection == "DOWN" then
430 level:SetPoint("TOPRIGHT", level.parent or level:GetParent(), "TOPLEFT", -5, 10)
431 else
432 level:SetPoint("BOTTOMRIGHT", level.parent or level:GetParent(), "BOTTOMLEFT", -5, -10)
433 end
434 end
435 end
436 if level:GetTop() > GetScreenHeight() then
437 local top = level:GetTop()
438 local point, parent, relativePoint, x, y = level:GetPoint(1)
439 level:ClearAllPoints()
440 level:SetPoint(point, parent, relativePoint, x or 0, (y or 0) + GetScreenHeight() - top)
441 elseif level:GetBottom() < 0 then
442 local bottom = level:GetBottom()
443 local point, parent, relativePoint, x, y = level:GetPoint(1)
444 level:ClearAllPoints()
445 level:SetPoint(point, parent, relativePoint, x or 0, (y or 0) - bottom)
446 end
447 CheckDualMonitor(self, level)
448 if mod(level.num, 5) == 0 then
449 local left, bottom = level:GetLeft(), level:GetBottom()
450 level:ClearAllPoints()
451 level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom)
452 end
453 end
454  
455 local Open
456 local OpenSlider
457 local OpenEditBox
458 local Refresh
459 local Clear
460 local function ReleaseButton(self, level, index)
461 if not level.buttons then
462 return
463 end
464 if not level.buttons[index] then
465 return
466 end
467 local button = level.buttons[index]
468 button:Hide()
469 if button.highlight then
470 button.highlight:Hide()
471 end
472 tremove(level.buttons, index)
473 tinsert(buttons, button)
474 for k in pairs(button) do
475 if k ~= 0 and k ~= "text" and k ~= "check" and k ~= "arrow" and k ~= "colorSwatch" and k ~= "highlight" and k ~= "radioHighlight" then
476 button[k] = nil
477 end
478 end
479 return true
480 end
481  
482 local function Scroll(self, level, down)
483 if down then
484 if level:GetBottom() < 0 then
485 local point, parent, relativePoint, x, y = level:GetPoint(1)
486 level:SetPoint(point, parent, relativePoint, x, y + 50)
487 if level:GetBottom() > 0 then
488 level:SetPoint(point, parent, relativePoint, x, y + 50 - level:GetBottom())
489 end
490 end
491 else
492 if level:GetTop() > GetScreenHeight() then
493 local point, parent, relativePoint, x, y = level:GetPoint(1)
494 level:SetPoint(point, parent, relativePoint, x, y - 50)
495 if level:GetTop() < GetScreenHeight() then
496 level:SetPoint(point, parent, relativePoint, x, y - 50 + GetScreenHeight() - level:GetTop())
497 end
498 end
499 end
500 end
501  
502 local sliderFrame
503 local editBoxFrame
504  
505 local function AcquireButton(self, level)
506 if not levels[level] then
507 return
508 end
509 level = levels[level]
510 if not level.buttons then
511 level.buttons = {}
512 end
513 local button
514 if tgetn(buttons) == 0 then
515 button = CreateFrame("Button")
516 button:SetFrameStrata("FULLSCREEN_DIALOG")
517 button:SetHeight(16)
518 local highlight = button:CreateTexture(nil, "BACKGROUND")
519 highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
520 button.highlight = highlight
521 highlight:SetBlendMode("ADD")
522 highlight:SetAllPoints(button)
523 highlight:Hide()
524 local check = button:CreateTexture(nil, "ARTWORK")
525 button.check = check
526 check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
527 check:SetPoint("CENTER", button, "LEFT", 12, 0)
528 check:SetWidth(24)
529 check:SetHeight(24)
530 local radioHighlight = button:CreateTexture(nil, "ARTWORK")
531 button.radioHighlight = radioHighlight
532 radioHighlight:SetTexture("Interface\\Buttons\\UI-RadioButton")
533 radioHighlight:SetAllPoints(check)
534 radioHighlight:SetBlendMode("ADD")
535 radioHighlight:SetTexCoord(0.5, 0.75, 0, 1)
536 radioHighlight:Hide()
537 button:SetScript("OnEnter", function()
538 if sliderFrame and sliderFrame:IsShown() and sliderFrame.mouseDown and sliderFrame.level == this.level.num + 1 then
539 Refresh(self, this.level)
540 return
541 elseif editBoxFrame and editBoxFrame:IsShown() and editBoxFrame.mouseDown and editBoxFrame.level == this.level.num + 1 then
542 Refresh(self, this.level)
543 return
544 end
545 self:Close(this.level.num + 1)
546 if this.hasSlider then
547 OpenSlider(self, this)
548 elseif this.hasEditBox then
549 OpenEditBox(self, this)
550 elseif this.hasArrow then
551 Open(self, this, nil, this.level.num + 1, this.value)
552 end
553 StopCounting(self, this.level.num + 1)
554 if not this.disabled then
555 highlight:Show()
556 if this.isRadio then
557 button.radioHighlight:Show()
558 end
559 end
560 if this.tooltipTitle then
561 GameTooltip_AddNewbieTip(this.tooltipTitle, 1.0, 1.0, 1.0, this.tooltipText, 1)
562 end
563 if this.tooltipFunc then
564 GameTooltip:SetOwner(this, "ANCHOR_NONE")
565 GameTooltip:SetPoint("TOPLEFT", this, "TOPRIGHT", 5, 0)
566 this.tooltipFunc(this.tooltipArg1, this.tooltipArg2, this.tooltipArg3, this.tooltipArg4)
567 GameTooltip:Show()
568 end
569 end)
570 button:SetScript("OnLeave", function()
571 highlight:Hide()
572 button.radioHighlight:Hide()
573 if this.level then
574 StartCounting(self, this.level.num)
575 end
576 GameTooltip:Hide()
577 end)
578 button:SetScript("OnClick", function()
579 if not this.disabled then
580 if this.hasColorSwatch then
581 local func = button.swatchFunc
582 ColorPickerFrame.func = function()
583 if func then
584 func(ColorPickerFrame:GetColorRGB())
585 end
586 end
587 ColorPickerFrame.hasOpacity = this.hasOpacity
588 local func = this.opacityFunc
589 ColorPickerFrame.opacityFunc = function()
590 if func then
591 func(1 - OpacitySliderFrame:GetValue())
592 end
593 end
594 ColorPickerFrame.opacity = 1 - this.opacity
595 ColorPickerFrame:SetColorRGB(this.r, this.g, this.b)
596 if this.cancelFunc then
597 local r, g, b, a = this.r, this.g, this.b, this.opacity
598 local func = this.cancelFunc
599 ColorPickerFrame.cancelFunc = function()
600 func(r, g, b, a)
601 end
602 end
603 self:Close(1)
604 ShowUIPanel(ColorPickerFrame)
605 elseif this.func then
606 local level = button.level
607 if type(this.func) == "string" then
608 assert(type(this.arg1[this.func]) == "function", "Cannot call method " .. this.func)
609 this.arg1[this.func](this.arg1, this.arg2, this.arg3, this.arg4)
610 else
611 this.func(this.arg1, this.arg2, this.arg3, this.arg4)
612 end
613 if this.closeWhenClicked then
614 self:Close()
615 elseif level:IsShown() then
616 Refresh(self, level)
617 end
618 elseif this.closeWhenClicked then
619 self:Close()
620 end
621 end
622 end)
623 local text = button:CreateFontString(nil, "ARTWORK")
624 button.text = text
625 text:SetFontObject(GameFontHighlightSmall)
626 button.text:SetFont(STANDARD_TEXT_FONT, UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT)
627 button:SetScript("OnMouseDown", function()
628 if not this.disabled and (this.func or this.swatchFunc or this.closeWhenClicked) then
629 text:SetPoint("LEFT", button, "LEFT", this.notCheckable and 1 or 25, -1)
630 end
631 end)
632 button:SetScript("OnMouseUp", function()
633 if not this.disabled and (this.func or this.swatchFunc or this.closeWhenClicked) then
634 text:SetPoint("LEFT", button, "LEFT", this.notCheckable and 0 or 24, 0)
635 end
636 end)
637 local arrow = button:CreateTexture(nil, "ARTWORK")
638 button.arrow = arrow
639 arrow:SetPoint("RIGHT", button, "RIGHT", 0, 0)
640 arrow:SetWidth(16)
641 arrow:SetHeight(16)
642 arrow:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow")
643 local colorSwatch = button:CreateTexture(nil, "OVERLAY")
644 button.colorSwatch = colorSwatch
645 colorSwatch:SetWidth(20)
646 colorSwatch:SetHeight(20)
647 colorSwatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch")
648 local texture = button:CreateTexture(nil, "OVERLAY")
649 colorSwatch.texture = texture
650 texture:SetTexture(1, 1, 1)
651 texture:SetWidth(11.5)
652 texture:SetHeight(11.5)
653 texture:Show()
654 texture:SetPoint("CENTER", colorSwatch, "CENTER")
655 colorSwatch:SetPoint("RIGHT", button, "RIGHT", 0, 0)
656 else
657 button = buttons[tgetn(buttons)]
658 tremove(buttons, tgetn(buttons))
659 end
660 button:SetParent(level)
661 button:SetFrameStrata(level:GetFrameStrata())
662 button:SetFrameLevel(level:GetFrameLevel() + 1)
663 button:SetPoint("LEFT", level, "LEFT", 10, 0)
664 button:SetPoint("RIGHT", level, "RIGHT", -10, 0)
665 if tgetn(level.buttons) == 0 then
666 button:SetPoint("TOP", level, "TOP", 0, -10)
667 else
668 button:SetPoint("TOP", level.buttons[tgetn(level.buttons)], "BOTTOM", 0, 0)
669 end
670 button.text:SetPoint("LEFT", button, "LEFT", 24, 0)
671 button:Show()
672 button.level = level
673 tinsert(level.buttons, button)
674 if not level.parented then
675 level.parented = true
676 level:ClearAllPoints()
677 if level.num == 1 then
678 if level.parent ~= UIParent then
679 level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT")
680 else
681 level:SetPoint("CENTER", level.parent, "CENTER")
682 end
683 else
684 if level.lastDirection == "RIGHT" then
685 if level.lastVDirection == "DOWN" then
686 level:SetPoint("TOPLEFT", level.parent, "TOPRIGHT", 5, 10)
687 else
688 level:SetPoint("BOTTOMLEFT", level.parent, "BOTTOMRIGHT", 5, -10)
689 end
690 else
691 if level.lastVDirection == "DOWN" then
692 level:SetPoint("TOPRIGHT", level.parent, "TOPLEFT", -5, 10)
693 else
694 level:SetPoint("BOTTOMRIGHT", level.parent, "BOTTOMLEFT", -5, -10)
695 end
696 end
697 end
698 level:SetFrameStrata("TOOLTIP")
699 end
700 return button
701 end
702  
703 local function AcquireLevel(self, level)
704 if not levels[level] then
705 for i = tgetn(levels) + 1, level, -1 do
706 local i = i
707 local frame = CreateFrame("Button")
708 if i == 1 then
709 local old_CloseWindows = CloseWindows
710 function CloseWindows(ignoreCenter)
711 local found = old_CloseWindows(ignoreCenter)
712 if levels[1]:IsShown() then
713 self:Close()
714 return 1
715 end
716 return found
717 end
718 end
719 levels[i] = frame
720 frame.num = i
721 frame:SetParent(UIParent)
722 frame:SetFrameStrata("TOOLTIP")
723 frame:Hide()
724 frame:SetWidth(180)
725 frame:SetHeight(10)
726 frame:SetFrameLevel(i * 3)
727 frame:SetScript("OnHide", function()
728 self:Close(level + 1)
729 end)
730 frame:SetFrameStrata("FULLSCREEN_DIALOG")
731 if frame.SetTopLevel then
732 frame:SetTopLevel(true)
733 end
734 frame:EnableMouse(true)
735 frame:EnableMouseWheel(true)
736 local backdrop = CreateFrame("Frame", nil, frame)
737 backdrop:SetAllPoints(frame)
738 backdrop:SetBackdrop(tmp(
739 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background",
740 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border",
741 'tile', true,
742 'insets', tmp2(
743 'left', 5,
744 'right', 5,
745 'top', 5,
746 'bottom', 5
747 ),
748 'tileSize', 16,
749 'edgeSize', 16
750 ))
751 backdrop:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
752 backdrop:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b)
753 frame:SetScript("OnClick", function()
754 self:Close(i)
755 end)
756 frame:SetScript("OnEnter", function()
757 StopCounting(self, i)
758 end)
759 frame:SetScript("OnLeave", function()
760 StartCounting(self, i)
761 end)
762 frame:SetScript("OnMouseWheel", function()
763 Scroll(self, frame, arg1 < 0)
764 end)
765 if i == 1 then
766 frame:SetScript("OnUpdate", function()
767 OnUpdate(self, arg1)
768 end)
769 levels[1].lastDirection = "RIGHT"
770 levels[1].lastVDirection = "DOWN"
771 else
772 levels[i].lastDirection = levels[i - 1].lastDirection
773 levels[i].lastVDirection = levels[i - 1].lastVDirection
774 end
775 end
776 end
777 return levels[level]
778 end
779  
780 local baseFunc, currentLevel
781 function Refresh(self, level)
782 if type(level) == "number" then
783 level = levels[level]
784 end
785 if not level then
786 return
787 end
788 if baseFunc then
789 currentLevel = level.num
790 Clear(self, level)
791 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)
792 CheckSize(self, level)
793 end
794 end
795  
796 function lib:Refresh(level)
797 argCheck(level, 2, "number")
798 Refresh(self, levels[level])
799 end
800  
801 function OpenSlider(self, parent)
802 if not sliderFrame then
803 sliderFrame = CreateFrame("Frame", nil, UIParent)
804 sliderFrame:SetWidth(80)
805 sliderFrame:SetHeight(170)
806 sliderFrame:SetBackdrop(tmp(
807 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background",
808 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border",
809 'tile', true,
810 'insets', tmp2(
811 'left', 5,
812 'right', 5,
813 'top', 5,
814 'bottom', 5
815 ),
816 'tileSize', 16,
817 'edgeSize', 16
818 ))
819 sliderFrame:SetFrameStrata("TOOLTIP")
820 if sliderFrame.SetTopLevel then
821 sliderFrame:SetTopLevel(true)
822 end
823 sliderFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
824 sliderFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b)
825 sliderFrame:EnableMouse(true)
826 sliderFrame:Hide()
827 sliderFrame:SetPoint("CENTER", UIParent, "CENTER")
828 local slider = CreateFrame("Slider", nil, sliderFrame)
829 sliderFrame.slider = slider
830 slider:SetOrientation("VERTICAL")
831 slider:SetMinMaxValues(0, 1)
832 slider:SetValueStep(0.01)
833 slider:SetValue(0.5)
834 slider:SetWidth(16)
835 slider:SetHeight(128)
836 slider:SetPoint("LEFT", sliderFrame, "LEFT", 15, 0)
837 slider:SetBackdrop(tmp(
838 'bgFile', "Interface\\Buttons\\UI-SliderBar-Background",
839 'edgeFile', "Interface\\Buttons\\UI-SliderBar-Border",
840 'tile', true,
841 'edgeSize', 8,
842 'tileSize', 8,
843 'insets', tmp2(
844 'left', 3,
845 'right', 3,
846 'top', 3,
847 'bottom', 3
848 )
849 ))
850 local texture = slider:CreateTexture()
851 slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical")
852 local text = slider:CreateFontString(nil, "ARTWORK")
853 sliderFrame.topText = text
854 text:SetFontObject(GameFontGreenSmall)
855 text:SetText("100%")
856 text:SetPoint("BOTTOM", slider, "TOP")
857 local text = slider:CreateFontString(nil, "ARTWORK")
858 sliderFrame.bottomText = text
859 text:SetFontObject(GameFontGreenSmall)
860 text:SetText("0%")
861 text:SetPoint("TOP", slider, "BOTTOM")
862 local text = slider:CreateFontString(nil, "ARTWORK")
863 sliderFrame.currentText = text
864 text:SetFontObject(GameFontHighlightSmall)
865 text:SetText("50%")
866 text:SetPoint("LEFT", slider, "RIGHT")
867 text:SetPoint("RIGHT", sliderFrame, "RIGHT", -6, 0)
868 text:SetJustifyH("CENTER")
869 local changed = false
870 local inside = false
871 slider:SetScript("OnValueChanged", function()
872 if sliderFrame.changing then
873 return
874 end
875 changed = true
876 local done = false
877 if sliderFrame.parent then
878 if sliderFrame.parent.sliderFunc then
879 local text = sliderFrame.parent.sliderFunc(1 - slider:GetValue())
880 if text then
881 sliderFrame.currentText:SetText(text)
882 done = true
883 end
884 end
885 end
886 if not done then
887 sliderFrame.currentText:SetText(format("%.0f%%", (1 - slider:GetValue()) * 100))
888 end
889 end)
890 sliderFrame:SetScript("OnEnter", function()
891 StopCounting(self, sliderFrame.level)
892 end)
893 sliderFrame:SetScript("OnLeave", function()
894 StartCounting(self, sliderFrame.level)
895 end)
896 slider:SetScript("OnMouseDown", function()
897 sliderFrame.mouseDown = true
898 end)
899 slider:SetScript("OnMouseUp", function()
900 sliderFrame.mouseDown = false
901 if changed and not inside then
902 local parent = sliderFrame.parent
903 Refresh(self, levels[sliderFrame.level - 1])
904 OpenSlider(self, parent)
905 end
906 end)
907 slider:SetScript("OnEnter", function()
908 inside = true
909 StopCounting(self, sliderFrame.level)
910 end)
911 slider:SetScript("OnLeave", function()
912 inside = false
913 StartCounting(self, sliderFrame.level)
914 if changed and not sliderFrame.mouseDown then
915 local parent = sliderFrame.parent
916 Refresh(self, levels[sliderFrame.level - 1])
917 OpenSlider(self, parent)
918 end
919 end)
920 end
921 sliderFrame.parent = parent
922 sliderFrame.level = parent.level.num + 1
923 sliderFrame.parentValue = parent.level.value
924 sliderFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3)
925 sliderFrame.slider:SetFrameLevel(sliderFrame:GetFrameLevel() + 1)
926 sliderFrame.changing = true
927 if not parent.sliderValue then
928 parent.sliderValue = 0.5
929 end
930 sliderFrame.slider:SetValue(1 - parent.sliderValue)
931 sliderFrame.changing = false
932 sliderFrame.bottomText:SetText(parent.sliderBottom or "0%")
933 sliderFrame.topText:SetText(parent.sliderTop or "100%")
934 local text
935 if parent.sliderFunc then
936 text = parent.sliderFunc(parent.sliderValue)
937 end
938 sliderFrame.currentText:SetText(text or format("%.0f%%", parent.sliderValue * 100))
939  
940 local level = parent.level
941 sliderFrame:Show()
942 sliderFrame:ClearAllPoints()
943 if level.lastDirection == "RIGHT" then
944 if level.lastVDirection == "DOWN" then
945 sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10)
946 else
947 sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10)
948 end
949 else
950 if level.lastVDirection == "DOWN" then
951 sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10)
952 else
953 sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10)
954 end
955 end
956 local dirty
957 if level.lastDirection == "RIGHT" then
958 if sliderFrame:GetRight() > GetScreenWidth() then
959 level.lastDirection = "LEFT"
960 dirty = true
961 end
962 elseif sliderFrame:GetLeft() < 0 then
963 level.lastDirection = "RIGHT"
964 dirty = true
965 end
966 if level.lastVDirection == "DOWN" then
967 if sliderFrame:GetBottom() < 0 then
968 level.lastVDirection = "UP"
969 dirty = true
970 end
971 elseif sliderFrame:GetTop() > GetScreenWidth() then
972 level.lastVDirection = "DOWN"
973 dirty = true
974 end
975 if dirty then
976 sliderFrame:ClearAllPoints()
977 if level.lastDirection == "RIGHT" then
978 if level.lastVDirection == "DOWN" then
979 sliderFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10)
980 else
981 sliderFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10)
982 end
983 else
984 if level.lastVDirection == "DOWN" then
985 sliderFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10)
986 else
987 sliderFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10)
988 end
989 end
990 end
991 local left, bottom = sliderFrame:GetLeft(), sliderFrame:GetBottom()
992 sliderFrame:ClearAllPoints()
993 sliderFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom)
994 if mod(level.num, 5) == 0 then
995 local left, bottom = level:GetLeft(), level:GetBottom()
996 level:ClearAllPoints()
997 level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom)
998 end
999 end
1000  
1001 function OpenEditBox(self, parent)
1002 if not editBoxFrame then
1003 editBoxFrame = CreateFrame("Frame", nil, UIParent)
1004 editBoxFrame:SetWidth(200)
1005 editBoxFrame:SetHeight(40)
1006 editBoxFrame:SetBackdrop(tmp(
1007 'bgFile', "Interface\\Tooltips\\UI-Tooltip-Background",
1008 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border",
1009 'tile', true,
1010 'insets', tmp2(
1011 'left', 5,
1012 'right', 5,
1013 'top', 5,
1014 'bottom', 5
1015 ),
1016 'tileSize', 16,
1017 'edgeSize', 16
1018 ))
1019 editBoxFrame:SetFrameStrata("TOOLTIP")
1020 if editBoxFrame.SetTopLevel then
1021 editBoxFrame:SetTopLevel(true)
1022 end
1023 editBoxFrame:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
1024 editBoxFrame:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b)
1025 editBoxFrame:EnableMouse(true)
1026 editBoxFrame:Hide()
1027 editBoxFrame:SetPoint("CENTER", UIParent, "CENTER")
1028  
1029 local editBox = CreateFrame("EditBox", nil, editBoxFrame)
1030 editBoxFrame.editBox = editBox
1031 editBox:SetFontObject(ChatFontNormal)
1032 editBox:SetWidth(160)
1033 editBox:SetHeight(13)
1034 editBox:SetPoint("CENTER", editBoxFrame, "CENTER", 0, 0)
1035  
1036 local left = editBox:CreateTexture(nil, "BACKGROUND")
1037 left:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Left")
1038 left:SetTexCoord(0, 100 / 256, 0, 1)
1039 left:SetWidth(100)
1040 left:SetHeight(32)
1041 left:SetPoint("LEFT", editBox, "LEFT", -10, 0)
1042 local right = editBox:CreateTexture(nil, "BACKGROUND")
1043 right:SetTexture("Interface\\ChatFrame\\UI-ChatInputBorder-Right")
1044 right:SetTexCoord(156/256, 1, 0, 1)
1045 right:SetWidth(100)
1046 right:SetHeight(32)
1047 right:SetPoint("RIGHT", editBox, "RIGHT", 10, 0)
1048  
1049 editBox:SetScript("OnEnterPressed", function()
1050 if editBoxFrame.parent and editBoxFrame.parent.editBoxFunc then
1051 editBoxFrame.parent.editBoxFunc(editBox:GetText() or "")
1052 end
1053 self:Close(editBoxFrame.level)
1054 end)
1055 editBox:SetScript("OnEscapePressed", function()
1056 self:Close(editBoxFrame.level)
1057 end)
1058 local changing = false
1059 local skipNext = false
1060  
1061 function editBox:SpecialSetText(text)
1062 local oldText = editBox:GetText() or ""
1063 if not text then
1064 text = ""
1065 end
1066 if text ~= oldText then
1067 changing = true
1068 self:SetText(text)
1069 changing = false
1070 skipNext = true
1071 end
1072 end
1073  
1074 editBox:SetScript("OnTextChanged", function()
1075 if skipNext then
1076 skipNext = false
1077 elseif not changing and editBoxFrame.parent and editBoxFrame.parent.editBoxChangeFunc then
1078 local text = editBoxFrame.parent.editBoxChangeFunc(editBox:GetText() or "")
1079 if text then
1080 editBox:SpecialSetText(text)
1081 end
1082 end
1083 end)
1084 editBoxFrame:SetScript("OnEnter", function()
1085 StopCounting(self, editBoxFrame.level)
1086 end)
1087 editBoxFrame:SetScript("OnLeave", function()
1088 StartCounting(self, editBoxFrame.level)
1089 end)
1090 editBox:SetScript("OnEnter", function()
1091 StopCounting(self, editBoxFrame.level)
1092 end)
1093 editBox:SetScript("OnLeave", function()
1094 StartCounting(self, editBoxFrame.level)
1095 end)
1096 end
1097 editBoxFrame.parent = parent
1098 editBoxFrame.level = parent.level.num + 1
1099 editBoxFrame.parentValue = parent.level.value
1100 editBoxFrame:SetFrameLevel(parent.level:GetFrameLevel() + 3)
1101 editBoxFrame.editBox:SetFrameLevel(editBoxFrame:GetFrameLevel() + 1)
1102 editBoxFrame.editBox:SpecialSetText(parent.editBoxText)
1103  
1104 local level = parent.level
1105 editBoxFrame:Show()
1106 editBoxFrame:ClearAllPoints()
1107 if level.lastDirection == "RIGHT" then
1108 if level.lastVDirection == "DOWN" then
1109 editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10)
1110 else
1111 editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10)
1112 end
1113 else
1114 if level.lastVDirection == "DOWN" then
1115 editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10)
1116 else
1117 editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10)
1118 end
1119 end
1120 local dirty
1121 if level.lastDirection == "RIGHT" then
1122 if editBoxFrame:GetRight() > GetScreenWidth() then
1123 level.lastDirection = "LEFT"
1124 dirty = true
1125 end
1126 elseif editBoxFrame:GetLeft() < 0 then
1127 level.lastDirection = "RIGHT"
1128 dirty = true
1129 end
1130 if level.lastVDirection == "DOWN" then
1131 if editBoxFrame:GetBottom() < 0 then
1132 level.lastVDirection = "UP"
1133 dirty = true
1134 end
1135 elseif editBoxFrame:GetTop() > GetScreenWidth() then
1136 level.lastVDirection = "DOWN"
1137 dirty = true
1138 end
1139 if dirty then
1140 editBoxFrame:ClearAllPoints()
1141 if level.lastDirection == "RIGHT" then
1142 if level.lastVDirection == "DOWN" then
1143 editBoxFrame:SetPoint("TOPLEFT", parent, "TOPRIGHT", 5, 10)
1144 else
1145 editBoxFrame:SetPoint("BOTTOMLEFT", parent, "BOTTOMRIGHT", 5, -10)
1146 end
1147 else
1148 if level.lastVDirection == "DOWN" then
1149 editBoxFrame:SetPoint("TOPRIGHT", parent, "TOPLEFT", -5, 10)
1150 else
1151 editBoxFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMLEFT", -5, -10)
1152 end
1153 end
1154 end
1155 local left, bottom = editBoxFrame:GetLeft(), editBoxFrame:GetBottom()
1156 editBoxFrame:ClearAllPoints()
1157 editBoxFrame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom)
1158 if mod(level.num, 5) == 0 then
1159 local left, bottom = level:GetLeft(), level:GetBottom()
1160 level:ClearAllPoints()
1161 level:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", left, bottom)
1162 end
1163 end
1164  
1165 function lib:IsOpen(parent)
1166 argCheck(parent, 2, "table", "nil")
1167 return levels[1] and levels[1]:IsShown() and (not parent or parent == levels[1].parent or parent == levels[1]:GetParent())
1168 end
1169  
1170 function Open(self, parent, func, level, value, point, relativePoint, cursorX, cursorY)
1171 if AceLibrary and AceLibrary:HasInstance("Dewdrop-2.0") then
1172 local d = AceLibrary("Dewdrop-2.0")
1173 local ret, val = pcall(d, IsOpen, d)
1174 if ret and val then
1175 AceLibrary("Dewdrop-2.0"):Close()
1176 end
1177 end
1178 self:Close(level)
1179 local frame = AcquireLevel(self, level)
1180 if level == 1 then
1181 frame.lastDirection = "RIGHT"
1182 frame.lastVDirection = "DOWN"
1183 else
1184 frame.lastDirection = levels[level - 1].lastDirection
1185 frame.lastVDirection = levels[level - 1].lastVDirection
1186 end
1187 frame:SetFrameStrata("TOOLTIP")
1188 frame:ClearAllPoints()
1189 frame.parent = parent
1190 frame:SetPoint("LEFT", UIParent, "RIGHT", 10000, 0)
1191 frame:Show()
1192 if level == 1 then
1193 baseFunc = func
1194 end
1195 levels[level].value = value
1196 relativePoint = relativePoint or point
1197 Refresh(self, levels[level])
1198 if point then
1199 frame:ClearAllPoints()
1200 frame:SetPoint(point, parent, relativePoint)
1201 if cursorX then
1202 local left = frame:GetLeft()
1203 local width = frame:GetWidth()
1204 local curX, curY = GetCursorPosition()
1205 frame:ClearAllPoints()
1206 relativePoint = relativePoint or point
1207 if point == "BOTTOM" or point == "TOP" then
1208 if curX < GetScreenWidth() / 2 then
1209 point = point .. "LEFT"
1210 else
1211 point = point .. "RIGHT"
1212 end
1213 elseif point == "CENTER" then
1214 if curX < GetScreenWidth() / 2 then
1215 point = "LEFT"
1216 else
1217 point = "RIGHT"
1218 end
1219 end
1220 frame:SetPoint(point, parent, relativePoint, curX - left - width / 2, 0)
1221 if level == 1 then
1222 frame.lastDirection = "RIGHT"
1223 end
1224 elseif cursorY then
1225 local bottom = frame:GetBottom()
1226 local height = frame:GetHeight()
1227 local curX, curY = GetCursorPosition()
1228 frame:ClearAllPoints()
1229 relativePoint = relativePoint or point
1230 if point == "LEFT" or point == "RIGHT" then
1231 if curX < GetScreenHeight() / 2 then
1232 point = point .. "BOTTOM"
1233 else
1234 point = point .. "TOP"
1235 end
1236 elseif point == "CENTER" then
1237 if curX < GetScreenHeight() / 2 then
1238 point = "BOTTOM"
1239 else
1240 point = "TOP"
1241 end
1242 end
1243 frame:SetPoint(point, parent, relativePoint, 0, curY - bottom - height / 2)
1244 if level == 1 then
1245 frame.lastDirection = "DOWN"
1246 end
1247 end
1248 if (strsub(point, 1, 3) ~= strsub(relativePoint, 1, 3)) then
1249 if frame:GetBottom() < 0 then
1250 local point, parent, relativePoint, x, y = frame:GetPoint(1)
1251 local change = GetScreenHeight() - frame:GetTop()
1252 local otherChange = -frame:GetBottom()
1253 if otherChange < change then
1254 change = otherChange
1255 end
1256 frame:SetPoint(point, parent, relativePoint, x, y + change)
1257 elseif frame:GetTop() > GetScreenHeight() then
1258 local point, parent, relativePoint, x, y = frame:GetPoint(1)
1259 local change = GetScreenHeight() - frame:GetTop()
1260 local otherChange = -frame:GetBottom()
1261 if otherChange < change then
1262 change = otherChange
1263 end
1264 frame:SetPoint(point, parent, relativePoint, x, y + change)
1265 end
1266 end
1267 end
1268 CheckDualMonitor(self, frame)
1269 StartCounting(self, level)
1270 end
1271  
1272 function lib:IsRegistered(parent)
1273 argCheck(parent, 2, "table")
1274 return not not self.registry[parent]
1275 end
1276  
1277 function lib: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)
1278 argCheck(parent, 2, "table")
1279 if self.registry[parent] then
1280 self:Unregister(parent)
1281 end
1282 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)
1283 self.registry[parent] = info
1284 if not info.dontHook and not self.onceRegistered[parent] then
1285 if parent:HasScript("OnMouseUp") then
1286 local script = parent:GetScript("OnMouseUp")
1287 parent:SetScript("OnMouseUp", function()
1288 if script then
1289 script()
1290 end
1291 if arg1 == "RightButton" and self.registry[parent] then
1292 if self:IsOpen(parent) then
1293 self:Close()
1294 else
1295 self:Open(parent)
1296 end
1297 end
1298 end)
1299 end
1300 if parent:HasScript("OnMouseDown") then
1301 local script = parent:GetScript("OnMouseDown")
1302 parent:SetScript("OnMouseDown", function()
1303 if script then
1304 script()
1305 end
1306 if self.registry[parent] then
1307 self:Close()
1308 end
1309 end)
1310 end
1311 end
1312 self.onceRegistered[parent] = true
1313 end
1314  
1315 function lib:Unregister(parent)
1316 argCheck(parent, 2, "table")
1317 self.registry[parent] = nil
1318 end
1319  
1320 function lib: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)
1321 argCheck(parent, 2, "table")
1322 local info
1323 if type(k1) == "table" and k1[0] and k1.IsFrameType and self.registry[k1] then
1324 info = tmp()
1325 for k,v in pairs(self.registry[k1]) do
1326 info[k] = v
1327 end
1328 else
1329 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)
1330 if self.registry[parent] then
1331 for k,v in pairs(self.registry[parent]) do
1332 if info[k] == nil then
1333 info[k] = v
1334 end
1335 end
1336 end
1337 end
1338 local point = info.point
1339 local relativePoint = info.relativePoint
1340 local cursorX = info.cursorX
1341 local cursorY = info.cursorY
1342 if type(point) == "function" then
1343 local b
1344 point, b = point(parent)
1345 if b then
1346 relativePoint = b
1347 end
1348 end
1349 if type(relativePoint) == "function" then
1350 relativePoint = relativePoint(parent)
1351 end
1352 Open(self, parent, info.children, 1, nil, point, relativePoint, cursorX, cursorY)
1353 end
1354  
1355 function Clear(self, level)
1356 if level then
1357 if level.buttons then
1358 for i = tgetn(level.buttons), 1, -1 do
1359 ReleaseButton(self, level, i)
1360 end
1361 end
1362 end
1363 end
1364  
1365 function lib:Close(level)
1366 if DropDownList1:IsShown() then
1367 DropDownList1:Hide()
1368 end
1369 if AceLibrary and AceLibrary:HasInstance("Dewdrop-2.0") then
1370 local d = AceLibrary("Dewdrop-2.0")
1371 local ret, val = pcall(d, IsOpen, d)
1372 if ret and val then
1373 AceLibrary("Dewdrop-2.0"):Close()
1374 end
1375 end
1376 if not level then
1377 level = 1
1378 else
1379 argCheck(level, 2, "number")
1380 end
1381 if level == 1 and levels[level] then
1382 levels[level].parented = false
1383 end
1384 if sliderFrame and sliderFrame.level == level then
1385 sliderFrame:Hide()
1386 end
1387 if editBoxFrame and editBoxFrame.level == level then
1388 editBoxFrame:Hide()
1389 end
1390 if levels[level] and levels[level]:IsShown() then
1391 Clear(self, levels[level])
1392 levels[level]:Hide()
1393 end
1394 for i = level, table.getn(levels) do
1395 levels[i]:ClearAllPoints()
1396 levels[i]:SetPoint("CENTER", UIParent, "CENTER")
1397 end
1398 end
1399  
1400 function lib: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)
1401 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)
1402 local level = info.level or currentLevel
1403 info.level = nil
1404 local button = AcquireButton(self, level)
1405 if not next(info) then
1406 info.disabled = true
1407 end
1408 button.disabled = info.isTitle or info.notClickable or info.disabled
1409 button.isTitle = info.isTitle
1410 button.notClickable = info.notClickable
1411 if button.isTitle then
1412 button.text:SetFontObject(GameFontNormalSmall)
1413 elseif button.notClickable then
1414 button.text:SetFontObject(GameFontHighlightSmall)
1415 elseif button.disabled then
1416 button.text:SetFontObject(GameFontDisableSmall)
1417 else
1418 button.text:SetFontObject(GameFontHighlightSmall)
1419 end
1420 if info.textR and info.textG and info.textB then
1421 button.textR = info.textR
1422 button.textG = info.textG
1423 button.textB = info.textB
1424 button.text:SetTextColor(button.textR, button.textG, button.textB)
1425 else
1426 button.text:SetTextColor(button.text:GetFontObject():GetTextColor())
1427 end
1428 button.notCheckable = info.notCheckable
1429 button.text:SetPoint("LEFT", button, "LEFT", button.notCheckable and 0 or 24, 0)
1430 button.checked = not info.notCheckable and info.checked
1431 button.isRadio = not info.notCheckable and info.isRadio
1432 if info.isRadio then
1433 button.check:Show()
1434 button.check:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton")
1435 if button.checked then
1436 button.check:SetTexCoord(0.25, 0.5, 0, 1)
1437 button.check:SetVertexColor(1, 1, 1, 1)
1438 else
1439 button.check:SetTexCoord(0, 0.25, 0, 1)
1440 button.check:SetVertexColor(1, 1, 1, 0.5)
1441 end
1442 button.radioHighlight:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton")
1443 button.check:SetWidth(16)
1444 button.check:SetHeight(16)
1445 else
1446 if button.checked then
1447 if info.checkIcon then
1448 button.check:SetWidth(16)
1449 button.check:SetHeight(16)
1450 button.check:SetTexture(info.checkIcon)
1451 if string.sub(info.checkIcon, 1, 16) == "Interface\\Icons\\" then
1452 button.check:SetTexCoord(0.05, 0.95, 0.05, 0.95)
1453 else
1454 button.check:SetTexCoord(0, 1, 0, 1)
1455 end
1456 else
1457 button.check:SetWidth(24)
1458 button.check:SetHeight(24)
1459 button.check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
1460 button.check:SetTexCoord(0, 1, 0, 1)
1461 end
1462 button.check:SetVertexColor(1, 1, 1, 1)
1463 else
1464 button.check:SetVertexColor(1, 1, 1, 0)
1465 end
1466 end
1467 if not button.disabled then
1468 button.func = info.func
1469 end
1470 button.hasColorSwatch = info.hasColorSwatch
1471 if button.hasColorSwatch then
1472 button.colorSwatch:Show()
1473 button.colorSwatch.texture:Show()
1474 button.r = info.r or 1
1475 button.g = info.g or 1
1476 button.b = info.b or 1
1477 button.colorSwatch.texture:SetTexture(button.r, button.g, button.b)
1478 button.checked = false
1479 button.func = nil
1480 button.swatchFunc = info.swatchFunc
1481 button.hasOpacity = info.hasOpacity
1482 button.opacityFunc = info.opacityFunc
1483 button.opacity = info.opacity or 1
1484 button.cancelFunc = info.cancelFunc
1485 else
1486 button.colorSwatch:Hide()
1487 button.colorSwatch.texture:Hide()
1488 end
1489 button.hasArrow = not button.hasColorSwatch and (info.value or info.hasSlider or info.hasEditBox) and info.hasArrow
1490 if button.hasArrow then
1491 button.arrow:SetAlpha(1)
1492 if info.hasSlider then
1493 button.hasSlider = true
1494 button.sliderTop = info.sliderTop or "100%"
1495 button.sliderBottom = info.sliderBottom or "0%"
1496 button.sliderFunc = info.sliderFunc
1497 button.sliderValue = info.sliderValue
1498 elseif info.hasEditBox then
1499 button.hasEditBox = true
1500 button.editBoxText = info.editBoxText or ""
1501 button.editBoxFunc = info.editBoxFunc
1502 button.editBoxChangeFunc = info.editBoxChangeFunc
1503 else
1504 button.value = info.value
1505 end
1506 else
1507 button.arrow:SetAlpha(0)
1508 end
1509 button.arg1 = info.arg1
1510 button.arg2 = info.arg2
1511 button.arg3 = info.arg3
1512 button.arg4 = info.arg4
1513 button.closeWhenClicked = info.closeWhenClicked
1514 button.textHeight = info.textHeight or UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT
1515 local font,_ = button.text:GetFont()
1516 button.text:SetFont(STANDARD_TEXT_FONT, button.textHeight)
1517 button:SetHeight(button.textHeight + 6)
1518 button.text:SetPoint("RIGHT", button.arrow, (button.hasColorSwatch or button.hasArrow) and "LEFT" or "RIGHT")
1519 button.text:SetJustifyH(info.justifyH or "LEFT")
1520 button.text:SetText(info.text)
1521 button.tooltipTitle = info.tooltipTitle
1522 button.tooltipText = info.tooltipText
1523 button.tooltipFunc = info.tooltipFunc
1524 button.tooltipArg1 = info.tooltipArg1
1525 button.tooltipArg2 = info.tooltipArg2
1526 button.tooltipArg3 = info.tooltipArg3
1527 button.tooltipArg4 = info.tooltipArg4
1528 if type(button.func) == "string" then
1529 assert(type(button.arg1) == "table", "Cannot call method " .. button.func .. " on a non-table")
1530 assert(type(button.arg1[button.func]) == "function", "Method " .. button.func .. " nonexistant.")
1531 end
1532 end
1533  
1534 DewdropLib:Register(lib)
1535 lib = nil