vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 local MAJOR_VERSION = "2.0"
2 local MINOR_VERSION = tonumber((string.gsub("$Revision: 9980 $", "^.-(%d+).-$", "%1")))
3  
4 if FUBAR_REVISION and FUBAR_REVISION > MINOR_VERSION then
5 MINOR_VERSION = FUBAR_REVISION
6 end
7 FUBAR_REVISION = nil
8  
9 local Compost = AceLibrary("Compost-2.0")
10 local Dewdrop = AceLibrary("Dewdrop-2.0")
11 local Tablet = AceLibrary:HasInstance("Tablet-2.0") and AceLibrary("Tablet-2.0")
12 local Jostle = AceLibrary("Jostle-2.0")
13  
14 local L = AceLibrary("AceLocale-2.0"):new("FuBar")
15  
16 FuBar = AceLibrary("AceAddon-2.0"):new("AceDB-2.0", "AceConsole-2.0", "AceEvent-2.0", "AceHook-2.0")
17 local FuBar = FuBar
18 FuBar.title = "FuBar"
19 FuBar.version = MAJOR_VERSION .. "." .. MINOR_VERSION
20 FuBar.date = string.gsub("$Date: 2006-09-03 12:10:31 -1000 (Sun, 03 Sep 2006) $", "^.-(%d%d%d%d%-%d%d%-%d%d).-$", "%1")
21  
22 FuBar:RegisterDB("FuBar2DB")
23  
24 local charID = AceLibrary("AceDB-2.0").CHAR_ID
25 local realmID = AceLibrary("AceDB-2.0").REALM_ID
26 local classID = AceLibrary("AceDB-2.0").CLASS_ID
27  
28 local _G = getfenv(0)
29 local plugins = {}
30  
31 local FuBar_Panel = FuBar_Panel
32 _G.FuBar_Panel = nil
33  
34 if not FUBAR_DEFAULTS then
35 FUBAR_DEFAULTS = function()
36 return {
37 fontSize = 12,
38 adjust = true,
39 panels = {
40 [1] = {
41 attachPoint = "TOP",
42 plugins = {
43 left = {
44 "LocationFu",
45 "ExperienceFu",
46 "PerformanceFu",
47 },
48 center = {},
49 right = {
50 "ClockFu",
51 "VolumeFu",
52 }
53 }
54 },
55 [2] = {
56 attachPoint = "BOTTOM"
57 }
58 }
59 }
60 end
61 end
62  
63 local CATEGORIES = {
64 ["Action Bars"] = L["Action Bars"],
65 ["Auction"] = L["Auction"],
66 ["Audio"] = L["Audio"],
67 ["Battlegrounds/PvP"] = L["Battlegrounds/PvP"],
68 ["Buffs"] = L["Buffs"],
69 ["Chat/Communication"] = L["Chat/Communication"],
70 ["Druid"] = L["Druid"],
71 ["Hunter"] = L["Hunter"],
72 ["Mage"] = L["Mage"],
73 ["Paladin"] = L["Paladin"],
74 ["Priest"] = L["Priest"],
75 ["Rogue"] = L["Rogue"],
76 ["Shaman"] = L["Shaman"],
77 ["Warlock"] = L["Warlock"],
78 ["Warrior"] = L["Warrior"],
79 ["Healer"] = L["Healer"],
80 ["Tank"] = L["Tank"],
81 ["Caster"] = L["Caster"],
82 ["Combat"] = L["Combat"],
83 ["Compilations"] = L["Compilations"],
84 ["Data Export"] = L["Data Export"],
85 ["Development Tools"] = L["Development Tools"],
86 ["Guild"] = L["Guild"],
87 ["Frame Modification"] = L["Frame Modification"],
88 ["Interface Enhancements"] = L["Interface Enhancements"],
89 ["Inventory"] = L["Inventory"],
90 ["Library"] = L["Library"],
91 ["Map"] = L["Map"],
92 ["Mail"] = L["Mail"],
93 ["Miscellaneous"] = L["Miscellaneous"],
94 ["Quest"] = L["Quest"],
95 ["Raid"] = L["Raid"],
96 ["Tradeskill"] = L["Tradeskill"],
97 ["UnitFrame"] = L["UnitFrame"],
98 ["Others"] = L["Others"],
99 }
100  
101 local basePluginFrame
102  
103 local alreadyEnabled = false
104  
105 local backgrounds = {["Interface\\AddOns\\FuBar\\background"] = L["Default"]}
106  
107 function FuBar:RegisterSkin(name, bgFile)
108 assert(type(name) == "string", "You must provide a name for your skin")
109 assert(type(bgFile) == "string", "You must provide a file for your skin")
110 if not backgrounds[bgFile] then
111 backgrounds[bgFile] = name
112 end
113 end
114  
115 local function SetBackground(bgFile)
116 if backgrounds[bgFile] then
117 FuBar.db.profile.skin = bgFile
118 FuBar_Panel:SetBackground(bgFile)
119 end
120 end
121  
122 local function GetBackground()
123 return backgrounds[FuBar.db.profile.skin] and FuBar.db.profile.skin or "Interface\\AddOns\\FuBar\\background"
124 end
125  
126 local function background_sort(alpha, bravo)
127 return backgrounds[alpha] < backgrounds[bravo]
128 end
129  
130 local optionsTable = {
131 handler = FuBar,
132 type = "group",
133 args = {
134 overflow = {
135 type = "toggle",
136 name = L["Overflow plugins"],
137 desc = L["Let plugins overflow onto another panel"],
138 get = "IsOverflowing",
139 set = "ToggleOverflowing",
140 },
141 create = {
142 type = "execute",
143 name = L["Create new panel"],
144 desc = L["Create new panel"],
145 func = "new",
146 handler = FuBar_Panel
147 },
148 adjust = {
149 type = "toggle",
150 name = L["Auto-adjust frames"],
151 desc = L["Toggle auto-adjustment of blizzard's frames"],
152 get = "IsAdjust",
153 set = "ToggleAdjust",
154 },
155 autohideTop = {
156 type = "toggle",
157 name = L["Auto-hide top panels"],
158 desc = L["Toggle auto-hiding of the top panels"],
159 get = "IsAutoHidingTop",
160 set = "ToggleAutoHidingTop",
161 },
162 autohideBottom = {
163 type = "toggle",
164 name = L["Auto-hide bottom panels"],
165 desc = L["Toggle auto-hiding of the bottom panels"],
166 get = "IsAutoHidingBottom",
167 set = "ToggleAutoHidingBottom",
168 },
169 texture = {
170 type = "text",
171 name = L["Texture"],
172 desc = L["Change the texture of the panels"],
173 get = GetBackground,
174 set = SetBackground,
175 validate = backgrounds
176 },
177 spacing = {
178 type = "group",
179 name = L["Spacing"],
180 desc = L["Spacing between plugins"],
181 args = {
182 left = {
183 type = "range",
184 name = L["Left-aligned spacing"],
185 desc = L["Set spacing between left-aligned plugins"],
186 max = 40,
187 min = 0,
188 step = 1,
189 get = "GetLeftSpacing",
190 set = "SetLeftSpacing",
191 },
192 center = {
193 type = "range",
194 name = L["Center-aligned spacing"],
195 desc = L["Set spacing between center-aligned plugins"],
196 max = 40,
197 min = 0,
198 step = 1,
199 get = "GetCenterSpacing",
200 set = "SetCenterSpacing",
201 },
202 right = {
203 type = "range",
204 name = L["Right-aligned spacing"],
205 desc = L["Set spacing between right-aligned plugins"],
206 max = 40,
207 min = 0,
208 step = 1,
209 get = "GetRightSpacing",
210 set = "SetRightSpacing",
211 },
212 }
213 },
214 fontsize = {
215 type = "group",
216 name = L["Font size"],
217 desc = L["Font size"],
218 args = {
219 panel = {
220 type = "range",
221 name = L["Panel font size"],
222 desc = L["Set font size for the plugins on the panel"],
223 max = 24,
224 min = 7,
225 step = 1,
226 get = "GetFontSize",
227 set = "SetFontSize",
228 },
229 tooltip = {
230 type = "range",
231 name = L["Tooltip font size"],
232 desc = L["Set font size for the tooltip"],
233 max = 2,
234 min = 0.5,
235 isPercent = true,
236 get = function()
237 return Tablet:GetFontSizePercent(FuBar.db.profile.tooltip)
238 end,
239 set = function(value)
240 return Tablet:SetFontSizePercent(FuBar.db.profile.tooltip, value)
241 end,
242 hidden = function()
243 return not Tablet
244 end
245 }
246 }
247 },
248 transparency = {
249 type = "group",
250 name = L["Transparency"],
251 desc = L["Transparency"],
252 args = {
253 panel = {
254 type = "range",
255 name = L["Panel transparency"],
256 desc = L["Set transparency of the panels"],
257 max = 1,
258 min = 0,
259 step = 0.05,
260 isPercent = true,
261 get = "GetTransparency",
262 set = "SetTransparency",
263 },
264 tooltip = {
265 type = "range",
266 name = L["Tooltip transparency"],
267 desc = L["Set transparency of the tooltip"],
268 max = 1,
269 min = 0,
270 step = 0.05,
271 isPercent = true,
272 get = function()
273 return Tablet:GetTransparency(FuBar.db.profile.tooltip)
274 end,
275 set = function(value)
276 return Tablet:SetTransparency(FuBar.db.profile.tooltip, value)
277 end,
278 hidden = function()
279 return not Tablet
280 end
281 }
282 }
283 },
284 thickness = {
285 type = "range",
286 name = L["Thickness"],
287 desc = L["Set thickness between the panels"],
288 max = 20,
289 min = 0,
290 step = 1,
291 get = "GetThickness",
292 set = "SetThickness",
293 },
294 }
295 }
296  
297 FuBar:RegisterChatCommand(L:GetTable("ChatCommands"), optionsTable)
298  
299 optionsTable.args.standby = nil
300  
301 function FuBar:GetScaledCursorPosition()
302 local x, y = GetCursorPosition()
303 local scale = GetScreenHeight() / 768
304 return x * scale, y * scale
305 end
306  
307 function FuBar:Reset()
308 self:UnregisterEvent("PLAYER_LOGOUT")
309 FuBar2DB = {}
310 ReloadUI()
311 end
312  
313 function FuBar:GetPanel(panelId)
314 return FuBar_Panel.instances[panelId]
315 end
316  
317 function FuBar:GetNumPanels()
318 return table.getn(FuBar_Panel.instances)
319 end
320  
321 function FuBar:GetBottommostTopPanel()
322 local bottom = GetScreenHeight()
323 local best
324 for i = 1, self:GetNumPanels() do
325 local panel = self:GetPanel(i)
326 if panel:GetAttachPoint() == "TOP" and panel.frame:GetBottom() < bottom then
327 bottom = panel.frame:GetBottom()
328 best = panel
329 end
330 end
331 return best
332 end
333  
334 function FuBar:GetTopmostBottomPanel()
335 local top = 0
336 local best
337 for i = 1, self:GetNumPanels() do
338 local panel = self:GetPanel(i)
339 if panel:GetAttachPoint() == "BOTTOM" and panel.frame:GetTop() > top then
340 top = panel.frame:GetTop()
341 best = panel
342 end
343 end
344 return best
345 end
346  
347 local isChangingProfile, previousProfile
348  
349 function FuBar:IsChangingProfile()
350 return isChangingProfile
351 end
352  
353 function FuBar:GetPluginProfiling()
354 for _,p in ipairs(plugins) do
355 if p:GetTitle() == self.db.profile.profilePlugin then
356 return p, p:GetTitle()
357 end
358 end
359 end
360  
361 function FuBar:SetPluginProfiling(plugin)
362 self.db.profile.profilePlugin = plugin:GetTitle()
363 end
364  
365 function FuBar:IsAdjust()
366 return self.db.profile.adjust
367 end
368  
369 function FuBar:ToggleAdjust()
370 self.db.profile.adjust = not self.db.profile.adjust
371 self:UpdateJostleAdjustments()
372 return self.db.profile.adjust
373 end
374  
375 function FuBar:IsOverflowing()
376 return not self.db.profile.overflow
377 end
378  
379 function FuBar:ToggleOverflowing()
380 self.db.profile.overflow = not self.db.profile.overflow
381 for i = 1, self:GetNumPanels() do
382 self:GetPanel(i):CheckForOverlap()
383 end
384 return not self.db.profile.overflow
385 end
386  
387 function FuBar:UpdateJostleAdjustments()
388 if not self.db.profile.adjust then
389 Jostle:DisableTopAdjusting()
390 Jostle:DisableBottomAdjusting()
391 else
392 if self:IsAutoHidingTop() then
393 Jostle:DisableTopAdjusting()
394 else
395 Jostle:EnableTopAdjusting()
396 end
397 if self:IsAutoHidingBottom() then
398 Jostle:DisableBottomAdjusting()
399 else
400 Jostle:EnableBottomAdjusting()
401 end
402 end
403 end
404  
405 function FuBar:IsAutoHidingTop()
406 return self.db.profile.autohideTop
407 end
408  
409 local autohideTopTime, autohideBottomTime
410  
411 function FuBar:ToggleAutoHidingTop()
412 self.db.profile.autohideTop = not self.db.profile.autohideTop
413 self:UpdateJostleAdjustments()
414 if not self.db.profile.autohideTop then
415 for i = 1, self:GetNumPanels() do
416 if self:GetPanel(i):GetAttachPoint() == "TOP" then
417 local frame = getglobal("FuBarFrame" .. i)
418 frame:SetAlpha(1)
419 frame:SetFrameStrata("HIGH")
420 end
421 end
422 else
423 self:ScheduleEvent("FuBar_AutoHideTop", self.OnUpdate_AutoHideTop, 1, self)
424 end
425 autohideTopTime = GetTime()
426 return self.db.profile.autohideTop
427 end
428  
429 function FuBar:IsAutoHidingBottom()
430 return self.db.profile.autohideBottom
431 end
432  
433 function FuBar:ToggleAutoHidingBottom()
434 self.db.profile.autohideBottom = not self.db.profile.autohideBottom
435 self:UpdateJostleAdjustments()
436 if not self.db.profile.autohideBottom then
437 for i = 1, self:GetNumPanels() do
438 if self:GetPanel(i):GetAttachPoint() == "BOTTOM" then
439 local frame = getglobal("FuBarFrame" .. i)
440 frame:SetAlpha(1)
441 frame:SetFrameStrata("HIGH")
442 end
443 end
444 else
445 self:ScheduleEvent("FuBar_AutoHideBottom", self.OnUpdate_AutoHideBottom, 1, self)
446 end
447 autohideBottomTime = GetTime()
448 return self.db.profile.autohideBottom
449 end
450  
451 function FuBar:GetFontSize()
452 if not self.db.profile then
453 return 12
454 end
455 return self.db.profile.fontSize or 12
456 end
457  
458 function FuBar:SetFontSize(size)
459 size = size or 12
460 self.db.profile.fontSize = size
461 for i,plugin in ipairs(plugins) do
462 if type(plugin.SetFontSize) ~= "function" then
463 table.remove(plugins, i)
464 i = i - 1
465 else
466 plugin:SetFontSize(size)
467 end
468 end
469 for i = 1, self:GetNumPanels() do
470 self:GetPanel(i):UpdateTexture()
471 end
472 self:Update()
473 Jostle:Refresh()
474 end
475  
476 function FuBar:GetLeftSpacing()
477 if not self.db.profile then
478 return 20
479 end
480 return self.db.profile.leftSpacing or 20
481 end
482  
483 function FuBar:SetLeftSpacing(size)
484 self.db.profile.leftSpacing = size
485 self:Update()
486 end
487  
488 function FuBar:GetCenterSpacing()
489 if not self.db.profile then
490 return 20
491 end
492 return self.db.profile.centerSpacing or 20
493 end
494  
495 function FuBar:SetCenterSpacing(size)
496 self.db.profile.centerSpacing = size
497 self:Update()
498 end
499  
500 function FuBar:GetRightSpacing()
501 if not self.db.profile then
502 return 20
503 end
504 return self.db.profile.rightSpacing or 20
505 end
506  
507 function FuBar:SetRightSpacing(size)
508 self.db.profile.rightSpacing = size
509 self:Update()
510 end
511  
512 function FuBar:SetThickness(size)
513 self.db.profile.thickness = size
514 for i = 1, self:GetNumPanels() do
515 self:GetPanel(i):UpdateTexture()
516 end
517 self:Update()
518 Jostle:Refresh()
519 end
520  
521 function FuBar:GetThickness(size)
522 if not self.db.profile then
523 return 5
524 end
525 return self.db.profile.thickness or 5
526 end
527  
528 function FuBar:GetTransparency()
529 return self.db.profile.transparency or 0.8
530 end
531  
532 function FuBar:SetTransparency(value)
533 self.db.profile.transparency = value
534 for i = 1, self:GetNumPanels() do
535 self:GetPanel(i):UpdateTexture()
536 end
537 end
538  
539 local function CheckLoadCondition(loadCondition)
540 return RunScript("(function()"..loadCondition.." end)()")
541 end
542  
543 local function _IsCorrectPlugin(plugin)
544 if type(plugin) ~= "table" then
545 return false
546 elseif type(plugin.GetName) ~= "function" then
547 return false
548 elseif type(plugin.GetTitle) ~= "function" then
549 return false
550 elseif type(plugin.GetCategory) ~= "function" then
551 return false
552 elseif type(plugin.SetFontSize) ~= "function" then
553 return false
554 elseif type(plugin.GetFrame) ~= "function" then
555 return false
556 elseif type(plugin.Show) ~= "function" then
557 return false
558 elseif type(plugin.Hide) ~= "function" then
559 return false
560 elseif type(plugin.GetPanel) ~= "function" then
561 return false
562 elseif type(plugin:GetName()) ~= "string" then
563 return false
564 elseif type(plugin:GetTitle()) ~= "string" then
565 return false
566 elseif type(plugin:GetCategory()) ~= "string" then
567 return false
568 end
569 local frame = plugin:GetFrame()
570 if type(frame) ~= "table" then
571 return false
572 elseif type(frame[0]) ~= "userdata" then
573 return false
574 elseif type(frame.GetFrameType) ~= "function" then
575 return false
576 elseif type(frame:GetFrameType()) ~= "string" then
577 return false
578 end
579 return true
580 end
581  
582 local donothing = function() end
583  
584 local function IsCorrectPlugin(plugin)
585 local add = DEFAULT_CHAT_FRAME.AddMessage
586 DEFAULT_CHAT_FRAME.AddMessage = donothing
587 local ret, msg = pcall(_IsCorrectPlugin, plugin)
588 DEFAULT_CHAT_FRAME.AddMessage = add
589 if ret then
590 return msg
591 end
592 end
593  
594 local function _IsCorrectPanel(panel)
595 if type(panel) ~= "table" then
596 return false
597 elseif type(panel.AddPlugin) ~= "function" then
598 return false
599 elseif type(panel.RemovePlugin) ~= "function" then
600 return false
601 elseif type(panel.GetNumPlugins) ~= "function" then
602 return false
603 elseif type(panel:GetNumPlugins()) ~= "number" then
604 return false
605 elseif type(panel.GetPlugin) ~= "function" then
606 return false
607 elseif type(panel.HasPlugin) ~= "function" then
608 return false
609 elseif type(panel.GetPluginSide) ~= "function" then
610 return false
611 end
612 return true
613 end
614  
615 local function IsCorrectPanel(panel)
616 local add = DEFAULT_CHAT_FRAME.AddMessage
617 DEFAULT_CHAT_FRAME.AddMessage = donothing
618 local ret, msg = pcall(_IsCorrectPanel, panel)
619 DEFAULT_CHAT_FRAME.AddMessage = add
620 if ret then
621 return msg
622 end
623 end
624  
625 local n
626 local mt = {
627 __newindex = function(self, k, v)
628 rawset(self, k, v)
629 n[k] = v
630 end,
631 }
632  
633 local function IsAceAddon(addon)
634 if type(addon) ~= "table" then
635 return false
636 elseif addon == AceAddon then
637 return true
638 elseif not getmetatable(addon) then
639 return false
640 else
641 return IsAceAddon(getmetatable(addon).__index)
642 end
643 end
644  
645 local blank = {}
646 local function LoadAddOnWrapper(addon)
647 local o = getfenv(0)
648 n = {}
649 setmetatable(o, mt)
650 local success, ret = pcall(LoadAddOn, addon)
651 setmetatable(o, blank)
652 if not ret then
653 FuBar:Print("Error loading LoadOnDemand plugin " .. addon)
654 return
655 elseif not success then
656 FuBar:Print("Error loading LoadOnDemand plugin " .. addon .. ": " .. ret)
657 return
658 end
659  
660 local dependencies
661 local plugin
662 for k,v in pairs(n) do
663 if IsCorrectPlugin(v) then
664 if plugin then
665 if not dependencies then
666 dependencies = {}
667 end
668 table.insert(dependencies, plugin)
669 end
670 plugin = v
671 if IsAceAddon(plugin) then
672 if not plugin._initialized then
673 if not AceData.profileBasePath then
674 --plugin._initialized = true
675 --plugin:Initialize()
676 --ace1ToBeInitialized[plugin] = true
677 else
678 plugin._initialized = true
679 ace:InitializeApp(plugin)
680 end
681 end
682 else
683 if not plugin._initialized then
684 plugin._initialized = true
685 if type(plugin.Initialize) == "function" then
686 plugin:Initialize()
687 end
688 end
689 end
690 end
691 end
692 if not plugin then
693 FuBar:Print("Error loading LoadOnDemand plugin " .. addon)
694 return
695 end
696 return ret, plugin, dependencies
697 end
698  
699 local toBeLoaded
700  
701 local function CleanDB()
702 local self = FuBar
703  
704 local t = Compost:Acquire()
705 for _,panel in ipairs(self.db.profile.panels) do
706 if panel and panel.plugins then
707 for _,part in pairs(panel.plugins) do
708 if part then
709 for i,plugin in ipairs(part) do
710 if t[plugin] then
711 i = i - 1
712 table.remove(part, i)
713 else
714 t[plugin] = true
715 end
716 end
717 end
718 end
719 end
720 end
721 t = Compost:Reclaim(t)
722 end
723  
724 function FuBar:OnInitialize()
725 toBeLoaded = {}
726  
727 if not next(FuBar.db.profile) then
728 local def
729 local profile = self:GetProfile()
730 if string.find(profile, "^char/") or string.find(profile, "^class/") then
731 local _,class = UnitClass("player")
732 def = _G["FUBAR_DEFAULTS_" .. class] or FUBAR_DEFAULTS
733 else
734 def = FUBAR_DEFAULTS
735 end
736 if type(def) == "function" then
737 def = def()
738 end
739 for k,v in pairs(def) do
740 FuBar.db.profile[k] = v
741 end
742 end
743  
744 if not self.db.profile.loadOnDemand then
745 self.db.profile.loadOnDemand = {}
746 end
747  
748 if not self.db.profile.tooltip then
749 self.db.profile.tooltip = {}
750 end
751  
752 self:SetFontSize(self:GetFontSize())
753  
754 self.menu = function(level, value)
755 local panelId = FuBar_Panel.selectedPanel or 1
756 local panel = self:GetPanel(panelId)
757  
758 if not panel then
759 Dewdrop:Close()
760 return
761 end
762  
763 if level == 1 then
764 Dewdrop:AddLine(
765 'text', self.name,
766 'isTitle', true
767 )
768  
769 local menuTitles = Compost:Acquire()
770 for _,plugin in ipairs(plugins) do
771 local alreadyExists = false
772 local category = plugin:GetCategory()
773 if not CATEGORIES[category] then
774 category = L["Others"]
775 end
776 menuTitles[category] = true
777 end
778 for _,name in ipairs(toBeLoaded) do
779 local category = self.db.profile.loadOnDemand[name].category
780 if not CATEGORIES[category] then
781 category = L["Others"]
782 end
783 menuTitles[category] = true
784 end
785 local titles = Compost:Acquire()
786 for name in menuTitles do
787 table.insert(titles, name)
788 end
789 Compost:Reclaim(menuTitles)
790 table.sort(titles)
791 for _,category in ipairs(titles) do
792 Dewdrop:AddLine(
793 'text', CATEGORIES[category],
794 'value', category,
795 'hasArrow', true
796 )
797 end
798 Compost:Reclaim(titles)
799  
800 Dewdrop:AddLine()
801  
802 Dewdrop:AddLine(
803 'text', L["Attach"],
804 'hasArrow', true,
805 'value', "attach"
806 )
807  
808 Dewdrop:AddLine(
809 'text', L["Lock panel"],
810 'arg1', panel,
811 'func', "ToggleLocked",
812 'checked', panel:IsLocked()
813 )
814  
815 Dewdrop:AddLine(
816 'text', L["Remove panel"],
817 'arg1', panel,
818 'func', "WarnDestroy",
819 'disabled', panelId == 1 and not self:GetPanel(2),
820 'closeWhenClicked', true
821 )
822  
823 Dewdrop:AddLine()
824  
825 Dewdrop:FeedAceOptionsTable(optionsTable)
826  
827 Dewdrop:AddLine(
828 'text', CLOSE,
829 'arg1', Dewdrop,
830 'func', "Close"
831 )
832 elseif Dewdrop:FeedAceOptionsTable(optionsTable) then
833 elseif level == 2 then
834 if value == "attach" then
835 Dewdrop:AddLine(
836 'text', L["Attach to top"],
837 'arg1', panel,
838 'func', panel:GetAttachPoint() ~= "TOP" and "SetAttachPoint",
839 'arg2', "TOP",
840 'checked', panel:GetAttachPoint() == "TOP",
841 'closeWhenClicked', true,
842 'isRadio', true
843 )
844  
845 Dewdrop:AddLine(
846 'text', L["Attach to bottom"],
847 'arg1', panel,
848 'func', panel:GetAttachPoint() ~= "BOTTOM" and "SetAttachPoint",
849 'arg2', "BOTTOM",
850 'checked', panel:GetAttachPoint() == "BOTTOM",
851 'closeWhenClicked', true,
852 'isRadio', true
853 )
854  
855 Dewdrop:AddLine(
856 'text', L["Detach panel"],
857 'arg1', panel,
858 'func', panel:GetAttachPoint() ~= "NONE" and "SetAttachPoint",
859 'arg2', "NONE",
860 'checked', panel:GetAttachPoint() == "NONE",
861 'closeWhenClicked', true,
862 'isRadio', true
863 )
864 else
865 for _,plugin in ipairs(plugins) do
866 local category = plugin:GetCategory()
867 if not CATEGORIES[category] then
868 category = L["Others"]
869 end
870 if category == value then
871 Dewdrop:AddLine(
872 'text', plugin:GetTitle(),
873 'arg1', plugin,
874 'func', plugin:GetPanel() and "Hide" or "Show",
875 'arg2', FuBar_Panel.selectedPanel or 1,
876 'checked', plugin:GetPanel()
877 )
878 end
879 end
880 for i,name in ipairs(toBeLoaded) do
881 local i, name = i, name
882 local lod = self.db.profile.loadOnDemand[name]
883  
884 local category = lod.category
885 if not CATEGORIES[category] then
886 category = L["Others"]
887 end
888 if category == value then
889 Dewdrop:AddLine(
890 'text', lod.title,
891 'arg1', self,
892 'func', "LoadPlugin",
893 'arg2', name
894 )
895 end
896 end
897 end
898 end
899 end
900  
901 self:ScheduleEvent(self.LoadLoadOnDemandPlugins, 0, self)
902  
903 CleanDB()
904 end
905  
906 function FuBar:LoadPlugin(name)
907 if not alreadyEnabled then
908 local dep1,dep2,dep3,dep4 = GetAddOnDependencies(name)
909 if dep1 == "Ace" or dep2 == "Ace" or dep3 == "Ace" or dep4 == "Ace" then
910 if not self.acePluginToLoad then
911 self.acePluginToLoad = {}
912 end
913 self.acePluginToLoad[name] = true
914 return
915 end
916 end
917 local loaded, plugin, dependencies = LoadAddOnWrapper(name)
918 if loaded then
919 if type(plugin.SetLoadOnDemand) == "function" then
920 plugin:SetLoadOnDemand(true)
921 end
922 self.db.profile.loadOnDemand[name] = {
923 title = plugin:GetTitle(),
924 category = plugin:GetCategory(),
925 disabled = nil,
926 condition = type(plugin.GetLoadCondition) == "function" and plugin:GetLoadCondition() or nil,
927 }
928 plugin:Show(FuBar_Panel.selectedPanel or false)
929 if dependencies then
930 for _,v in ipairs(dependencies) do
931 if type(v.SetLoadOnDemand) == "function" then
932 v:SetLoadOnDemand(true)
933 end
934 self.db.profile.loadOnDemand[name].disabled = nil
935 for j,u in ipairs(toBeLoaded) do
936 if u == v:GetTitle() then
937 table.remove(toBeLoaded, j)
938 break
939 end
940 end
941 if v.hideWithoutStandby then
942 v:EnableApp()
943 else
944 v:Show(panelId or false)
945 end
946 end
947 end
948 self:SetFontSize(self:GetFontSize())
949 for i,n in ipairs(toBeLoaded) do
950 if n == name then
951 table.remove(toBeLoaded, i)
952 break
953 end
954 end
955 self.db.profile.loadOnDemand[name].disabled = nil
956 end
957 end
958  
959 function FuBar:OnEnable()
960 if alreadyEnabled then
961 ReloadUI()
962 return
963 end
964 alreadyEnabled = true
965  
966 if AceLibrary:HasInstance("Tablet-2.0") then
967 Tablet = AceLibrary("Tablet-2.0")
968 end
969 if not self.db.profile.panels then
970 self.db.profile.panels = {}
971 end
972  
973 if not self.db.profile.minimap then
974 self.db.profile.minimap = {}
975 end
976  
977 for i = table.getn(self.db.profile.panels), 1, -1 do
978 if self.db.profile.panels[i] then
979 FuBar_Panel:new()
980 end
981 end
982  
983 self:CheckResolution()
984  
985 if self:GetNumPanels() == 0 then
986 FuBar_Panel:new()
987 end
988  
989 if FuBar.db.profile.skin then
990 SetBackground(FuBar.db.profile.skin)
991 end
992  
993 self:RegisterEvent("AceLibrary_Register")
994 -- self:RegisterEvent("DISPLAY_SIZE_CHANGED", "OnDisplaySizeChanged")
995 self:RegisterEvent("CVAR_UPDATE", "OnCVarUpdate")
996  
997 self:Hook("RestartGx")
998  
999 local function func()
1000 if not self:SetupPlugins() then
1001 self:ScheduleEvent(func, 0)
1002 return
1003 end
1004 self:Update()
1005  
1006 self:ScheduleEvent("FuBar_AutoHideTop", self.OnUpdate_AutoHideTop, 1, self)
1007 self:ScheduleEvent("FuBar_AutoHideBottom", self.OnUpdate_AutoHideBottom, 1, self)
1008 end
1009 self:RegisterEvent("AceEvent_FullyInitialized", func, true)
1010  
1011 self:UpdateJostleAdjustments()
1012  
1013 if self.db.profile.skin and backgrounds[self.db.profile.skin] then
1014 FuBar_Panel:SetBackground(self.db.profile.skin)
1015 end
1016  
1017 self:RegisterEvent("PLAYER_ENTERING_WORLD", "PLAYER_ENTERING_WORLD", true)
1018 end
1019  
1020 function FuBar:LoadLoadOnDemandPlugins()
1021 for i = 1, GetNumAddOns() do
1022 local name, title, notes, enabled, loadable, reason, security = GetAddOnInfo(i)
1023 if IsAddOnLoadOnDemand(i) and enabled and loadable and not IsAddOnLoaded(i) then
1024 local deps = Compost:Acquire(GetAddOnDependencies(name))
1025 local good = false
1026 for _,dep in ipairs(deps) do
1027 if dep == "FuBar" then
1028 good = true
1029 break
1030 end
1031 end
1032 if good then
1033 if not self.db.profile.loadOnDemand[name] then
1034 self:LoadPlugin(name)
1035 elseif not self.db.profile.loadOnDemand[name].disabled and (not self.db.profile.loadOnDemand[name].condition or CheckLoadCondition(self.db.profile.loadOnDemand[name].condition)) then
1036 self:LoadPlugin(name)
1037 else
1038 table.insert(toBeLoaded, name)
1039 end
1040 end
1041 Compost:Reclaim(deps)
1042 end
1043 end
1044 end
1045  
1046 function FuBar:AceLibrary_Register(major, instance)
1047 if major == "Tablet-2.0" then
1048 Tablet = instance
1049 end
1050 end
1051  
1052 function FuBar:PLAYER_ENTERING_WORLD()
1053 if self.acePluginToLoad then
1054 for name in pairs(self.acePluginToLoad) do
1055 self:LoadPlugin(name)
1056 end
1057 Compost:Reclaim(self.acePluginToLoad)
1058 self.acePluginToLoad = nil
1059 end
1060 end
1061  
1062 function FuBar:RestartGx()
1063 self.hooks.RestartGx.orig()
1064 self:ScheduleEvent(self.Update, 0, self)
1065 end
1066  
1067 function FuBar:OnCVarUpdate()
1068 if arg1 == "USE_UISCALE" then
1069 self:ScheduleEvent(self.CheckResolution, 0, self)
1070 end
1071 end
1072  
1073 local lastScreenWidth = GetScreenWidth()
1074 function FuBar:CheckResolution()
1075 local screenWidth = GetScreenWidth()
1076 if lastScreenWidth ~= screenWidth then
1077 for i = 1, self:GetNumPanels() do
1078 self:GetPanel(i):Update()
1079 end
1080 lastScreenWidth = screenWidth
1081 Jostle:Refresh()
1082 end
1083 end
1084  
1085 local inTopPanel, inBottomPanel
1086  
1087 function FuBar:OnUpdate_AutoHideTop()
1088 if not inTopPanel and self:IsAutoHidingTop() then
1089 for i = 1, self:GetNumPanels() do
1090 if self:GetPanel(i):GetAttachPoint() == "TOP" then
1091 local frame = getglobal("FuBarFrame" .. i)
1092 frame:SetAlpha(0)
1093 frame:SetFrameStrata("BACKGROUND")
1094 end
1095 end
1096 end
1097 end
1098  
1099 function FuBar:OnUpdate_AutoHideBottom()
1100 if not inBottomPanel and self:IsAutoHidingBottom() then
1101 for i = 1, self:GetNumPanels() do
1102 if self:GetPanel(i):GetAttachPoint() == "BOTTOM" then
1103 local frame = getglobal("FuBarFrame" .. i)
1104 frame:SetAlpha(0)
1105 frame:SetFrameStrata("BACKGROUND")
1106 end
1107 end
1108 end
1109 end
1110  
1111 local doneSetupPlugins, pluginsToSetup
1112  
1113 function FuBar:OnDisable()
1114 for i = 1, self:GetNumPanels() do
1115 self:GetPanel(i).frame:Hide()
1116 end
1117 end
1118  
1119 function FuBar:Report()
1120 local report = Compost:Acquire(
1121 Compost:AcquireHash(
1122 'text', self.loc.ARGUMENT_ADJUST,
1123 'val', self:IsAdjust() and 1 or 0,
1124 'map', self.loc.MAP_ONOFF
1125 )
1126 )
1127 self.cmd:report(report)
1128 Compost:Reclaim(report, 1)
1129 end
1130  
1131 function FuBar:GetNumPlugins()
1132 return table.getn(plugins)
1133 end
1134  
1135 function FuBar:GetPlugin(i)
1136 return plugins[i]
1137 end
1138  
1139 function FuBar:RegisterPlugin(plugin)
1140 if not IsCorrectPlugin(plugin) then
1141 return
1142 end
1143 table.insert(plugins, plugin)
1144  
1145 local frame = plugin:GetFrame()
1146 local downTime
1147 if frame:HasScript("OnClick") then
1148 local OnClick = frame:GetScript("OnClick")
1149 frame:SetScript("OnClick", function()
1150 if OnClick and (not downTime or GetTime() < downTime + 0.5) and (not this.stopClick or GetTime() > this.stopClick) then
1151 OnClick()
1152 end
1153 downTime = nil
1154 end)
1155 end
1156 local OnMouseDown = frame:GetScript("OnMouseDown")
1157 frame:SetScript("OnMouseDown", function()
1158 if arg1 == "LeftButton" and not IsShiftKeyDown() and not IsControlKeyDown() and not IsAltKeyDown() then
1159 downTime = GetTime()
1160 FuBar:Plugin_StartDrag(plugin)
1161 end
1162 if OnMouseDown then
1163 OnMouseDown()
1164 end
1165 end)
1166 local OnMouseUp = frame:GetScript("OnMouseUp")
1167 frame:SetScript("OnMouseUp", function()
1168 if arg1 == "LeftButton" then
1169 if not FuBar:Plugin_StopDrag(plugin) then
1170 if OnMouseUp then
1171 OnMouseUp()
1172 end
1173 else
1174 this.stopClick = GetTime() + 0.05
1175 end
1176 elseif OnMouseUp then
1177 OnMouseUp()
1178 end
1179 end)
1180 local OnEnter = frame:GetScript("OnEnter")
1181 frame:SetScript("OnEnter", function()
1182 FuBar:Panel_OnEnter(plugin)
1183 if OnEnter then
1184 OnEnter()
1185 end
1186 end)
1187 local OnLeave = frame:GetScript("OnLeave")
1188 frame:SetScript("OnLeave", function()
1189 FuBar:Panel_OnLeave(this.plugin)
1190 if OnLeave then
1191 OnLeave()
1192 end
1193 end)
1194 end
1195  
1196 function FuBar:Update()
1197 for panelId = 1, self:GetNumPanels() do
1198 self:GetPanel(panelId):Update()
1199 end
1200 end
1201  
1202 function FuBar:SetupPlugins()
1203 doneSetupPlugins = true
1204 if pluginsToSetup then
1205 for i = 1, self:GetNumPanels() do
1206 local panel = self:GetPanel(i)
1207 for h = 1, 3 do
1208 local side
1209 if h == 1 then
1210 side = "LEFT"
1211 elseif h == 2 then
1212 side = "CENTER"
1213 else
1214 side = "RIGHT"
1215 end
1216 local order = panel:GetSavedOrder(side)
1217 for _,name in ipairs(order) do
1218 for plugin in pairs(pluginsToSetup) do
1219 if not plugin:IsDisabled() and plugin:GetTitle() == name then
1220 if not panel:AddPlugin(plugin, nil, side) then
1221 doneSetupPlugins = false
1222 return
1223 end
1224 pluginsToSetup[plugin] = nil
1225 break
1226 end
1227 end
1228 end
1229 end
1230 end
1231  
1232 local order = self.db.profile.detached
1233 if order then
1234 for name in pairs(order) do
1235 for plugin in pairs(pluginsToSetup) do
1236 if not plugin:IsDisabled() and plugin:GetTitle() == name then
1237 pluginsToSetup[plugin] = nil
1238 plugin:Show(0)
1239 break
1240 end
1241 end
1242 end
1243 else
1244 self.db.profile.detached = {}
1245 end
1246  
1247 for plugin in pairs(pluginsToSetup) do
1248 if type(plugin.GetDefaultPosition) == "function" and plugin:GetDefaultPosition() == "MINIMAP" then
1249 plugin:Show(0)
1250 else
1251 self.lastPanelId = (self.lastPanelId or 0) + 1
1252 if self.lastPanelId > self:GetNumPanels() then
1253 self.lastPanelId = 1
1254 end
1255 self:GetPanel(self.lastPanelId):AddPlugin(plugin, nil, type(plugin.GetDefaultPosition) == "function" and plugin:GetDefaultPosition() or "LEFT", true)
1256 end
1257 end
1258  
1259 pluginsToSetup = nil
1260 end
1261 return true
1262 end
1263  
1264 function FuBar:ShowPlugin(plugin, panelId)
1265 if doneSetupPlugins then
1266 if not panelId then
1267 doneSetupPlugins = false
1268 pluginsToSetup = Compost:Acquire()
1269 pluginsToSetup[plugin] = true
1270 local function func()
1271 if not self:SetupPlugins() then
1272 self:ScheduleEvent(func, 0)
1273 return
1274 end
1275 self:Update()
1276 end
1277 func()
1278 else
1279 self:GetPanel(panelId):AddPlugin(plugin, nil, type(plugin.GetDefaultPosition) == "function" and plugin:GetDefaultPosition() or "LEFT", true)
1280 end
1281 else
1282 if not pluginsToSetup then
1283 pluginsToSetup = {}
1284 end
1285 pluginsToSetup[plugin] = true
1286 end
1287 end
1288  
1289 local previousPosition_panel, previousPosition_index, previousPosition_side, previousPosition_x, previousPosition_y
1290  
1291 function FuBar:Plugin_StartDrag(plugin)
1292 local panel = plugin:GetPanel()
1293 assert(panel, plugin:GetTitle() .. ": You must be attached to a panel.")
1294 self:Panel_OnLeave()
1295 local index, side = panel:IndexOfPlugin(plugin)
1296  
1297 if index then
1298 if not panel:IsLocked() then
1299 if index < panel:GetNumPlugins(side) then
1300 local frame = panel:GetPlugin(index + 1, side).frame
1301 local x, y = frame:GetLeft(), frame:GetBottom()
1302 frame:ClearAllPoints()
1303 frame:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", x, y)
1304 end
1305  
1306 previousPosition_panel = panel
1307 previousPosition_index = index
1308 previousPosition_side = side
1309 previousPosition_x, previousPosition_y = self:GetScaledCursorPosition()
1310  
1311 FuBar_Panel:PreventUpdate()
1312 panel:RemovePlugin(index, side)
1313 plugin:GetFrame():StartMoving()
1314 end
1315 end
1316 end
1317  
1318 function FuBar:Plugin_StopDrag(plugin)
1319 plugin:GetFrame():StopMovingOrSizing()
1320 if previousPosition_panel and not previousPosition_panel:IsLocked() then
1321 local insertAt
1322 local panel = previousPosition_panel
1323 local side = previousPosition_side
1324 local x, y = self:GetScaledCursorPosition()
1325 local px, py = previousPosition_x, previousPosition_y
1326  
1327 for panelId = 1, self:GetNumPanels() do
1328 local p = self:GetPanel(panelId)
1329 local frame = p.frame
1330 local x1, x2, y1, y2 = frame:GetLeft(), frame:GetRight(), frame:GetBottom(), frame:GetTop()
1331 if x1 <= x and x <= x2 and y1 <= y and y <= y2 then
1332 panel = p
1333 break
1334 end
1335 end
1336  
1337 if panel:GetNumPlugins(side) == 0 then
1338 insertAt = 1
1339 else
1340 for i = 1, panel:GetNumPlugins(side) + 1 do
1341 local left, right
1342 local leftPlugin
1343 local rightPlugin
1344  
1345 leftPlugin = panel:GetPlugin(i - 1, side)
1346 rightPlugin = panel:GetPlugin(i, side)
1347  
1348 if side == "RIGHT" then
1349 leftPlugin, rightPlugin = rightPlugin, leftPlugin
1350 end
1351 left = leftPlugin and leftPlugin:GetFrame():GetCenter() or 0
1352 right = rightPlugin and rightPlugin:GetFrame():GetCenter() or GetScreenWidth()
1353 if left <= x and x <= right then
1354 insertAt = i
1355 break
1356 end
1357 end
1358 end
1359 if not insertAt then
1360 insertAt = panel:GetNumPlugins(side) + 1
1361 end
1362  
1363 panel:AddPlugin(plugin, insertAt, side)
1364 FuBar_Panel:StopPreventUpdate()
1365 previousPosition_panel:Update()
1366 panel:Update()
1367 previousPosition_panel = nil
1368 previousPosition_index = nil
1369 previousPosition_side = nil
1370 previousPosition_x = nil
1371 previousPosition_y = nil
1372 if math.abs(px - x) <= 5 and math.abs(py - y) <= 5 then
1373 return false
1374 else
1375 return true
1376 end
1377 end
1378 end
1379  
1380 function FuBar:Panel_OnEnter(plugin)
1381 local point = plugin
1382 if type(plugin) == "table" then
1383 point = plugin:GetPanel():GetAttachPoint()
1384 end
1385 if point == "TOP" then
1386 inTopPanel = true
1387 self:CancelScheduledEvent("FuBar_AutoHideTop")
1388 elseif point == "BOTTOM" then
1389 inBottomPanel = true
1390 self:CancelScheduledEvent("FuBar_AutoHideBottom")
1391 end
1392 for i = 1, self:GetNumPanels() do
1393 local panel = self:GetPanel(i)
1394 if panel:GetAttachPoint() == point then
1395 panel.frame:SetAlpha(1)
1396 panel.frame:SetFrameStrata("HIGH")
1397 end
1398 end
1399 end
1400  
1401 function FuBar:Panel_OnLeave(plugin)
1402 local point = plugin
1403 if type(plugin) == "table" then
1404 if not plugin:GetPanel() then
1405 return
1406 end
1407 point = plugin:GetPanel():GetAttachPoint()
1408 end
1409 if point == "TOP" then
1410 inTopPanel = false
1411 self:ScheduleEvent("FuBar_AutoHideTop", self.OnUpdate_AutoHideTop, 1, self)
1412 elseif point == "BOTTOM" then
1413 inBottomPanel = false
1414 self:ScheduleEvent("FuBar_AutoHideBottom", self.OnUpdate_AutoHideBottom, 1, self)
1415 end
1416 end
1417  
1418 function FuBar:OnProfileEnable(oldName, _, copyFrom)
1419 isChangingProfile = true
1420 if not next(FuBar.db.profile) then
1421 local def
1422 local profile = self:GetProfile()
1423 if string.find(profile, "^char/") or string.find(profile, "^class/") then
1424 local _,class = UnitClass("player")
1425 def = _G["FUBAR_DEFAULTS_" .. class] or FUBAR_DEFAULTS
1426 else
1427 def = FUBAR_DEFAULTS
1428 end
1429 if type(def) == "function" then
1430 def = def()
1431 end
1432 for k,v in pairs(def) do
1433 FuBar.db.profile[k] = v
1434 end
1435 end
1436  
1437 if not self.db.profile.loadOnDemand then
1438 self.db.profile.loadOnDemand = {}
1439 end
1440  
1441 if not self.db.profile.tooltip then
1442 self.db.profile.tooltip = {}
1443 end
1444  
1445 if not self.db.profile.panels then
1446 self.db.profile.panels = {}
1447 end
1448  
1449 CleanDB()
1450  
1451 doneSetupPlugins = false
1452 pluginsToSetup = {}
1453 for i,plugin in ipairs(plugins) do
1454 pluginsToSetup[plugin] = true
1455 local frame = plugin:GetFrame()
1456 frame:Hide()
1457 frame:ClearAllPoints()
1458 plugin:SetPanel(nil)
1459 end
1460  
1461 for i = self:GetNumPanels(), 1, -1 do
1462 self:GetPanel(i):del(true)
1463 end
1464  
1465 for i = table.getn(self.db.profile.panels), 1, -1 do
1466 if self.db.profile.panels[i] then
1467 FuBar_Panel:new()
1468 end
1469 end
1470  
1471 if self:GetNumPanels() == 0 then
1472 FuBar_Panel:new()
1473 end
1474  
1475 self:CheckResolution()
1476  
1477 for i = 1, GetNumAddOns() do
1478 local name, title, notes, enabled, loadable, reason, security = GetAddOnInfo(i)
1479 if IsAddOnLoadOnDemand(i) and enabled and loadable and not IsAddOnLoaded(i) then
1480 local good = false
1481 for _,dep in ipairs({GetAddOnDependencies(name)}) do
1482 if dep == "FuBar" then
1483 good = true
1484 end
1485 end
1486 if good then
1487 if not self.db.profile.loadOnDemand[name] then
1488 self:LoadPlugin(name)
1489 elseif not self.db.profile.loadOnDemand[name].disabled and (not self.db.profile.loadOnDemand[name].condition or CheckLoadCondition(self.db.profile.loadOnDemand[name].condition)) then
1490 self:LoadPlugin(name)
1491 else
1492 local exists = false
1493 for _,n in ipairs(toBeLoaded) do
1494 if n == name then
1495 exists = true
1496 break
1497 end
1498 end
1499 if not exists then
1500 table.insert(toBeLoaded, name)
1501 end
1502 end
1503 end
1504 end
1505 end
1506  
1507 for i,plugin in ipairs(plugins) do
1508 if plugin.IsDisabled and plugin:IsDisabled() and plugin:GetPanel() then
1509 plugin:GetPanel():RemovePlugin(plugin)
1510 end
1511 end
1512  
1513 local name = self:GetProfile()
1514 for _,plugin in ipairs(plugins) do
1515 if type(plugin.SetProfile) == "function" and not plugin.independentProfile then
1516 plugin:SetProfile(name, copyFrom)
1517 end
1518 end
1519  
1520 self:SetFontSize(self:GetFontSize())
1521  
1522 local function func()
1523 if not self:SetupPlugins() then
1524 self:ScheduleEvent(func, 0)
1525 return
1526 end
1527 self:Update()
1528 end
1529 self:ScheduleEvent(func, 0.01)
1530  
1531 isChangingProfile = false
1532 end
1533