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: 1867 $", 12, -3))
3 local DEBUG = false
4 if TabletLib and TabletLib.versions[MAJOR_VERSION] and TabletLib.versions[MAJOR_VERSION].minor >= MINOR_VERSION then
5 return
6 end
7  
8 local SCROLL_UP, SCROLL_DOWN, HINT, DETACH, SIZE, CLOSE_MENU
9 if GetLocale() == "deDE" then
10 SCROLL_UP = "Hochscrolle"
11 SCROLL_DOWN = "Herunterscrolle"
12 HINT = "Hinweis"
13 DETACH = "L\195\182sen"
14 SIZE = "Größe"
15 CLOSE_MENU = "Menü schließen"
16 else
17 SCROLL_UP = "Scroll up"
18 SCROLL_DOWN = "Scroll down"
19 HINT = "Hint"
20 DETACH = "Detach"
21 SIZE = "Size"
22 CLOSE_MENU = "Close menu"
23 end
24  
25 -------------IRIEL'S-STUB-CODE--------------
26 local stub = {};
27  
28 -- Instance replacement method, replace contents of old with that of new
29 function stub:ReplaceInstance(old, new)
30 for k,v in pairs(old) do old[k]=nil; end
31 for k,v in pairs(new) do old[k]=v; end
32 end
33  
34 -- Get a new copy of the stub
35 function stub:NewStub()
36 local newStub = {};
37 self:ReplaceInstance(newStub, self);
38 newStub.lastVersion = '';
39 newStub.versions = {};
40 return newStub;
41 end
42  
43 -- Get instance version
44 function stub:GetInstance(version)
45 if (not version) then version = self.lastVersion; end
46 local versionData = self.versions[version];
47 if (not versionData) then
48 message("Cannot find library instance with version '"
49 .. version .. "'");
50 return;
51 end
52 return versionData.instance;
53 end
54  
55 -- Register new instance
56 function stub:Register(newInstance)
57 local version,minor = newInstance:GetLibraryVersion();
58 self.lastVersion = version;
59 local versionData = self.versions[version];
60 if (not versionData) then
61 -- This one is new!
62 versionData = { instance = newInstance,
63 minor = minor,
64 old = {}
65 };
66 self.versions[version] = versionData;
67 newInstance:LibActivate(self);
68 return newInstance;
69 end
70 if (minor <= versionData.minor) then
71 -- This one is already obsolete
72 if (newInstance.LibDiscard) then
73 newInstance:LibDiscard();
74 end
75 return versionData.instance;
76 end
77 -- This is an update
78 local oldInstance = versionData.instance;
79 local oldList = versionData.old;
80 versionData.instance = newInstance;
81 versionData.minor = minor;
82 local skipCopy = newInstance:LibActivate(self, oldInstance, oldList);
83 table.insert(oldList, oldInstance);
84 if (not skipCopy) then
85 for i, old in ipairs(oldList) do
86 self:ReplaceInstance(old, newInstance);
87 end
88 end
89 return newInstance;
90 end
91  
92 -- Bind stub to global scope if it's not already there
93 if (not TabletLib) then
94 TabletLib = stub:NewStub();
95 end
96  
97 -- Nil stub for garbage collection
98 stub = nil;
99 -----------END-IRIEL'S-STUB-CODE------------
100  
101 local function assert(condition, message)
102 if not condition then
103 local stack = debugstack()
104 local first = string.gsub(stack, "\n.*", "")
105 local file = string.gsub(first, "^(.*\\.*)%.lua:%d+: .*", "%1")
106 if not message then
107 local _,_,second = string.find(stack, "\n(.-)\n")
108 message = "assertion failed! " .. second
109 end
110 message = "TabletLib: " .. message
111 local i = 1
112 for s in string.gfind(stack, "\n(.-)\n") do
113 i = i + 1
114 if not string.find(s, file .. "%.lua:%d+:") then
115 error(message, i)
116 return
117 end
118 end
119 error(message, 2)
120 return
121 end
122 return condition
123 end
124  
125 local start = GetTime()
126 local wrap
127 local GetProfileInfo
128 if DEBUG then
129 local tree = {}
130 local treeMemories = {}
131 local treeTimes = {}
132 local memories = {}
133 local times = {}
134 function wrap(value, name)
135 if type(value) == "function" then
136 local oldFunction = value
137 memories[name] = 0
138 times[name] = 0
139 return function(self, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60)
140 local pos = table.getn(tree)
141 table.insert(tree, name)
142 table.insert(treeMemories, 0)
143 table.insert(treeTimes, 0)
144 local t, mem = GetTime(), gcinfo()
145 local r1, r2, r3, r4, r5, r6, r7, r8 = oldFunction(self, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, a51, a52, a53, a54, a55, a56, a57, a58, a59, a60)
146 mem, t = gcinfo() - mem, GetTime() - t
147 if pos > 0 then
148 treeMemories[pos] = treeMemories[pos] + mem
149 treeTimes[pos] = treeTimes[pos] + t
150 end
151 local otherMem = table.remove(treeMemories)
152 if mem - otherMem > 0 then
153 memories[name] = memories[name] + mem - otherMem
154 end
155 times[name] = times[name] + t - table.remove(treeTimes)
156 table.remove(tree)
157 return r1, r2, r3, r4, r5, r6, r7, r8
158 end
159 end
160 end
161  
162 function GetProfileInfo()
163 return GetTime() - start, times, memories
164 end
165 else
166 function wrap(value)
167 return value
168 end
169 end
170  
171 local MIN_TOOLTIP_SIZE = 200
172 local lib = {}
173 local ipairs = ipairs
174 local tinsert = table.insert
175 local tremove = table.remove
176 local tgetn = table.getn
177 local function getsecond(_, value)
178 return value
179 end
180 local dewdrop
181 local sekeys
182 local CleanCategoryPool
183 local pool = {}
184 local function del(t)
185 if t then
186 if DEBUG and t[".poolprint"] then
187 print(t[".poolprint"])
188 end
189 for k in pairs(t) do
190 t[k] = nil
191 end
192 setmetatable(t, nil)
193 table.setn(t, 0)
194 table.insert(pool, t)
195 end
196 end
197  
198 local new
199  
200 local function copy(parent)
201 local t
202 if table.getn(pool) > 0 then
203 t = table.remove(pool)
204 else
205 t = {}
206 end
207 if parent then
208 for k,v in pairs(parent) do
209 t[k] = v
210 end
211 table.setn(t, table.getn(parent))
212 setmetatable(t, getmetatable(parent))
213 end
214 return t
215 end
216  
217 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, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25, k26, v26, k27, v27, k28, v28, k29, v29, k30, v30)
218 local t
219 if table.getn(pool) > 0 then
220 t = table.remove(pool)
221 else
222 t = {}
223 end
224 if k1 then t[k1] = v1
225 if k2 then t[k2] = v2
226 if k3 then t[k3] = v3
227 if k4 then t[k4] = v4
228 if k5 then t[k5] = v5
229 if k6 then t[k6] = v6
230 if k7 then t[k7] = v7
231 if k8 then t[k8] = v8
232 if k9 then t[k9] = v9
233 if k10 then t[k10] = v10
234 if k11 then t[k11] = v11
235 if k12 then t[k12] = v12
236 if k13 then t[k13] = v13
237 if k14 then t[k14] = v14
238 if k15 then t[k15] = v15
239 if k16 then t[k16] = v16
240 if k17 then t[k17] = v17
241 if k18 then t[k18] = v18
242 if k19 then t[k19] = v19
243 if k20 then t[k20] = v20
244 if k21 then t[k21] = v21
245 if k22 then t[k22] = v22
246 if k23 then t[k23] = v23
247 if k24 then t[k24] = v24
248 if k25 then t[k25] = v25
249 if k26 then t[k26] = v26
250 if k27 then t[k27] = v27
251 if k28 then t[k28] = v28
252 if k29 then t[k29] = v29
253 if k30 then t[k30] = v30
254 end end end end end end end end end end end end end end end end end end end end end end end end end end end end end end
255 return t
256 end
257 local tmp
258 tmp = setmetatable({}, {__index = function(self, key)
259 local t = {}
260 tmp[key] = function(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, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25, k26, v26, k27, v27, k28, v28, k29, v29, k30, v30)
261 for k in pairs(t) do
262 t[k] = nil
263 end
264 if k1 then t[k1] = v1
265 if k2 then t[k2] = v2
266 if k3 then t[k3] = v3
267 if k4 then t[k4] = v4
268 if k5 then t[k5] = v5
269 if k6 then t[k6] = v6
270 if k7 then t[k7] = v7
271 if k8 then t[k8] = v8
272 if k9 then t[k9] = v9
273 if k10 then t[k10] = v10
274 if k11 then t[k11] = v11
275 if k12 then t[k12] = v12
276 if k13 then t[k13] = v13
277 if k14 then t[k14] = v14
278 if k15 then t[k15] = v15
279 if k16 then t[k16] = v16
280 if k17 then t[k17] = v17
281 if k18 then t[k18] = v18
282 if k19 then t[k19] = v19
283 if k20 then t[k20] = v20
284 if k21 then t[k21] = v21
285 if k22 then t[k22] = v22
286 if k23 then t[k23] = v23
287 if k24 then t[k24] = v24
288 if k25 then t[k25] = v25
289 if k26 then t[k26] = v26
290 if k27 then t[k27] = v27
291 if k28 then t[k28] = v28
292 if k29 then t[k29] = v29
293 if k30 then t[k30] = v30
294 end end end end end end end end end end end end end end end end end end end end end end end end end end end end end end
295 return t
296 end
297 return tmp[key]
298 end})
299  
300 function lib:GetLibraryVersion()
301 return MAJOR_VERSION, MINOR_VERSION
302 end
303  
304 function lib:LibActivate(stub, oldLib, oldList)
305 if oldLib then
306 self.registry = oldLib.registry
307 self.onceRegistered = oldLib.onceRegistered
308 else
309 self.registry = {}
310 self.onceRegistered = {}
311 end
312 end
313  
314 function lib:LibDeactivate(stub)
315 end
316  
317 local _,headerSize = GameTooltipHeaderText:GetFont()
318 local _,normalSize = GameTooltipText:GetFont()
319 local tooltip
320 local testString
321 local TabletData = {}
322 local Category = {}
323 local Line = {}
324 do
325 local TabletData_mt = { __index = TabletData }
326 function TabletData:new(tablet)
327 if not testString then
328 testString = UIParent:CreateFontString()
329 testString:Hide()
330 end
331 local self = new()
332 self.categories = new()
333 self.id = 0
334 self.width = 0--(MIN_TOOLTIP_SIZE - 20)*tablet.fontSizePercent
335 self.tablet = tablet
336 self.title = "Title"
337 setmetatable(self, TabletData_mt)
338 return self
339 end
340  
341 function TabletData:del()
342 for k, v in ipairs(self.categories) do
343 v:del()
344 end
345 del(self.categories)
346 del(self)
347 end
348  
349 function TabletData:print(id)
350 printFull(id, self)
351 end
352  
353 function TabletData:Display()
354 if self.tablet == tooltip then
355 local info = new(
356 'hideBlankLine', true,
357 'text', self.title,
358 'justify', "CENTER",
359 'font', GameTooltipHeaderText,
360 'isTitle', true
361 )
362 self:AddCategory(info, 1)
363 del(info)
364 if self.hint then
365 self:AddCategory(nil):AddLine(
366 'text', HINT .. ": " .. self.hint,
367 'textR', 0,
368 'textG', 1,
369 'textB', 0,
370 'wrap', true
371 )
372 end
373 end
374  
375 local tabletData = self.tabletData
376 local width
377 for k, v in ipairs(self.categories) do
378 if v.columns <= 2 then
379 width = v.x1
380 else
381 width = v.x1 + v.x2 + v.x3 + v.x4 + (v.columns - 1) * 20
382 end
383 if self.width < width then
384 self.width = width
385 end
386 end
387  
388 local good = false
389 local lastTitle = true
390 for k, v in ipairs(self.categories) do
391 if lastTitle then
392 v.hideBlankLine = true
393 lastTitle = false
394 end
395 if v:Display(self.tablet) then
396 good = true
397 end
398 if v.isTitle then
399 lastTitle = true
400 end
401 end
402 if not good then
403 local width
404 local info = new(
405 'hideBlankLine', true,
406 'text', self.title,
407 'justify', "CENTER",
408 'font', GameTooltipHeaderText,
409 'isTitle', true
410 )
411 local cat = self:AddCategory(info)
412 del(info)
413 self.width = self.categories[table.getn(self.categories)].x1
414 cat:Display(self.tablet)
415 end
416 end
417  
418 function TabletData:AddCategory(info, index)
419 local made = false
420 if not info then
421 made = true
422 info = new()
423 end
424 local cat = Category:new(self, info)
425 if index then
426 table.insert(self.categories, index, cat)
427 else
428 table.insert(self.categories, cat)
429 end
430 if made then
431 del(info)
432 end
433 return cat
434 end
435  
436 function TabletData:SetHint(hint)
437 self.hint = hint
438 end
439  
440 function TabletData:SetTitle(title)
441 self.title = title or "Title"
442 end
443 end
444 do
445 local Category_mt = { __index = Category }
446 function Category:new(tabletData, info, superCategory)
447 local self = copy(info)
448 if superCategory and not self.noInherit then
449 self.superCategory = superCategory.superCategory
450 for k, v in pairs(superCategory) do
451 if string.find(k, "^child_") then
452 local k = strsub(k, 7)
453 if self[k] == nil then
454 self[k] = v
455 end
456 end
457 end
458 self.columns = superCategory.columns
459 else
460 self.superCategory = self
461 end
462 self.tabletData = tabletData
463 self.lines = new()
464 if not self.columns then
465 self.columns = 1
466 end
467 self.x1 = 0
468 self.x2 = 0
469 self.x3 = 0
470 self.x4 = 0
471 setmetatable(self, Category_mt)
472 self.lastWasTitle = nil
473 if self.text or self.text2 or self.text3 or self.text4 then
474 local x = new(
475 'category', category,
476 'text', self.text,
477 'textR', self.textR or 1,
478 'textG', self.textG or 1,
479 'textB', self.textB or 1,
480 'fakeChild', true,
481 'func', self.func,
482 'arg1', info.arg1,
483 'arg2', self.arg2,
484 'arg3', self.arg3,
485 'hasCheck', self.hasCheck,
486 'checked', self.checked,
487 'checkIcon', self.checkIcon,
488 'isRadio', self.isRadio,
489 'font', self.font,
490 'size', self.size,
491 'wrap', self.wrap,
492 'catStart', true,
493 'indentation', self.indentation,
494 'noInherit', true,
495 'justify', self.justify,
496 'justify2', self.justify2,
497 'justify3', self.justify3,
498 'justify4', self.justify4
499 )
500 if self.isTitle then
501 x.textR = self.textR or 1
502 x.textG = self.textG or 0.823529
503 x.textB = self.textB or 0
504 else
505 x.textR = self.textR or 1
506 x.textG = self.textG or 1
507 x.textB = self.textB or 1
508 end
509 x.text2 = self.text2
510 x.text3 = self.text3
511 x.text4 = self.text4
512 x.text2R = self.text2R or self.textR2 or 1
513 x.text2G = self.text2G or self.textG2 or 1
514 x.text2B = self.text2B or self.textB2 or 1
515 x.text3R = self.text3R or self.textR3 or 1
516 x.text3G = self.text3G or self.textG3 or 1
517 x.text3B = self.text3B or self.textB3 or 1
518 x.text4R = self.text4R or self.textR4 or 1
519 x.text4G = self.text4G or self.textG4 or 1
520 x.text4B = self.text4B or self.textB4 or 1
521 x.font2 = self.font2
522 x.font3 = self.font3
523 x.font4 = self.font4
524 x.size2 = self.size2
525 x.size3 = self.size3
526 x.size4 = self.size4
527 self:AddLine(x)
528 del(x)
529 self.lastWasTitle = true
530 end
531 return self
532 end
533  
534 function Category:del()
535 local prev = garbageLine
536 for k, v in pairs(self.lines) do
537 v:del()
538 end
539 del(self.lines)
540 del(self)
541 end
542  
543 function Category: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, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25, k26, v26, k27, v27, k28, v28, k29, v29, k30, v30)
544 self.lastWasTitle = nil
545 local line
546 if type(k1) == "table" then
547 Line:new(self, k1, v1)
548 else
549 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, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25, k26, v26, k27, v27, k28, v28, k29, v29, k30, v30)
550 Line:new(self, info)
551 del(info)
552 end
553 end
554  
555 function Category:AddCategory(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, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25, k26, v26, k27, v27, k28, v28, k29, v29, k30, v30)
556 local lastWasTitle = self.lastWasTitle
557 self.lastWasTitle = nil
558 local info
559 if type(k1) == "table" then
560 info = k1
561 else
562 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, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25, k26, v26, k27, v27, k28, v28, k29, v29, k30, v30)
563 end
564 if lastWasTitle or table.getn(self.lines) == 0 then
565 info.hideBlankLine = true
566 end
567 local cat = Category:new(self.tabletData, info, self)
568 table.insert(self.lines, cat)
569 return cat
570 end
571  
572 function Category:HasChildren()
573 local hasChildren = false
574 for k, v in ipairs(self.lines) do
575 if v.HasChildren then
576 if v:HasChildren() then
577 return true
578 end
579 end
580 if not v.fakeChild then
581 return true
582 end
583 end
584 return false
585 end
586  
587 local lastWasTitle = false
588 function Category:Display(tablet)
589 if not self.isTitle and not self.showWithoutChildren and not self:HasChildren() then
590 return false
591 end
592 if not self.hideBlankLine and not lastWasTitle then
593 local info = new(
594 'blank', true,
595 'fakeChild', true
596 )
597 self:AddLine(info, 1)
598 del(info)
599 end
600 local good = false
601 if table.getn(self.lines) > 0 then
602 self.tabletData.id = self.tabletData.id + 1
603 self.id = self.tabletData.id
604 for k, v in ipairs(self.lines) do
605 if v:Display(tablet) then
606 good = true
607 end
608 end
609 end
610 lastWasTitle = self.isTitle
611 return good
612 end
613 end
614 do
615 local Line_mt = { __index = Line }
616 function Line:new(category, info, position)
617 local self = copy(info)
618 if not info.noInherit then
619 for k, v in pairs(category) do
620 if string.find(k, "^child_") then
621 local k = strsub(k, 7)
622 if self[k] == nil then
623 self[k] = v
624 end
625 end
626 end
627 end
628 self.category = category
629 if position then
630 table.insert(category.lines, position, self)
631 else
632 table.insert(category.lines, self)
633 end
634 setmetatable(self, Line_mt)
635 local columns = category.columns
636 if columns == 1 then
637 if not self.justify then
638 self.justify = "LEFT"
639 end
640 elseif columns == 2 then
641 self.justify = "LEFT"
642 self.justify2 = "RIGHT"
643 if self.wrap then
644 self.wrap2 = false
645 end
646 elseif columns == 3 then
647 if not self.justify then
648 self.justify = "LEFT"
649 end
650 if not self.justify2 then
651 self.justify2 = "CENTER"
652 end
653 if not self.justify3 then
654 self.justify3 = "RIGHT"
655 end
656 if self.wrap then
657 self.wrap2 = false
658 self.wrap3 = false
659 elseif self.wrap2 then
660 self.wrap3 = false
661 end
662 elseif columns == 4 then
663 if not self.justify then
664 self.justify = "LEFT"
665 end
666 if not self.justify2 then
667 self.justify2 = "CENTER"
668 end
669 if not self.justify3 then
670 self.justify3 = "CENTER"
671 end
672 if not self.justify4 then
673 self.justify4 = "RIGHT"
674 end
675 if self.wrap then
676 self.wrap2 = false
677 self.wrap3 = false
678 self.wrap4 = false
679 elseif self.wrap2 then
680 self.wrap3 = false
681 self.wrap4 = false
682 elseif self.wrap3 then
683 self.wrap4 = false
684 end
685 end
686 if self.textR2 then
687 self.text2R, self.textR2 = self.text2R or self.textR2
688 self.text2G, self.textG2 = self.text2G or self.textG2
689 self.text2B, self.textB2 = self.text2B or self.textB2
690 if self.textR3 then
691 self.text3R, self.textR3 = self.text3R or self.textR3
692 self.text3G, self.textG3 = self.text3G or self.textG3
693 self.text3B, self.textB3 = self.text3B or self.textB3
694 if self.textR4 then
695 self.text4R, self.textR4 = self.text4R or self.textR4
696 self.text4G, self.textG4 = self.text4G or self.textG4
697 self.text4B, self.textB4 = self.text4B or self.textB4
698 end
699 end
700 end
701 if not self.indentation or self.indentation < 0 then
702 self.indentation = 0
703 end
704 if not self.font then
705 self.font = GameTooltipText
706 end
707 if not self.font2 then
708 self.font2 = self.font
709 end
710 if not self.font3 then
711 self.font3 = self.font
712 end
713 if not self.font4 then
714 self.font4 = self.font
715 end
716 if not self.size then
717 _,self.size = self.font:GetFont()
718 end
719 if not self.size2 then
720 _,self.size2 = self.font2:GetFont()
721 end
722 if not self.size3 then
723 _,self.size3 = self.font3:GetFont()
724 end
725 if not self.size4 then
726 _,self.size4 = self.font4:GetFont()
727 end
728  
729 local fontSizePercent = category.tabletData.tablet.fontSizePercent
730 local w = 0
731 if self.text then
732 if not self.wrap then
733 testString:SetWidth(0)
734 testString:SetFontObject(self.font)
735 local font,_,flags = testString:GetFont()
736 testString:SetFont(font, self.size * fontSizePercent, flags)
737 testString:SetText(self.text)
738 local checkWidth = self.hasCheck and self.size * fontSizePercent or 0
739 w = testString:GetWidth() + self.indentation * fontSizePercent
740 if self.hasCheck then
741 w = w + self.size
742 end
743 if category.superCategory.x1 < w then
744 category.superCategory.x1 = w
745 end
746 else
747 if columns == 1 then
748 testString:SetWidth(0)
749 testString:SetFontObject(self.font)
750 local font,_,flags = testString:GetFont()
751 testString:SetFont(font, self.size * fontSizePercent, flags)
752 testString:SetText(self.text)
753 local checkWidth = self.hasCheck and self.size * fontSizePercent or 0
754 w = testString:GetWidth() + self.indentation * fontSizePercent
755 if self.hasCheck then
756 w = w + self.size
757 end
758 if w > (MIN_TOOLTIP_SIZE - 20) * fontSizePercent then
759 w = (MIN_TOOLTIP_SIZE - 20) * fontSizePercent
760 end
761 else
762 w = MIN_TOOLTIP_SIZE * fontSizePercent / 2
763 end
764 if category.superCategory.x1 < w then
765 category.superCategory.x1 = w
766 end
767 end
768 end
769 if columns == 2 and self.text2 then
770 if not self.wrap2 then
771 testString:SetWidth(0)
772 testString:SetFontObject(self.font2)
773 local font,_,flags = testString:GetFont()
774 testString:SetFont(font, self.size2 * fontSizePercent, flags)
775 testString:SetText(self.text2)
776 w = w + 40 * fontSizePercent + testString:GetWidth()
777 if category.superCategory.x1 < w then
778 category.superCategory.x1 = w
779 end
780 else
781 w = w + 40 * fontSizePercent + MIN_TOOLTIP_SIZE * fontSizePercent / 2
782 if category.superCategory.x1 < w then
783 category.superCategory.x1 = w
784 end
785 end
786 elseif columns >= 3 then
787 if self.text2 then
788 if not self.wrap2 then
789 testString:SetWidth(0)
790 testString:SetFontObject(self.font2)
791 local font,_,flags = testString:GetFont()
792 testString:SetFont(font, self.size2 * fontSizePercent, flags)
793 testString:SetText(self.text2)
794 local w = testString:GetWidth()
795 if category.superCategory.x2 < w then
796 category.superCategory.x2 = w
797 end
798 else
799 local w = MIN_TOOLTIP_SIZE / 2
800 if category.superCategory.x2 < w then
801 category.superCategory.x2 = w
802 end
803 end
804 end
805 if self.text3 then
806 if not self.wrap3 then
807 testString:SetWidth(0)
808 testString:SetFontObject(self.font3)
809 local font,_,flags = testString:GetFont()
810 testString:SetFont(font, self.size3 * fontSizePercent, flags)
811 testString:SetText(self.text3)
812 local w = testString:GetWidth()
813 if category.superCategory.x3 < w then
814 category.superCategory.x3 = w
815 end
816 else
817 local w = MIN_TOOLTIP_SIZE / 2
818 if category.superCategory.x3 < w then
819 category.superCategory.x3 = w
820 end
821 end
822 end
823 if columns >= 4 then
824 if self.text4 then
825 if not self.wrap4 then
826 testString:SetWidth(0)
827 testString:SetFontObject(self.font4)
828 local font,_,flags = testString:GetFont()
829 testString:SetFont(font, self.size4 * fontSizePercent, flags)
830 testString:SetText(self.text4)
831 w = testString:GetWidth()
832 if category.superCategory.x4 < w then
833 category.superCategory.x4 = w
834 end
835 else
836 local w = MIN_TOOLTIP_SIZE / 2
837 if category.superCategory.x4 < w then
838 category.superCategory.x4 = w
839 end
840 end
841 end
842 end
843 end
844 return self
845 end
846  
847 function Line:del()
848 del(self)
849 end
850  
851 function Line:Display(tablet)
852 tablet:AddLine(self)
853 return true
854 end
855 end
856  
857 local function button_OnEnter()
858 if this.self:GetScript("OnEnter") then
859 this.self:GetScript("OnEnter")()
860 end
861 this.highlight:Show()
862 end
863  
864 local function button_OnLeave()
865 if this.self:GetScript("OnLeave") then
866 this.self:GetScript("OnLeave")()
867 end
868 this.highlight:Hide()
869 end
870  
871 local function NewLine(self)
872 if self.maxLines <= self.numLines then
873 self.maxLines = self.maxLines + 1
874 local button = CreateFrame("Button", nil, self)
875 button.indentation = 0
876 local check = button:CreateTexture(nil, "ARTWORK")
877 local left = button:CreateFontString(nil, "ARTWORK")
878 local right = button:CreateFontString(nil, "ARTWORK")
879 local third = button:CreateFontString(nil, "ARTWORK")
880 local fourth = button:CreateFontString(nil, "ARTWORK")
881 local highlight = button:CreateTexture(nil, "BACKGROUND")
882 highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
883 button.highlight = highlight
884 highlight:SetBlendMode("ADD")
885 highlight:SetAllPoints(button)
886 highlight:Hide()
887 table.insert(self.buttons, button)
888 table.insert(self.checks, check)
889 table.insert(self.lefts, left)
890 table.insert(self.rights, right)
891 table.insert(self.thirds, third)
892 table.insert(self.fourths, fourth)
893 left:SetWidth(0)
894 if self.maxLines == 1 then
895 left:SetFontObject(GameTooltipHeaderText)
896 right:SetFontObject(GameTooltipHeaderText)
897 third:SetFontObject(GameTooltipHeaderText)
898 fourth:SetFontObject(GameTooltipHeaderText)
899 left:SetJustifyH("CENTER")
900 button:SetPoint("TOPLEFT", self, "TOPLEFT", 8, -10)
901 else
902 left:SetFontObject(GameTooltipText)
903 right:SetFontObject(GameTooltipText)
904 third:SetFontObject(GameTooltipText)
905 fourth:SetFontObject(GameTooltipText)
906 button:SetPoint("TOPLEFT", self.buttons[self.maxLines - 1], "BOTTOMLEFT", 0, -2)
907 end
908 button:SetScript("OnEnter", button_OnEnter)
909 button:SetScript("OnLeave", button_OnLeave)
910 button.check = check
911 button.self = self
912 button:SetPoint("RIGHT", self, "RIGHT", -12, 0)
913 check.shown = false
914 check:SetPoint("TOPLEFT", button, "TOPLEFT")
915 left:SetPoint("TOPLEFT", check, "TOPLEFT")
916 right:SetPoint("TOPLEFT", left, "TOPRIGHT", 40 * self.fontSizePercent, 0)
917 third:SetPoint("TOPLEFT", right, "TOPRIGHT", 20 * self.fontSizePercent, 0)
918 fourth:SetPoint("TOPLEFT", third, "TOPRIGHT", 20 * self.fontSizePercent, 0)
919 right:SetJustifyH("RIGHT")
920 local _,size = GameTooltipText:GetFont()
921 check:SetHeight(size * 1.5)
922 check:SetWidth(size * 1.5)
923 check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
924 check:SetAlpha(0)
925 if not button.clicked then
926 button:SetScript("OnMouseWheel", self:GetScript("OnMouseWheel"))
927 button:EnableMouseWheel(true)
928 button:Hide()
929 end
930 check:Show()
931 left:Hide()
932 right:Hide()
933 end
934 end
935 NewLine = wrap(NewLine, "NewLine")
936  
937 local function GetMaxLinesPerScreen(self)
938 if self == tooltip then
939 return floor(50 / self.fontSizePercent)
940 else
941 return floor(30 / self.fontSizePercent)
942 end
943 end
944 GetMaxLinesPerScreen = wrap(GetMaxLinesPerScreen, "GetMaxLinesPerScreen")
945  
946 local detachedTooltips = {}
947 local AcquireDetachedFrame, ReleaseDetachedFrame
948 local function AcquireFrame(self, registration, data, detachedData)
949 if not detachedData then
950 detachedData = data
951 end
952 if tooltip then
953 tooltip.data = data
954 tooltip.detachedData = detachedData
955 local fontSizePercent = tooltip.data and tooltip.data.fontSizePercent or 1
956 local transparency = tooltip.data and tooltip.data.transparency or 0.75
957 local r = tooltip.data and tooltip.data.r or 0
958 local g = tooltip.data and tooltip.data.g or 0
959 local b = tooltip.data and tooltip.data.b or 0
960 tooltip:SetFontSizePercent(fontSizePercent)
961 tooltip:SetTransparency(transparency)
962 tooltip:SetColor(r, g, b)
963 else
964 tooltip = CreateFrame("Frame", "TabletLibFrame", UIParent)
965 tooltip.data = data
966 tooltip.detachedData = detachedData
967 tooltip:EnableMouse(true)
968 tooltip:EnableMouseWheel(true)
969 tooltip:SetFrameStrata("TOOLTIP")
970 tooltip:SetFrameLevel(10)
971 local backdrop = new(
972 'bgFile', "Interface\\Buttons\\WHITE8X8",
973 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border",
974 'tile', true,
975 'tileSize', 16,
976 'edgeSize', 16,
977 'insets', new(
978 'left', 5,
979 'right', 5,
980 'top', 5,
981 'bottom', 5
982 )
983 )
984 tooltip:SetBackdrop(backdrop)
985 del(backdrop.insets)
986 del(backdrop)
987 tooltip:SetBackdropColor(0, 0, 0, 1)
988  
989 tooltip.numLines = 0
990 --tooltip.categoryLines = {}
991 tooltip.idLines = {}
992 tooltip.categories = 0
993 tooltip.owner = nil
994 tooltip.fontSizePercent = tooltip.data and tooltip.data.fontSizePercent or 1
995 tooltip.maxLines = 0
996 tooltip.buttons = {}
997 tooltip.checks = {}
998 tooltip.lefts = {}
999 tooltip.rights = {}
1000 tooltip.thirds = {}
1001 tooltip.fourths = {}
1002 tooltip.transparency = tooltip.data and tooltip.data.transparency or 0.75
1003 tooltip:SetBackdropColor(0, 0, 0, tooltip.transparency)
1004 tooltip:SetBackdropBorderColor(1, 1, 1, tooltip.transparency)
1005 tooltip.scroll = 0
1006  
1007 tooltip:SetScript("OnUpdate", function()
1008 if not tooltip.updating and not tooltip.enteredFrame then
1009 tooltip.scroll = 0
1010 tooltip:Hide()
1011 tooltip.registration.tooltip = nil
1012 tooltip.registration = nil
1013 end
1014 end)
1015  
1016 tooltip:SetScript("OnEnter", function()
1017 if tooltip.clickable then
1018 tooltip.enteredFrame = true
1019 end
1020 end)
1021  
1022 tooltip:SetScript("OnLeave", function()
1023 if not tooltip.updating then
1024 tooltip.enteredFrame = false
1025 end
1026 end)
1027  
1028 tooltip:SetScript("OnMouseWheel", function()
1029 tooltip.updating = true
1030 tooltip:Scroll(arg1 < 0)
1031 tooltip.updating = false
1032 end)
1033  
1034 NewLine(tooltip)
1035  
1036 tooltip.scrollUp = tooltip:CreateFontString(nil, "ARTWORK")
1037 tooltip.scrollUp:SetPoint("TOPLEFT", tooltip.buttons[1], "BOTTOMLEFT", 0, -2)
1038 tooltip.scrollUp:SetPoint("RIGHT", tooltip, "RIGHT", 0, -10)
1039 tooltip.scrollUp:SetFontObject(GameTooltipText)
1040 tooltip.scrollUp:Hide()
1041 local font,_,flags = tooltip.scrollUp:GetFont()
1042 tooltip.scrollUp:SetFont(font, normalSize * tooltip.fontSizePercent, flags)
1043 tooltip.scrollUp:SetJustifyH("CENTER")
1044 tooltip.scrollUp:SetTextColor(1, 0.823529, 0)
1045 tooltip.scrollUp:SetText(" ")
1046  
1047 tooltip.scrollDown = tooltip:CreateFontString(nil, "ARTWORK")
1048 tooltip.scrollDown:SetPoint("TOPLEFT", tooltip.buttons[1], "BOTTOMLEFT", 0, -2)
1049 tooltip.scrollDown:SetPoint("RIGHT", tooltip, "RIGHT", 0, -10)
1050 tooltip.scrollDown:SetFontObject(GameTooltipText)
1051 tooltip.scrollDown:Hide()
1052 local font,_,flags = tooltip.scrollUp:GetFont()
1053 tooltip.scrollDown:SetFont(font, normalSize * tooltip.fontSizePercent, flags)
1054 tooltip.scrollDown:SetJustifyH("CENTER")
1055 tooltip.scrollDown:SetTextColor(1, 0.823529, 0)
1056 tooltip.scrollDown:SetText(" ")
1057  
1058 function tooltip:SetOwner(o)
1059 self:Hide(o)
1060 self.owner = o
1061 end
1062 tooltip.SetOwner = wrap(tooltip.SetOwner, "tooltip:SetOwner")
1063  
1064 function tooltip:IsOwned(o)
1065 return self.owner == o
1066 end
1067 tooltip.IsOwned = wrap(tooltip.IsOwned, "tooltip:IsOwned")
1068  
1069 function tooltip:ClearLines(hide)
1070 CleanCategoryPool(self)
1071 for i = 1, self.numLines do
1072 local button = self.buttons[i]
1073 local check = self.checks[i]
1074 if not button.clicked or hide then
1075 button:Hide()
1076 end
1077 check.shown = false
1078 check:SetAlpha(0)
1079 end
1080 for key,_ in pairs(self.idLines) do
1081 local i = self.idLines[key]
1082 if i then
1083 local check = self.checks[i]
1084 if check and check.shown then
1085 check.shown = false
1086 check:SetAlpha(0)
1087 end
1088 end
1089 self.idLines[key] = nil
1090 end
1091 self.numLines = 0
1092 self.categories = 0
1093 end
1094 tooltip.ClearLines = wrap(tooltip.ClearLines, "tooltip:ClearLines")
1095  
1096 function tooltip:NumLines()
1097 return self.numLines
1098 end
1099  
1100 local lastWidth
1101 local old_tooltip_Hide = tooltip.Hide
1102 function tooltip:Hide(newOwner)
1103 if self == tooltip or newOwner == nil then
1104 old_tooltip_Hide(self)
1105 end
1106 self:ClearLines(true)
1107 self.owner = nil
1108 self.lastWidth = nil
1109 end
1110 tooltip.Hide = wrap(tooltip.Hide, "tooltip:Hide")
1111  
1112 local old_tooltip_Show = tooltip.Show
1113 function tooltip:Show(tabletData)
1114 if self.owner == nil or self.notInUse then
1115 return
1116 end
1117 old_tooltip_Show(self)
1118  
1119 local maxWidth = tabletData and tabletData.width or self:GetWidth() - 20
1120 local hasWrap = false
1121 local screenWidth = GetScreenWidth()
1122 local scrollMax = self.numLines
1123 if scrollMax > GetMaxLinesPerScreen(self) + self.scroll then
1124 scrollMax = GetMaxLinesPerScreen(self) + self.scroll
1125 end
1126 local numColumns
1127 local x1, x2, x3, x4 = 0, 0, 0, 0
1128  
1129 local height = 20
1130 if scrollMax ~= self.numLines then
1131 self.scrollDown:SetWidth(maxWidth)
1132 height = height + self.scrollDown:GetHeight() + 2
1133 end
1134 if self.scroll ~= 0 then
1135 self.scrollUp:SetWidth(maxWidth)
1136 height = height + self.scrollUp:GetHeight() + 2
1137 end
1138 self:SetWidth(maxWidth + 20)
1139  
1140 local tmp = self.scroll + 1
1141 if tmp ~= 1 then
1142 tmp = tmp + 1
1143 end
1144 for i = 1, self.numLines do
1145 if i < tmp or i > scrollMax then
1146 self.buttons[i]:ClearAllPoints()
1147 self.buttons[i]:Hide()
1148 else
1149 if i ~= scrollMax or i == self.numLines then
1150 local button = self.buttons[i]
1151 local left = self.lefts[i]
1152 local right = self.rights[i]
1153 local third = self.thirds[i]
1154 local fourth = self.fourths[i]
1155 local check = self.checks[i]
1156 button:SetWidth(maxWidth)
1157 button:SetHeight(math.max(left:GetHeight(), right:GetHeight(), third:GetHeight(), fourth:GetHeight()))
1158 height = height + button:GetHeight() + 2
1159 if i == self.scroll + 1 then
1160 button:SetPoint("TOPLEFT", self, "TOPLEFT", 10, -10)
1161 else
1162 button:SetPoint("TOPLEFT", self.buttons[i - 1], "BOTTOMLEFT", 0, -2)
1163 end
1164 if button.clicked then
1165 check:SetPoint("TOPLEFT", button, "TOPLEFT", button.indentation * self.fontSizePercent + (check.width - check:GetWidth()) / 2 + 1, -1)
1166 else
1167 check:SetPoint("TOPLEFT", button, "TOPLEFT", button.indentation * self.fontSizePercent + (check.width - check:GetWidth()) / 2, 0)
1168 end
1169 button:Show()
1170 end
1171 end
1172 end
1173 if self.scroll ~= 0 then
1174 self.scrollUp:SetPoint("TOPLEFT", self, "TOPLEFT", 10, -10)
1175 self.buttons[self.scroll + 2]:SetPoint("TOPLEFT", self.scrollUp, "BOTTOMLEFT", 0, -2)
1176 self.scrollUp:SetText(SCROLL_UP .. " (" .. self.scroll + 2 .. " / " .. self.numLines .. ")")
1177 self.scrollUp:Show()
1178 else
1179 self.scrollUp:Hide()
1180 end
1181 if scrollMax ~= self.numLines and self.buttons[scrollMax - 1] then
1182 self.scrollDown:SetPoint("TOPLEFT", self.buttons[scrollMax - 1], "BOTTOMLEFT", 0, -2)
1183 self.scrollDown:SetText(SCROLL_DOWN .. " (" .. scrollMax - 1 .. " / " .. self.numLines .. ")")
1184 self.scrollDown:Show()
1185 else
1186 self.scrollDown:Hide()
1187 end
1188 self:SetHeight(height)
1189 end
1190 tooltip.Show = wrap(tooltip.Show, "tooltip:Show")
1191  
1192 local lastMouseDown
1193 local function button_OnClick()
1194 if this.self:HasScript("OnClick") and this.self:GetScript("OnClick") then
1195 this.self:GetScript("OnClick")()
1196 end
1197 if arg1 == "RightButton" then
1198 if this.self:HasScript("OnClick") and this.self:GetScript("OnClick") then
1199 this.self:GetScript("OnClick")()
1200 end
1201 elseif arg1 == "LeftButton" then
1202 if this.self.preventClick == nil or GetTime() > this.self.preventClick and GetTime() < lastMouseDown + 0.5 then
1203 this.self.preventClick = nil
1204 this.self.updating = true
1205 this.self.preventRefresh = true
1206 this.func(this.a1, this.a2, this.a3)
1207 this.self.preventRefresh = false
1208 this.self:children()
1209 this.self.updating = false
1210 end
1211 end
1212 end
1213 local function button_OnMouseUp()
1214 if this.self:HasScript("OnMouseUp") and this.self:GetScript("OnMouseUp") then
1215 this.self:GetScript("OnMouseUp")()
1216 end
1217 if arg1 ~= "RightButton" then
1218 if this.clicked then
1219 local a,b,c,d,e = this.check:GetPoint(1)
1220 this.check:SetPoint(a,b,c,d-1,e+1)
1221 this.clicked = false
1222 end
1223 end
1224 end
1225 local function button_OnMouseDown()
1226 if this.self:HasScript("OnMouseDown") and this.self:GetScript("OnMouseDown") then
1227 this.self:GetScript("OnMouseDown")()
1228 end
1229 lastMouseDown = GetTime()
1230 if arg1 ~= "RightButton" then
1231 local a,b,c,d,e = this.check:GetPoint(1)
1232 this.check:SetPoint(a,b,c,d+1,e-1)
1233 this.clicked = true
1234 end
1235 end
1236 function tooltip:AddLine(info)
1237 local category = info.category
1238 local maxWidth = category.tabletData.width
1239 local text = info.blank and "\n" or info.text
1240 local id = info.id
1241 local func = info.func
1242 local checked = info.checked
1243 local isRadio = info.isRadio
1244 local checkTexture = info.checkTexture
1245 local fontSizePercent = self.fontSizePercent
1246 if not info.font then
1247 info.font = GameTooltipText
1248 end
1249 if not info.size then
1250 _,info.size = info.font:GetFont()
1251 end
1252 local catStart = false
1253 local columns = category and category.columns or 1
1254 local x1, x2, x3, x4
1255 if category then
1256 x1, x2, x3, x4 = category.x1, category.x2, category.x3, category.x4
1257 else
1258 x1, x2, x3, x4 = 0, 0, 0, 0
1259 end
1260 if info.isTitle then
1261 justAddedTitle = true
1262 end
1263  
1264 self.numLines = self.numLines + 1
1265 NewLine(self)
1266 self.lefts[self.numLines]:Show()
1267 self.buttons[self.numLines]:Show()
1268 num = self.numLines
1269  
1270 if id ~= nil and self.idLines[id] == nil then
1271 self.idLines[id] = num
1272 end
1273 local button = self.buttons[num]
1274 button.indentation = info.indentation-- or 0
1275 local left = self.lefts[num]
1276 local right = self.rights[num]
1277 local third = self.thirds[num]
1278 local fourth = self.fourths[num]
1279 local check = self.checks[num]
1280 if columns >= 1 then
1281 left:SetFontObject(info.font)
1282 left:SetText(text)
1283 left:Show()
1284 if info.textR and info.textG and info.textB then
1285 left:SetTextColor(info.textR, info.textG, info.textB)
1286 else
1287 left:SetTextColor(1, 0.823529, 0)
1288 end
1289 local a,_,b = left:GetFont()
1290 left:SetFont(a, info.size * fontSizePercent, b)
1291 left:SetJustifyH(info.justify)
1292 end
1293 if columns >= 2 then
1294 right:SetFontObject(info.font2)
1295 right:SetText(info.text2)
1296 right:Show()
1297 if info.text2R and info.text2G and info.text2B then
1298 right:SetTextColor(info.text2R, info.text2G, info.text2B)
1299 else
1300 right:SetTextColor(1, 0.823529, 0)
1301 end
1302 local a,_,b = right:GetFont()
1303 right:SetFont(a, info.size2 * fontSizePercent, b)
1304 right:SetJustifyH(info.justify2)
1305 else
1306 right:SetText(nil)
1307 right:Hide()
1308 end
1309 if columns >= 3 then
1310 third:SetFontObject(info.font3)
1311 third:SetText(info.text3)
1312 third:Show()
1313 if info.text3R and info.text3G and info.text3B then
1314 third:SetTextColor(info.text3R, info.text3G, info.text3B)
1315 else
1316 third:SetTextColor(1, 0.823529, 0)
1317 end
1318 local a,_,b = third:GetFont()
1319 third:SetFont(a, info.size3 * fontSizePercent, b)
1320 right:ClearAllPoints()
1321 right:SetPoint("TOPLEFT", left, "TOPRIGHT", 20 * fontSizePercent, 0)
1322 third:SetJustifyH(info.justify3)
1323 else
1324 third:SetText(nil)
1325 third:Hide()
1326 right:SetPoint("TOPLEFT", left, "TOPRIGHT", 40 * fontSizePercent, 0)
1327 right:SetPoint("TOPRIGHT", button, "TOPRIGHT", -5, 0)
1328 end
1329 if columns >= 4 then
1330 fourth:SetFontObject(info.font4)
1331 fourth:SetText(info.text4)
1332 fourth:Show()
1333 if info.text4R and info.text4G and info.text4B then
1334 fourth:SetTextColor(info.text4R, info.text4G, info.text4B)
1335 else
1336 fourth:SetTextColor(1, 0.823529, 0)
1337 end
1338 local a,_,b = fourth:GetFont()
1339 fourth:SetFont(a, info.size4 * fontSizePercent, b)
1340 fourth:SetJustifyH(info.justify4)
1341 else
1342 fourth:SetText(nil)
1343 fourth:Hide()
1344 end
1345  
1346 check:SetWidth(info.size)
1347 check:SetHeight(info.size)
1348 check.width = info.size
1349 if info.hasCheck then
1350 check.shown = true
1351 check:Show()
1352 if isRadio then
1353 check:SetTexture(info.checkIcon or "Interface\\Buttons\\UI-RadioButton")
1354 if info.checked then
1355 check:SetAlpha(1)
1356 check:SetTexCoord(0.25, 0.5, 0, 1)
1357 else
1358 check:SetAlpha(self.transparency)
1359 check:SetTexCoord(0, 0.25, 0, 1)
1360 end
1361 else
1362 if info.checkIcon then
1363 check:SetTexture(info.checkIcon)
1364 else
1365 check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
1366 check:SetWidth(info.size * 1.5)
1367 check:SetHeight(info.size * 1.5)
1368 check.width = info.size * 1.2
1369 end
1370 check:SetTexCoord(0, 1, 0, 1)
1371 check:SetAlpha(info.checked and 1 or 0)
1372 end
1373 left:SetPoint("TOPLEFT", check, "TOPLEFT", check.width, 0)
1374 else
1375 left:SetPoint("TOPLEFT", check, "TOPLEFT")
1376 end
1377 if columns == 1 then
1378 left:SetWidth(maxWidth)
1379 elseif columns == 2 then
1380 left:SetWidth(0)
1381 right:SetWidth(0)
1382 if info.wrap then
1383 left:SetWidth(maxWidth - right:GetWidth() - 40 * fontSizePercent)
1384 elseif info.wrap2 then
1385 right:SetWidth(maxWidth - left:GetWidth() - 40 * fontSizePercent)
1386 end
1387 right:ClearAllPoints()
1388 right:SetPoint("TOPRIGHT", button, "TOPRIGHT", 0, 0)
1389 if not info.text2 then
1390 left:SetJustifyH(info.justify or "LEFT")
1391 end
1392 elseif columns == 3 then
1393 left:SetWidth(x1)
1394 right:SetWidth(x2)
1395 third:SetWidth(x3)
1396 right:ClearAllPoints()
1397 local num = (category.tabletData.width - x1 - x2 - x3) / 2
1398 right:SetPoint("TOPLEFT", left, "TOPRIGHT", num, 0)
1399 third:SetPoint("TOPLEFT", right, "TOPRIGHT", num, 0)
1400 elseif columns == 4 then
1401 left:SetWidth(x1)
1402 right:SetWidth(x2)
1403 third:SetWidth(x3)
1404 fourth:SetWidth(x4)
1405 local num = (category.tabletData.width - x1 - x2 - x3 - x4) / 3
1406 right:SetPoint("TOPLEFT", left, "TOPRIGHT", num, 0)
1407 third:SetPoint("TOPLEFT", right, "TOPRIGHT", num, 0)
1408 fourth:SetPoint("TOPLEFT", third, "TOPRIGHT", num, 0)
1409 end
1410 if not self.locked or IsAltKeyDown() then
1411 local func = info.func
1412 if func then
1413 if type(func) == "string" then
1414 assert(type(info.arg1) == "table", "Cannot call method " .. info.func .. " on a non-table")
1415 func = info.arg1[func]
1416 assert(type(func) == "function", "Method " .. info.func .. " nonexistant")
1417 end
1418 assert(type(func) == "function", "func must be a function or method")
1419 button.func = func
1420 button.a1 = info.arg1
1421 button.a2 = info.arg2
1422 button.a3 = info.arg3
1423 button.self = self
1424 button:SetScript("OnMouseUp", button_OnMouseUp)
1425 button:SetScript("OnMouseDown", button_OnMouseDown)
1426 button:SetScript("OnClick", button_OnClick)
1427 if button.clicked then
1428 button:SetButtonState("PUSHED")
1429 end
1430 button:EnableMouse(true)
1431 else
1432 button:SetScript("OnMouseDown", nil)
1433 button:SetScript("OnMouseUp", nil)
1434 button:SetScript("OnClick", nil)
1435 button:EnableMouse(false)
1436 end
1437 else
1438 button:SetScript("OnMouseDown", nil)
1439 button:SetScript("OnMouseUp", nil)
1440 button:SetScript("OnClick", nil)
1441 button:EnableMouse(false)
1442 end
1443 end
1444 tooltip.AddLine = wrap(tooltip.AddLine, "tooltip:AddLine")
1445  
1446 function tooltip:SetFontSizePercent(percent)
1447 local data, detachedData = self.data, self.detachedData
1448 if detachedData and detachedData.detached then
1449 data = detachedData
1450 end
1451 local lastSize = self.fontSizePercent
1452 percent = tonumber(percent) or 1
1453 if percent < 0.25 then
1454 percent = 0.25
1455 elseif percent > 4 then
1456 percent = 4
1457 end
1458 self.fontSizePercent = percent
1459 if data then
1460 data.fontSizePercent = percent ~= 1 and percent or nil
1461 end
1462 self.scrollUp:SetFont(font, normalSize * self.fontSizePercent, flags)
1463 self.scrollDown:SetFont(font, normalSize * self.fontSizePercent, flags)
1464 local ratio = self.fontSizePercent / lastSize
1465 for i = 1, self.numLines do
1466 local left = self.lefts[i]
1467 local right = self.rights[i]
1468 local third = self.thirds[i]
1469 local fourth = self.fourths[i]
1470 local check = self.checks[i]
1471 local font, size, flags = left:GetFont()
1472 left:SetFont(font, size * ratio, flags)
1473 local font, size, flags = right:GetFont()
1474 right:SetFont(font, size * ratio, flags)
1475 local font, size, flags = third:GetFont()
1476 third:SetFont(font, size * ratio, flags)
1477 local font, size, flags = fourth:GetFont()
1478 fourth:SetFont(font, size * ratio, flags)
1479 check.width = check.width * ratio
1480 check:SetWidth(check:GetWidth() * ratio)
1481 check:SetHeight(check:GetHeight() * ratio)
1482 end
1483 self:SetWidth((self:GetWidth() - 51) * ratio + 51)
1484 self:SetHeight((self:GetHeight() - 51) * ratio + 51)
1485 if self:IsShown() and self.children then
1486 self:Show()
1487 end
1488 end
1489 tooltip.SetFontSizePercent = wrap(tooltip.SetFontSizePercent, "tooltip:SetFontSizePercent")
1490  
1491 function tooltip:GetFontSizePercent()
1492 return self.fontSizePercent
1493 end
1494  
1495 function tooltip:SetTransparency(alpha)
1496 local data, detachedData = self.data, self.detachedData
1497 if detachedData and detachedData.detached then
1498 data = detachedData
1499 end
1500 self.transparency = alpha
1501 if data then
1502 data.transparency = alpha ~= 0.75 and alpha or nil
1503 end
1504 self:SetBackdropColor(self.r or 0, self.g or 0, self.b or 0, alpha)
1505 self:SetBackdropBorderColor(1, 1, 1, alpha)
1506 end
1507 tooltip.SetTransparency = wrap(tooltip.SetTransparency, "tooltip:SetTransparency")
1508  
1509 function tooltip:GetTransparency()
1510 return self.transparency
1511 end
1512  
1513 function tooltip:SetColor(r, g, b)
1514 local data, detachedData = self.data, self.detachedData
1515 if detachedData and detachedData.detached then
1516 data = detachedData
1517 end
1518 self.r = r
1519 self.g = g
1520 self.b = b
1521 if data then
1522 data.r = r ~= 0 and r or nil
1523 data.g = g ~= 0 and g or nil
1524 data.b = b ~= 0 and b or nil
1525 end
1526 self:SetBackdropColor(r or 0, g or 0, b or 0, self.transparency)
1527 self:SetBackdropBorderColor(1, 1, 1, self.transparency)
1528 end
1529 tooltip.SetColor = wrap(tooltip.SetColor, "tooltip:SetColor")
1530  
1531 function tooltip:GetColor()
1532 return self.r, self.g, self.b
1533 end
1534  
1535 function tooltip:Scroll(down)
1536 if down then
1537 if IsShiftKeyDown() then
1538 self.scroll = self.numLines - GetMaxLinesPerScreen(self)
1539 else
1540 self.scroll = self.scroll + 3
1541 end
1542 else
1543 if IsShiftKeyDown() then
1544 self.scroll = 0
1545 else
1546 self.scroll = self.scroll - 3
1547 end
1548 end
1549 if self.scroll > self.numLines - GetMaxLinesPerScreen(self) then
1550 self.scroll = self.numLines - GetMaxLinesPerScreen(self)
1551 end
1552 if self.scroll < 0 then
1553 self.scroll = 0
1554 end
1555 if self:IsShown() then
1556 self:Show()
1557 end
1558 end
1559 tooltip.Scroll = wrap(tooltip.Scroll, "tooltip:Scroll")
1560  
1561 function tooltip.Detach(tooltip)
1562 local owner = tooltip.owner
1563 tooltip:Hide()
1564 assert(tooltip.detachedData, "You cannot detach if detachedData is not present")
1565 tooltip.detachedData.detached = true
1566 local detached = AcquireDetachedFrame(self, tooltip.registration, tooltip.data, tooltip.detachedData)
1567  
1568 detached.menu, tooltip.menu = tooltip.menu, nil
1569 detached.children = tooltip.children
1570 tooltip.children = nil
1571 detached:SetOwner(owner)
1572 detached:children()
1573 detached:Show()
1574 end
1575 tooltip.Detach = wrap(tooltip.Detach, "tooltip:Detach")
1576 end
1577  
1578 tooltip.registration = registration
1579 registration.tooltip = tooltip
1580 return tooltip
1581 end
1582 AcquireFrame = wrap(AcquireFrame, "AcquireFrame")
1583  
1584 function ReleaseDetachedFrame(self, data, detachedData)
1585 if not detachedData then
1586 detachedData = data
1587 end
1588 for _, detached in ipairs(detachedTooltips) do
1589 if detached.detachedData == detachedData then
1590 detached.notInUse = true
1591 detached:Hide()
1592 detached.registration.tooltip = nil
1593 detached.registration = nil
1594 end
1595 end
1596 end
1597 ReleaseDetachedFrame = wrap(ReleaseDetachedFrame, "ReleaseDetachedFrame")
1598  
1599 function AcquireDetachedFrame(self, registration, data, detachedData)
1600 if not detachedData then
1601 detachedData = data
1602 end
1603 for _, detached in ipairs(detachedTooltips) do
1604 if detached.notInUse then
1605 detached.data = data
1606 detached.detachedData = detachedData
1607 detached.notInUse = nil
1608 local fontSizePercent = detachedData.fontSizePercent or 1
1609 local transparency = detachedData.transparency or 0.75
1610 local r = detachedData.r or 0
1611 local g = detachedData.g or 0
1612 local b = detachedData.b or 0
1613 detached:SetFontSizePercent(fontSizePercent)
1614 detached:SetTransparency(transparency)
1615 detached:SetColor(r, g, b)
1616 detached:ClearAllPoints()
1617 detached:SetPoint(detachedData.anchor or "CENTER", UIParent, detachedData.anchor or "CENTER", detachedData.offsetx or 0, detachedData.offsety or 0)
1618 detached.registration = registration
1619 registration.tooltip = detached
1620 return detached
1621 end
1622 end
1623  
1624 if not dewdrop and DewdropLib then
1625 dewdrop = DewdropLib:GetInstance('1.0')
1626 end
1627 if not sekeys and SpecialEventsEmbed and SpecialEventsEmbed.versions["Keys 1"] then
1628 sekeys = SpecialEventsEmbed:GetInstance("Keys 1")
1629 sekeys:RegisterEvent(self, "SPECIAL_ALTKEY_DOWN")
1630 sekeys:RegisterEvent(self, "SPECIAL_ALTKEY_UP")
1631  
1632 function self:SPECIAL_ALTKEY_DOWN()
1633 for _, detached in ipairs(detachedTooltips) do
1634 if detached:IsShown() and detached.locked then
1635 detached:EnableMouse(IsAltKeyDown())
1636 detached:children()
1637 end
1638 end
1639 end
1640  
1641 self.SPECIAL_ALTKEY_UP = self.SPECIAL_ALTKEY_DOWN
1642 end
1643 if not tooltip then
1644 AcquireFrame(self, {})
1645 end
1646 local detached = CreateFrame("Frame", "TabletLibDetachedFrame" .. (table.getn(detachedTooltips) + 1), UIParent)
1647 table.insert(detachedTooltips, detached)
1648 detached.notInUse = true
1649 detached:EnableMouse(not data.locked)
1650 detached:EnableMouseWheel(true)
1651 detached:SetMovable(true)
1652 detached:SetPoint(data.anchor or "CENTER", UIParent, data.anchor or "CENTER", data.offsetx or 0, data.offsety or 0)
1653  
1654 detached.numLines = 0
1655 --detached.categoryLines = {}
1656 detached.idLines = {}
1657 detached.categories = 0
1658 detached.owner = nil
1659 detached.fontSizePercent = 1
1660 detached.maxLines = 0
1661 detached.buttons = {}
1662 detached.checks = {}
1663 detached.lefts = {}
1664 detached.rights = {}
1665 detached.thirds = {}
1666 detached.fourths = {}
1667 detached.transparency = 0.75
1668 detached.r = 0
1669 detached.g = 0
1670 detached.b = 0
1671 detached:SetFrameStrata("BACKGROUND")
1672 detached:SetBackdrop(tmp.a(
1673 'bgFile', "Interface\\Buttons\\WHITE8X8",
1674 'edgeFile', "Interface\\Tooltips\\UI-Tooltip-Border",
1675 'tile', true,
1676 'tileSize', 16,
1677 'edgeSize', 16,
1678 'insets', tmp.b(
1679 'left', 5,
1680 'right', 5,
1681 'top', 5,
1682 'bottom', 5
1683 )
1684 ))
1685 detached.locked = data.locked
1686 detached.scroll = 0
1687  
1688 local width = GetScreenWidth()
1689 local height = GetScreenHeight()
1690 detached:SetScript("OnMouseDown", function()
1691 if arg1 == "LeftButton" then
1692 if not detached.locked then
1693 detached:StartMoving()
1694 end
1695 end
1696 end)
1697  
1698 detached:SetScript("OnMouseUp", function()
1699 if arg1 == "LeftButton" then
1700 if not detached.locked then
1701 detached:StopMovingOrSizing()
1702 local anchor
1703 local offsetx
1704 local offsety
1705 if detached:GetTop() + detached:GetBottom() < height then
1706 anchor = "BOTTOM"
1707 offsety = detached:GetBottom()
1708 if offsety < 0 then
1709 offsety = 0
1710 end
1711 if offsety < MainMenuBar:GetTop() and MainMenuBar:IsVisible() then
1712 offsety = MainMenuBar:GetTop()
1713 end
1714 local top = 0
1715 if FuBar then
1716 for i = 1, FuBar:GetNumPanels() do
1717 local panel = FuBar:GetPanel(i)
1718 if panel:GetAttachPoint() == "BOTTOM" then
1719 if panel.frame:GetTop() > top then
1720 top = panel.frame:GetTop()
1721 break
1722 end
1723 end
1724 end
1725 end
1726 if offsety < top then
1727 offsety = top
1728 end
1729 else
1730 anchor = "TOP"
1731 offsety = detached:GetTop() - height
1732 if offsety > 0 then
1733 offsety = 0
1734 end
1735 local bottom = GetScreenHeight()
1736 if FuBar then
1737 for i = 1, FuBar:GetNumPanels() do
1738 local panel = FuBar:GetPanel(i)
1739 if panel:GetAttachPoint() == "TOP" then
1740 if panel.frame:GetBottom() < bottom then
1741 bottom = panel.frame:GetBottom()
1742 break
1743 end
1744 end
1745 end
1746 end
1747 bottom = bottom - GetScreenHeight()
1748 if offsety > bottom then
1749 offsety = bottom
1750 end
1751 end
1752 if detached:GetLeft() + detached:GetRight() < width * 2 / 3 then
1753 anchor = anchor .. "LEFT"
1754 offsetx = detached:GetLeft()
1755 if offsetx < 0 then
1756 offsetx = 0
1757 end
1758 elseif detached:GetLeft() + detached:GetRight() < width * 4 / 3 then
1759 if anchor == "" then
1760 anchor = "CENTER"
1761 end
1762 offsetx = (detached:GetLeft() + detached:GetRight() - GetScreenWidth()) / 2
1763 else
1764 anchor = anchor .. "RIGHT"
1765 offsetx = detached:GetRight() - width
1766 if offsetx > 0 then
1767 offsetx = 0
1768 end
1769 end
1770 detached:ClearAllPoints()
1771 detached:SetPoint(anchor, UIParent, anchor, offsetx, offsety)
1772 local t = detached.detachedData
1773 if t.anchor ~= anchor or math.abs(t.offsetx - offsetx) > 8 or math.abs(t.offsety - offsety) > 8 then
1774 detached.preventClick = GetTime() + 0.05
1775 end
1776 t.anchor = anchor
1777 t.offsetx = offsetx
1778 t.offsety = offsety
1779 detached:Show()
1780 end
1781 end
1782 end)
1783  
1784 dewdrop:Register(detached,
1785 'children', function(level, value)
1786 if detached.menu then
1787 detached.menu(level, value)
1788 if level == 1 then
1789 dewdrop:AddLine()
1790 end
1791 end
1792 if level == 1 then
1793 if not detached.registration.cantAttach then
1794 dewdrop:AddLine(
1795 'text', DETACH,
1796 'checked', true,
1797 'arg1', detached,
1798 'func', "Attach",
1799 'closeWhenClicked', true
1800 )
1801 end
1802 dewdrop:AddLine(
1803 'text', LOCK,
1804 'checked', detached:IsLocked(),
1805 'arg1', detached,
1806 'func', "Lock",
1807 'closeWhenClicked', not detached:IsLocked()
1808 )
1809 dewdrop:AddLine(
1810 'text', COLOR,
1811 'hasColorSwatch', true,
1812 'r', detached.r,
1813 'g', detached.g,
1814 'b', detached.b,
1815 'swatchFunc', function(r, g, b)
1816 detached:SetColor(r, g, b)
1817 end,
1818 'hasOpacity', true,
1819 'opacity', detached.transparency,
1820 'opacityFunc', function(alpha)
1821 detached:SetTransparency(alpha)
1822 end,
1823 'cancelFunc', function(r, g, b, a)
1824 detached:SetColor(r, g, b)
1825 detached:SetTransparency(a)
1826 end
1827 )
1828 local value = detached:GetFontSizePercent()
1829 if value < 1 then
1830 value = value - 0.5
1831 else
1832 value = value / 2
1833 end
1834 dewdrop:AddLine(
1835 'text', SIZE,
1836 'hasArrow', true,
1837 'hasSlider', true,
1838 'sliderFunc', function(value)
1839 if value > 0.5 then
1840 value = value * 2
1841 else
1842 value = value + 0.5
1843 end
1844 detached:SetFontSizePercent(value)
1845 return format("%d%%", value * 100)
1846 end,
1847 'sliderTop', "200%",
1848 'sliderBottom', "50%",
1849 'sliderValue', value
1850 )
1851 dewdrop:AddLine()
1852 dewdrop:AddLine(
1853 'text', CLOSE_MENU,
1854 'func', function()
1855 dewdrop:Close()
1856 end
1857 )
1858 end
1859 end,
1860 'point', function()
1861 local x, y = detached:GetCenter()
1862 if x < GetScreenWidth() / 2 then
1863 if y < GetScreenHeight() / 2 then
1864 return "BOTTOMLEFT", "BOTTOMRIGHT"
1865 else
1866 return "TOPLEFT", "TOPRIGHT"
1867 end
1868 else
1869 if y < GetScreenHeight() / 2 then
1870 return "BOTTOMRIGHT", "BOTTOMLEFT"
1871 else
1872 return "TOPRIGHT", "TOPLEFT"
1873 end
1874 end
1875 end
1876 )
1877  
1878 NewLine(detached)
1879  
1880 detached.scrollUp = detached:CreateFontString(nil, "ARTWORK")
1881 detached.scrollUp:SetPoint("TOPLEFT", detached.buttons[1], "BOTTOMLEFT", 0, -2)
1882 detached.scrollUp:SetPoint("RIGHT", detached, "RIGHT", 0, -10)
1883 detached.scrollUp:SetFontObject(GameTooltipText)
1884 detached.scrollUp:Hide()
1885 local font,_,flags = detached.scrollUp:GetFont()
1886 detached.scrollUp:SetFont(font, normalSize * detached.fontSizePercent, flags)
1887 detached.scrollUp:SetJustifyH("CENTER")
1888 detached.scrollUp:SetTextColor(1, 0.823529, 0)
1889 detached.scrollUp:SetText(" ")
1890  
1891 detached.scrollDown = detached:CreateFontString(nil, "ARTWORK")
1892 detached.scrollDown:SetPoint("TOPLEFT", detached.buttons[1], "BOTTOMLEFT", 0, -2)
1893 detached.scrollDown:SetPoint("RIGHT", detached, "RIGHT", 0, -10)
1894 detached.scrollDown:SetFontObject(GameTooltipText)
1895 detached.scrollDown:Hide()
1896 local font,_,flags = detached.scrollUp:GetFont()
1897 detached.scrollDown:SetFont(font, normalSize * detached.fontSizePercent, flags)
1898 detached.scrollDown:SetJustifyH("CENTER")
1899 detached.scrollDown:SetTextColor(1, 0.823529, 0)
1900 detached.scrollDown:SetText(" ")
1901  
1902 detached:SetScript("OnMouseWheel", function()
1903 detached:Scroll(arg1 < 0)
1904 end)
1905  
1906 detached.SetTransparency = tooltip.SetTransparency
1907 detached.GetTransparency = tooltip.GetTransparency
1908 detached.SetColor = tooltip.SetColor
1909 detached.GetColor = tooltip.GetColor
1910 detached.SetFontSizePercent = tooltip.SetFontSizePercent
1911 detached.GetFontSizePercent = tooltip.GetFontSizePercent
1912 detached.SetOwner = tooltip.SetOwner
1913 detached.IsOwned = tooltip.IsOwned
1914 detached.ClearLines = tooltip.ClearLines
1915 detached.NumLines = tooltip.NumLines
1916 detached.Hide = tooltip.Hide
1917 detached.Show = tooltip.Show
1918 detached.AddLine = tooltip.AddLine
1919 detached.Scroll = tooltip.Scroll
1920 function detached:IsLocked()
1921 return self.locked
1922 end
1923 function detached:Lock()
1924 self:EnableMouse(self.locked)
1925 self.locked = not self.locked
1926 self.detachedData.locked = self.locked or nil
1927 self:children()
1928 end
1929  
1930 function detached.Attach(detached)
1931 assert(detached, "Detached tooltip not given.")
1932 assert(detached.AddLine, "detached argument not a Tooltip.")
1933 assert(detached.owner, "Detached tooltip has no owner.")
1934 assert(not detached.notInUse, "Detached tooltip not in use.")
1935 detached.menu = nil
1936 detached.detachedData.detached = nil
1937 detached:SetOwner(nil)
1938 detached.notInUse = TRUE
1939 end
1940  
1941 return AcquireDetachedFrame(self, registration, data, detachedData)
1942 end
1943 AcquireDetachedFrame = wrap(AcquireDetachedFrame, "AcquireDetachedFrame")
1944  
1945 function lib:Close(parent)
1946 if not parent then
1947 if tooltip and tooltip:IsShown() then
1948 tooltip:Hide()
1949 tooltip.registration.tooltip = nil
1950 tooltip.registration = nil
1951 end
1952 return
1953 end
1954 local info = self.registry[parent]
1955 assert(info, "You cannot close a tablet with an unregistered parent frame.")
1956 local data = info.data
1957 local detachedData = info.detachedData
1958 if detachedData and detachedData.detached then
1959 ReleaseDetachedFrame(self, data, detachedData)
1960 elseif tooltip.data == data then
1961 tooltip:Hide()
1962 tooltip.registration.tooltip = nil
1963 tooltip.registration = nil
1964 end
1965 end
1966 lib.Close = wrap(lib.Close, "lib:Close")
1967  
1968 local currentFrame
1969 local currentTabletData
1970  
1971 function lib:Open(parent)
1972 assert(parent, "You must provide a parent frame whose tablet you mean to open.")
1973 local info = self.registry[parent]
1974 assert(info, "You cannot open a tablet with an unregistered parent frame.")
1975 self:Close()
1976 local data = info.data
1977 local detachedData = info.detachedData
1978 local children = info.children
1979 if not children then
1980 return
1981 end
1982 local frame = AcquireFrame(self, info, data, detachedData)
1983 frame.clickable = info.clickable
1984 frame.menu = info.menu
1985 local children = info.children
1986 function frame:children()
1987 if not self.preventRefresh then
1988 currentFrame = self
1989 currentTabletData = TabletData:new(self)
1990 self:ClearLines()
1991 if children then
1992 children()
1993 end
1994 currentTabletData:Display(currentFrame)
1995 self:Show(currentTabletData)
1996 currentTabletData:del()
1997 currentTabletData = nil
1998 currentFrame = nil
1999 end
2000 end
2001 frame:SetOwner(parent)
2002 frame:children()
2003 local point = info.point
2004 local relativePoint = info.point
2005 if type(point) == "function" then
2006 local b
2007 point, b = point(parent)
2008 if b then
2009 relativePoint = b
2010 end
2011 end
2012 if type(relativePoint) == "function" then
2013 relativePoint = relativePoint(parent)
2014 end
2015 if not point then
2016 point = "CENTER"
2017 end
2018 if not relativePoint then
2019 relativePoint = point
2020 end
2021 frame:ClearAllPoints()
2022 frame:SetPoint(point, parent, relativePoint)
2023 local offsetx = 0
2024 local offsety = 0
2025 if frame:GetBottom() and frame:GetLeft() then
2026 if frame:GetRight() > GetScreenWidth() then
2027 offsetx = frame:GetRight() - GetScreenWidth()
2028 elseif frame:GetLeft() < 0 then
2029 offsetx = -frame:GetLeft()
2030 end
2031 local ratio = GetScreenWidth() / GetScreenHeight()
2032 if ratio >= 2.4 and frame:GetRight() > GetScreenWidth() / 2 and frame:GetLeft() < GetScreenWidth() / 2 then
2033 if frame:GetCenter() < GetScreenWidth() / 2 then
2034 offsetx = frame:GetRight() - GetScreenWidth() / 2
2035 else
2036 offsetx = frame:GetLeft() - GetScreenWidth() / 2
2037 end
2038 end
2039 if frame:GetBottom() < 0 then
2040 offsety = frame:GetBottom()
2041 elseif frame:GetTop() and frame:GetTop() > GetScreenHeight() then
2042 offsety = frame:GetTop() - GetScreenHeight()
2043 end
2044 if frame:GetBottom() < MainMenuBar:GetTop() and MainMenuBar:IsVisible() and offsety < frame:GetBottom() - MainMenuBar:GetTop() then
2045 offsety = frame:GetBottom() - MainMenuBar:GetTop()
2046 end
2047  
2048 if FuBar then
2049 local top = 0
2050 if FuBar then
2051 for i = 1, FuBar:GetNumPanels() do
2052 local panel = FuBar:GetPanel(i)
2053 if panel:GetAttachPoint() == "BOTTOM" then
2054 if panel.frame:GetTop() > top then
2055 top = panel.frame:GetTop()
2056 break
2057 end
2058 end
2059 end
2060 end
2061 if frame:GetBottom() < top and offsety < frame:GetBottom() - top then
2062 offsety = frame:GetBottom() - top
2063 end
2064 local bottom = GetScreenHeight()
2065 if FuBar then
2066 for i = 1, FuBar:GetNumPanels() do
2067 local panel = FuBar:GetPanel(i)
2068 if panel:GetAttachPoint() == "TOP" then
2069 if panel.frame:GetBottom() < bottom then
2070 bottom = panel.frame:GetBottom()
2071 break
2072 end
2073 end
2074 end
2075 end
2076 if frame:GetTop() > bottom and offsety < frame:GetTop() - bottom then
2077 offsety = frame:GetTop() - bottom
2078 end
2079 end
2080 end
2081 frame:SetPoint(point, parent, relativePoint, -offsetx, -offsety)
2082  
2083 if detachedData and (info.cantAttach or detachedData.detached) and frame == tooltip then
2084 detachedData.detached = false
2085 frame:Detach()
2086 end
2087 end
2088 lib.Open = wrap(lib.Open, "lib:Open")
2089  
2090 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, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25, k26, v26, k27, v27, k28, v28, k29, v29, k30, v30)
2091 assert(parent, "You must provide a parent frame to register with")
2092 if self.registry[parent] then
2093 self:Unregister(parent)
2094 end
2095 local info
2096 if type(k1) == "table" and k1[0] then
2097 assert(type(self.registry[k1]) == "table", "Other parent not registered")
2098 info = copy(self.registry[k1])
2099 if type(v1) == "function" then
2100 info.point = v1
2101 info.relativePoint = nil
2102 end
2103 else
2104 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, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25, k26, v26, k27, v27, k28, v28, k29, v29, k30, v30)
2105 end
2106 self.registry[parent] = info
2107 info.data = info.data or info.detachedData
2108 info.detachedData = info.detachedData or info.data
2109 local data = info.data
2110 local detachedData = info.detachedData
2111 if not self.onceRegistered[parent] then
2112 if not dewdrop then
2113 dewdrop = DewdropLib:GetInstance('1.0')
2114 end
2115 local script = parent:GetScript("OnEnter")
2116 parent:SetScript("OnEnter", function()
2117 if script then
2118 script()
2119 end
2120 if self.registry[parent] then
2121 if (not data or not detachedData.detached) and not dewdrop:IsOpen(parent) then
2122 self:Open(parent)
2123 tooltip.enteredFrame = true
2124 end
2125 end
2126 end)
2127 local script = parent:GetScript("OnLeave")
2128 parent:SetScript("OnLeave", function()
2129 if script then
2130 script()
2131 end
2132 if self.registry[parent] then
2133 if tooltip and (not data or not detachedData or not detachedData.detached) then
2134 tooltip.enteredFrame = false
2135 end
2136 end
2137 end)
2138 if parent:HasScript("OnMouseDown") then
2139 local script = parent:GetScript("OnMouseDown")
2140 parent:SetScript("OnMouseDown", function()
2141 if script then
2142 script()
2143 end
2144 if self.registry[parent] and self.registry[parent].tooltip and self.registry[parent].tooltip == tooltip then
2145 tooltip:Hide()
2146 end
2147 end)
2148 end
2149 if parent:HasScript("OnMouseWheel") then
2150 local script = parent:GetScript("OnMouseWheel")
2151 parent:SetScript("OnMouseWheel", function()
2152 if script then
2153 script()
2154 end
2155 if self.registry[parent] and self.registry[parent].tooltip then
2156 self.registry[parent].tooltip:Scroll(arg1 < 0)
2157 end
2158 end)
2159 end
2160 end
2161 self.onceRegistered[parent] = true
2162 if GetMouseFocus() == parent then
2163 self:Open(parent)
2164 end
2165 end
2166 lib.Register = wrap(lib.Register, "lib:Register")
2167  
2168 function lib:Unregister(parent)
2169 assert(self.registry[parent], "You cannot unregister a parent frame if it has not been registered already.")
2170 self.registry[parent] = nil
2171 end
2172 lib.Unregister = wrap(lib.Unregister, "lib:Unregister")
2173  
2174 function lib:IsRegistered(parent)
2175 return self.registry[parent] and true
2176 end
2177 lib.IsRegistered = wrap(lib.IsRegistered, "lib:IsRegistered")
2178  
2179 local _id = 0
2180 local addedCategory
2181 local currentCategoryInfo
2182 local depth = 0
2183 local categoryPool = {}
2184 function CleanCategoryPool(self)
2185 for k,v in pairs(categoryPool) do
2186 del(v)
2187 categoryPool[k] = nil
2188 end
2189 _id = 0
2190 end
2191  
2192 function lib:AddCategory(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, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25, k26, v26, k27, v27, k28, v28, k29, v29, k30, v30)
2193 assert(currentFrame, "You must add categories in within a registration.")
2194 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, k21, v21, k22, v22, k23, v23, k24, v24, k25, v25, k26, v26, k27, v27, k28, v28, k29, v29, k30, v30)
2195 local cat = currentTabletData:AddCategory(info)
2196 del(info)
2197 return cat
2198 end
2199 lib.AddCategory = wrap(lib.AddCategory, "lib:AddCategory")
2200  
2201 function lib:SetHint(text)
2202 assert(currentFrame, "You must set hint within a registration.")
2203 assert(not currentCategoryInfo, "You cannot set hint in a category.")
2204 currentTabletData:SetHint(text)
2205 end
2206 lib.SetHint = wrap(lib.SetHint, "lib:SetHint")
2207  
2208 function lib:SetTitle(text)
2209 assert(currentFrame, "You must set title within a registration")
2210 assert(not currentCategoryInfo, "You cannot set title in a category.")
2211 currentTabletData:SetTitle(text)
2212 end
2213 lib.SetTitle = wrap(lib.SetTitle, "lib:SetTitle")
2214  
2215 function lib:GetNormalFontSize()
2216 return normalSize
2217 end
2218  
2219 function lib:GetHeaderFontSize()
2220 return headerSize
2221 end
2222  
2223 function lib:GetNormalFontObject()
2224 return GameTooltipText
2225 end
2226  
2227 function lib:GetHeaderFontObject()
2228 return GameTooltipHeaderText
2229 end
2230  
2231 function lib:SetFontSizePercent(parent, percent)
2232 assert(parent, "You must provide a parent frame to change font size.")
2233 if parent[0] then
2234 local info = self.registry[parent]
2235 assert(info, "You cannot change font size with an unregistered parent frame.")
2236 if info.tooltip then
2237 info.tooltip:SetFontSizePercent(percent)
2238 else
2239 if detachedData.detached then
2240 detachedData.fontSizePercent = percent
2241 else
2242 data.fontSizePercent = percent
2243 end
2244 end
2245 else
2246 parent.fontSizePercent = percent
2247 end
2248 end
2249 lib.SetFontSizePercent = wrap(lib.SetFontSizePercent, "lib:SetFontSizePercent")
2250  
2251 function lib:GetFontSizePercent(parent)
2252 assert(parent, "You must provide a parent frame to check font size.")
2253 if parent[0] then
2254 local info = self.registry[parent]
2255 assert(info, "You cannot check font size with an unregistered parent frame.")
2256 local data = info.data
2257 local detachedData = info.detachedData
2258 if detachedData.detached then
2259 return detachedData.fontSizePercent or 1
2260 else
2261 return data.fontSizePercent or 1
2262 end
2263 else
2264 return parent.fontSizePercent or 1
2265 end
2266 end
2267 lib.GetFontSizePercent = wrap(lib.GetFontSizePercent, "lib:GetFontSizePercent")
2268  
2269 function lib:SetTransparency(parent, percent)
2270 assert(parent, "You must provide a parent frame to change transparency")
2271 if parent[0] then
2272 local info = self.registry[parent]
2273 assert(info, "You cannot change transparency with an unregistered parent frame.")
2274 if info.tooltip then
2275 info.tooltip:SetTransparency(percent)
2276 else
2277 if detachedData.detached then
2278 detachedData.transparency = percent
2279 else
2280 data.transparency = percent
2281 end
2282 end
2283 else
2284 parent.transparency = percent
2285 end
2286 end
2287 lib.SetTransparency = wrap(lib.SetTransparency, "lib:SetTransparency")
2288  
2289 function lib:GetTransparency(parent)
2290 assert(parent, "You must provide a parent frame to check transparency")
2291 if parent[0] then
2292 local info = self.registry[parent]
2293 assert(info, "You cannot check transparency with an unregistered parent frame.")
2294 local data = info.data
2295 local detachedData = info.detachedData
2296 if detachedData.detached then
2297 return detachedData.transparency or 0.75
2298 else
2299 return data.transparency or 0.75
2300 end
2301 else
2302 return parent.transparency or 0.75
2303 end
2304 end
2305 lib.GetTransparency = wrap(lib.GetTransparency, "lib:GetTransparency")
2306  
2307 function lib:SetColor(parent, r, g, b)
2308 assert(parent, "You must provide a parent frame to change color")
2309 if parent[0] then
2310 local info = self.registry[parent]
2311 assert(info, "You cannot change color with an unregistered parent frame.")
2312 if info.tooltip then
2313 info.tooltip:SetColor(r, g, b)
2314 else
2315 if detachedData.detached then
2316 detachedData.r = r
2317 detachedData.g = g
2318 detachedData.b = b
2319 else
2320 data.r = r
2321 data.g = g
2322 data.b = b
2323 end
2324 end
2325 else
2326 parent.r = r
2327 parent.g = g
2328 parent.b = b
2329 end
2330 end
2331 lib.SetColor = wrap(lib.SetColor, "lib:SetColor")
2332  
2333 function lib:GetColor(parent)
2334 assert(parent, "You must provide a parent frame to check color")
2335 if parent[0] then
2336 local info = self.registry[parent]
2337 assert(info, "You cannot check color with an unregistered parent frame.")
2338 local data = info.data
2339 local detachedData = info.detachedData
2340 if detachedData.detached then
2341 return detachedData.r or 0, detachedData.g or 0, detachedData.b or 0
2342 else
2343 return data.r or 0, data.g or 0, data.b or 0
2344 end
2345 else
2346 return parent.r or 0, parent.g or 0, parent.b or 0
2347 end
2348 end
2349 lib.GetColor = wrap(lib.GetColor, "lib:GetColor")
2350  
2351 function lib:Detach(parent)
2352 assert(parent, "You must provide a parent frame to detach tablet")
2353 local info = self.registry[parent]
2354 assert(info, "You cannot detach tablet with an unregistered parent frame.")
2355 assert(info.detachedData, "You cannot detach tablet without a data field.")
2356 if info.tooltip and info.tooltip == tooltip then
2357 tooltip:Detach()
2358 else
2359 info.detachedData.detached = true
2360 local detached = AcquireDetachedFrame(self, info, info.data, info.detachedData)
2361  
2362 detached.menu = info.menu
2363 local children = info.children
2364 function detached:children()
2365 if not self.preventRefresh then
2366 currentFrame = self
2367 currentTabletData = TabletData:new(self)
2368 self:ClearLines()
2369 if children then
2370 children()
2371 end
2372 currentTabletData:Display(currentFrame)
2373 self:Show(currentTabletData)
2374 currentTabletData:del()
2375 currentTabletData = nil
2376 currentFrame = nil
2377 end
2378 end
2379 detached:SetOwner(parent)
2380 detached:children()
2381 end
2382 end
2383 lib.Detach = wrap(lib.Detach, "lib:Detach")
2384  
2385 function lib:Attach(parent)
2386 assert(parent, "You must provide a parent frame to detach tablet")
2387 local info = self.registry[parent]
2388 assert(info, "You cannot detach tablet with an unregistered parent frame.")
2389 assert(info.detachedData, "You cannot attach tablet without a data field.")
2390 if info.tooltip and info.tooltip ~= tooltip then
2391 info.tooltip:Attach()
2392 else
2393 info.detachedData.detached = false
2394 end
2395 end
2396 lib.Attach = wrap(lib.Attach, "lib:Attach")
2397  
2398 function lib:IsAttached(parent)
2399 assert(parent, "You must provide a parent frame to check tablet")
2400 local info = self.registry[parent]
2401 assert(info, "You cannot check tablet with an unregistered parent frame.")
2402 return not info.detachedData or not info.detachedData.detached
2403 end
2404 lib.IsAttached = wrap(lib.IsAttached, "lib:IsAttached")
2405  
2406 function lib:Refresh(parent)
2407 assert(parent, "You must provide a parent frame to refresh tablet")
2408 local info = self.registry[parent]
2409 assert(info, "You cannot refresh tablet with an unregistered parent frame.")
2410 local tt = info.tooltip
2411 if tt and not tt.preventRefresh and tt:IsShown() then
2412 tt.updating = true
2413 tt:children()
2414 tt.updating = false
2415 end
2416 end
2417 lib.Refresh = wrap(lib.Refresh, "lib:Refresh")
2418  
2419 function lib:IsLocked(parent)
2420 assert(parent, "You must provide a parent frame to detach tablet")
2421 local info = self.registry[parent]
2422 assert(info, "You cannot detach tablet with an unregistered parent frame.")
2423 return info.detachedData and info.detachedData.locked
2424 end
2425 lib.IsLocked = wrap(lib.IsLocked, "lib:IsLocked")
2426  
2427 function lib:ToggleLocked(parent)
2428 assert(parent, "You must provide a parent frame to detach tablet")
2429 local info = self.registry[parent]
2430 assert(info, "You cannot detach tablet with an unregistered parent frame.")
2431 if info.tooltip and info.tooltip ~= tooltip then
2432 info.tooltip:Lock()
2433 elseif info.detachedData then
2434 info.detachedData.locked = info.detachedData.locked
2435 end
2436 end
2437 lib.ToggleLocked = wrap(lib.ToggleLocked, "lib:ToggleLocked")
2438  
2439 if DEBUG then
2440 function lib:ListProfileInfo()
2441 local duration, times, memories = GetProfileInfo()
2442 assert(duration and times and memories)
2443 local t = new()
2444 for method in pairs(memories) do
2445 table.insert(t, method)
2446 end
2447 table.sort(t, function(alpha, bravo)
2448 if memories[alpha] ~= memories[bravo] then
2449 return memories[alpha] < memories[bravo]
2450 elseif times[alpha] ~= times[bravo] then
2451 return times[alpha] < times[bravo]
2452 else
2453 return alpha < bravo
2454 end
2455 end)
2456 local memory = 0
2457 local time = 0
2458 for _,method in ipairs(t) do
2459 DEFAULT_CHAT_FRAME:AddMessage(format("%s || %.3f s || %.3f%% || %d KiB", method, times[method], times[method] / duration * 100, memories[method]))
2460 memory = memory + memories[method]
2461 time = time + times[method]
2462 end
2463 DEFAULT_CHAT_FRAME:AddMessage(format("%s || %.3f s || %.3f%% || %d KiB", "Total", time, time / duration * 100, memory))
2464 table.setn(t, 0)
2465 del(t)
2466 end
2467 SLASH_TABLET1 = "/tablet"
2468 SLASH_TABLET2 = "/tabletlib"
2469 SlashCmdList["TABLET"] = function(msg)
2470 TabletLib:GetInstance(MAJOR_VERSION):ListProfileInfo()
2471 end
2472 end
2473 TabletLib:Register(lib)
2474 lib = nil