diff --git a/Changelog and Notes.txt b/Changelog and Notes.txt index 895b7c1..a30e1d9 100644 --- a/Changelog and Notes.txt +++ b/Changelog and Notes.txt @@ -3,12 +3,17 @@ Backport: -Need to see why does it always open on home page via minimap button. + Need to fix transparency of settings in Settings main window. +May be backport retail quest accept. + + Functions: + +Add NPC specific tracking icons on minimap. Improve Quest Accept conditions (aka skip welcome window and block shared aka escort quests) Frame mover Square minimap diff --git a/Leatrix_Plus.lua b/Leatrix_Plus.lua index e7da531..e7538c2 100644 --- a/Leatrix_Plus.lua +++ b/Leatrix_Plus.lua @@ -1503,31 +1503,45 @@ end ---------------------------------------------------------------------- - -- Automate gossip (no reload required) + -- Automate gossip (no reload required) -- ---------------------------------------------------------------------- do + local isMessagePrinted = false + -- Function to skip gossip local function SkipGossip(skipAltKeyRequirement) if not skipAltKeyRequirement and not IsAltKeyDown() then return end - local gossipInfoTable = C_GossipInfo.GetOptions() - if gossipInfoTable and #gossipInfoTable == 1 and C_GossipInfo.GetNumAvailableQuests() == 0 and C_GossipInfo.GetNumActiveQuests() == 0 and gossipInfoTable[1] and gossipInfoTable[1].gossipOptionID then - C_GossipInfo.SelectOption(gossipInfoTable[1].gossipOptionID) + local gossipInfoTable = GetGossipOptions() + local getnumGossips = GetNumGossipOptions() + if getnumGossips ~=0 and GetNumGossipAvailableQuests() == 0 and GetNumGossipActiveQuests() == 0 then + SelectGossipOption(1) + if not isMessagePrinted then + print("|cFF00ff99Leatrix Plus:|r option chosen. Hold a shift key to override.") + isMessagePrinted = true + end end end + -- Reset Message flag when gossip window is closed + local function ResetMessageFlag() + isMessagePrinted = false + end + -- Create gossip event frame local gossipFrame = CreateFrame("FRAME") - -- Function to setup events - local function SetupEvents() - if LeaPlusLC["AutomateGossip"] == "On" then - gossipFrame:RegisterEvent("GOSSIP_SHOW") - else - gossipFrame:UnregisterEvent("GOSSIP_SHOW") - end + -- Function to setup events + local function SetupEvents() + if LeaPlusLC["AutomateGossip"] == "On" then + gossipFrame:RegisterEvent("GOSSIP_SHOW") + gossipFrame:RegisterEvent("GOSSIP_CLOSED") -- Added line to register GOSSIP_CLOSED event + else + gossipFrame:UnregisterEvent("GOSSIP_SHOW") + gossipFrame:UnregisterEvent("GOSSIP_CLOSED") -- Added line to unregister GOSSIP_CLOSED event end + end -- Setup events when option is clicked and on startup (if option is enabled) LeaPlusCB["AutomateGossip"]:HookScript("OnClick", SetupEvents) @@ -1556,16 +1570,24 @@ 30431, 32538, 32287, 32540, 32533, 31238, 29529, 28997, 32172, 31580, 27730, 28995, 28701, 32763, 32565, 28992, 29636, 8137, 31579, 29523, 32514, 31582, 18960, 32216, 28721, 35507, 32564, 28718, 7947, 18484, 29537, 12781, 20096, 18988, 32515, 340, 19186, 18987, 31863, 19296, 29535, 31581, 31031, 18911, 4561, 2664, 8139, 28722, 16585, 35508, 20097, 25206, 8145, 19663, 35498, 31910, 32773, 19373, 32380, 20028, 12022, 2810, 18011, 28715, 12793, 2821, 29547, 21655, 4229, 18015, 31032, 32385, 18773, 2803, 2806, 16583, 18753, 19004, 31916, 5494, 8125, 32509, 29493, 19213, 28742, 66, 29744, 32774, 18756, 18774, 16786, 12919, 15174, 33026, 18993, 29532, 20916, 1448, 18990, 30472, 16826, 29527, 3556, 19383, 18751, 34252, 28951, 28714, 29587, 25977, 5940, 19038, 31911, 1465, 29478, 18382, 3027, 14846, 2685, 31865, 31864, 21113, 28776, 12944, 16253, 19662, 3482, 16588, 16657, 3323, 14753, 5594, 19837, 24539, 30885, 12783, 18005, 18991, 4877, 19074, 12246, 10618, 7564, 12245, 26484, 12788, 28040, 1275, 18957, 32834, 12778, 19575, 14754, 20980, 21432, 17904, 18525, 13219, 35496, 23489, 32594, 19042, 12796, 18802, 8678, 16782, 29528, 16624, 3489, 4574, 5162, 32832, 18775, 5817, 6548, 11189, 29628, 26941, 17512, 28687, 2393, 1286, 20080, 14847, 32383, 35497, 9499, 19227, 20240, 3954, 8666, 12043, 1148, 19661, 11185, 28692, 27037, 25046, 19617, 29715, 29491, 11187, 16823, 28589, 3348, 13217, 3313, 30006, 18749, 6367, 3497, 21643, 22212, 5483, 16860, 28038, 30825, 7775, 15419, 4305, 11557, 33638, 29049, 3546, 22208, 4879, 3333, 32631, 27012, 4897, 1257, 19331, 15127, 26977, 25314, 18772, 2663, 6779, 13218, 23732, 28990, 14860, 26110, 14624, 1285, 1263, 14322, 33027, 15126, 18897, 35099, 3335, 2381, 23007, 14921, 18752, 16262, 5519, 1684, 3029, 21019, 32356, 35500, 29495, 18771, 29497, 32337, 17657, 12033, 27011, 32381, 3881, 26938, 27668, 2480, 734, 13216, 5188, 17585, 23381, 17246, 233, 4307, 32382, 20377, 21474, 20241, 8665, 19772, 4453, 3346, 35132, 13476, 9179, 20242, 27722, 22213, 8401, 28685, 19196, 24780, 1301, 5193, 33679, 12795, 6746, 27039, 16635, 277, 4731, 5942, 24291, 29716, 19694, 15179, 26995, 3960, 19521, 20981, 16602, 19232, 3550, 23802, 25032, 1303, 35101, 30723, 29548, 19540, 27721, 3362, 989, 24341, 1460, 28991, 12943, 28993, 1347, 31781, 2848, 23367, 29496, 13433, 1318, 8679, 4200, 4217, 18672, 18018, 23604, 11056, 21485, 16631, 26352, 5101, 5151, 2832, 16528, 4553, 19182, 5611, 483, 29688, 18427, 7854, 21906, 5049, 24357, 167, 3614, 12794, 25976, 12384, 29499, 2805, 32641, 32334, 16015, 1307, 10667, 19538, 35131, 3495, 32639, 8161, 12942, 27142, 8681, 3413, 30730, 27063, 29203, 11057, 19197, 3133, 32413, 4226, 20278, 3400, 14637, 15351, 18754, 5514, 152, 29702, 15006, 5160, 31776, 5175, 15350, 789, 5815, 28723, 11278, 3334, 3366, 1261, 3081, 2670, 1302, 12957, 26600, 19053, 843, 1325, 5565, 25195, 21183, 27267, 28691, 8361, 3342, 27134, 829, 19539, 384, 1299, 222, 945, 29703, 12096, 3562, 4981, 836, 981, 3490, 22491, 9636, 2383, 227, 5753, 19857, 226, 2626, 12785, 3023, 6777, 26596, 2118, 20510, 17553, 16376, 16638, 24396, 29291, 980, 3685, 15165, 1311, 19015, 10118, 13420, 19321, 16264, 23521, 844, 8158, 2838, 1304, 28726, 956, 25178, 8176, 11555, 6740, 258, 793, 1237, 74, 23748, 4730, 791, 3351, 4577, 28725, 24188, 5178, 984, 982, 31557, 16442, 28994, 15293, 17222, 11038, 2672, 15197, 958, 20092, 28727, 1328, 16268, 19678, 3358, 4575, 29538, 9501, 372, 19342, 32354, 15471, 12784, 1313, 7955, 959, 27144, 4265, 4225, 19773, 4221, 17584, 26898, 896, 8404, 15400, 25196, 2481, 3364, 4165, 2687, 1213, 29905, 18907, 5111, 6929, 15291, 29510, 3135, 28716, 29908, 16224, 30438, 21905, 18266, 2482, 26945, 1321, 27138, 32355, 27030, 19536, 1298, 14437, 23437, 14740, 30735, 12792, 5848, 32412, 2380, 31804, 12799, 27195, 3488, 1146, 12956, 5173, 9087, 4602, 5128, 21112, 32477, 1669, 17101, 1250, 1314, 27935, 14337, 10216, 29962, 6741, 8150, 1305, 4590, 1287, 33019, 4878, 17930, 13018, 23159, 1308, 3955, 23208, 27711, 14522, 27146, 15011, 26599, 27031, 3481, 1291, 20986, 16708, 28728, 11188, 3369, 3493, 960, 1289, 23484, 19879, 11116, 1471, 12941, 4083, 1454, 3536, 3015, 4173, 8157, 16829, 12024, 32642, 27052, 18954, 16191, 20808, 16649, 1149, 4228, 25278, 16611, 3537, 28989, 29512, 1294, 24054, 27071, 5163, 27148, 16709, 16722, 3168, 4184, 3018, 23731, 17630, 6807, 8403, 23428, 6574, 3359, 8178, 4085, 24468, 7852, 11536, 23145, 7945, 10367, 27019, 2622, 1690, 5158, 29907, 7952, 2135, 4604, 7683, 4610, 14480, 19932, 1312, 25274, 11183, 24033, 23263, 26936, 2697, 3578, 20494, 12019, 29288, 26934, 18898, 4585, 3367, 12097, 3085, 29014, 4885, 16444, 2265, 16766, 3410, 19574, 16641, 19011, 26868, 1645, 27489, 22225, 20807, 1407, 3935, 2819, 16636, 3409, 23896, 1316, 16705, 3350, 20616, 228, 21488, 5110, 21084, 27817, 16553, 18906, 4894, 6374, 12021, 3577, 2668, 3180, 29277, 30434, 6300, 4170, 5100, 4556, 8508, 3962, 6731, 1247, 33018, 4892, 12023, 28046, 3134, 3958, 4558, 5758, 27140, 3658, 12959, 27186, 3551, 19718, 16678, 29122, 18017, 27055, 32478, 32416, 3178, 18019, 15864, 16612, 6568, 18542, 26569, 28707, 27667, 28796, 24333, 18267, 20081, 16367, 1351, 16739, 29922, 54, 29205, 4220, 19371, 2397, 26968, 15292, 23862, 21110, 2682, 32638, 3316, 28760, 3956, 2264, 7733, 6747, 19495, 2388, 7736, 6730, 5512, 3322, 19474, 3937, 1691, 27185, 27053, 28812, 27478, 19330, 19047, 26707, 1694, 11874, 19836, 2134, 8878, 12026, 4241, 12029, 2364, 1323, 3539, 19450, 16677, 19473, 8177, 14581, 14371, 30439, 1326, 5189, 4259, 27938, 19013, 19245, 3534, 2679, 8117, 16443, 18664, 26474, 27137, 27149, 8131, 6576, 31024, 12777, 12782, 20378, 20249, 7940, 24148, 19533, 19534, 27950, 24510, 4891, 23064, 4555, 19518, 4223, 6567, 12958, 4256, 23511, 24408, 5112, 16748, 26908, 18564, 2352, 5688, 6790, 6791, 3610, 19195, 13435, 30241, 17489, 19560, 13434, 24975, 32421, 19020, 30724, 3533, 3076, 4183, 2814, 16767, 8160, 30572, 19479, 16632, 18810, 16263, 16718, 18009, 3528, 3532, 27181, 491, 31115, 7879, 2699, 2684, 2688, 27057, 28871, 15199, 14737, 5520, 23606, 7976, 4562, 24342, 5169, 4899, 15176, 2842, 22099, 20082, 26568, 16664, 25248, 3952, 23244, 8359, 18581, 28807, 2816, 20463, 18255, 2113, 10856, 23522, 16713, 4893, 5620, 3097, 7978, 5570, 3096, 28827, 4182, 4266, 16683, 26398, 2137, 4587, 16670, 2845, 3091, 3298, 4600, 2698, 5820, 4232, 1692, 16716, 19561, 2839, 2844, 30731, 18905, 1464, 6930, 28682, 3491, 25245, 2483, 15012, 2401, 1697, 3589, 3588, 4231, 5748, 8305, 5411, 5870, 8362, 29511, 19520, 27147, 27143, 1297, 5129, 19239, 18010, 2394, 4888, 28791, 16620, 2357, -- Battlemaster and Arenamaster - 12197, 29318, 15006, 26007, 857, 907, 35007, 19859, 3890, 7029, 35023, 15008, 34999, 15972, 34955, 7885, 34991, 19905, 14981, 14982, 19907, 347, 7427, 7410, 20271, 19855, 29568, 19858, 2302, 14942, 17506, 15007, 34983, 5238, 29234, 32332, 1037, 10360, 2804, 30578, 20388, 30171, 5118, 18439, 32333, 20120, 19908, 30581, 20118, 14879, 16711, 20381, 35024, 22516, 25991, 20200, 7314, 20269, 34895, 35027, 30583, 18895, 20272, 30584, 35017, 19811, 20386, 34971, 20273, 34972, 19915, 20274, 30587, 20390, 19923, 20497, 34976, 12198, 19925, 16695, 20362, 35022, 20499, 14623, 16696, 20374, 21235, 19909, 40413, 20382, 32330, 20119, 30579, 35000, 34985, 30580, 35001, 35025, 35002, 17507, 20383, 34437, 35026, 20384, 19910, 35008, 20385, 19912, 29533, 30586, 35019, 34993, 35020, 16694, 30231, 19906, 34986, 34987, 19911, 34989, 30590, 35021, 30610, 30582, 34988, 20276, 34978, 34973, 34997, 34998 + 12197, 29318, 15006, 26007, 857, 907, 35007, 19859, 3890, 7029, 35023, 15008, 34999, 15972, 34955, 7885, 34991, 19905, 14981, 14982, 19907, 347, 7427, 7410, 20271, 19855, 29568, 19858, 2302, 14942, 17506, 15007, 34983, 5238, 29234, 32332, 1037, 10360, 2804, 30578, 20388, 30171, 5118, 18439, 32333, 20120, 19908, 30581, 20118, 14879, 16711, 20381, 35024, 22516, 25991, 20200, 7314, 20269, 34895, 35027, 30583, 18895, 20272, 30584, 35017, 19811, 20386, 34971, 20273, 34972, 19915, 20274, 30587, 20390, 19923, 20497, 34976, 12198, 19925, 16695, 20362, 35022, 20499, 14623, 16696, 20374, 21235, 19909, 40413, 20382, 32330, 20119, 30579, 35000, 34985, 30580, 35001, 35025, 35002, 17507, 20383, 34437, 35026, 20384, 19910, 35008, 20385, 19912, 29533, 30586, 35019, 34993, 35020, 16694, 30231, 19906, 34986, 34987, 19911, 34989, 30590, 35021, 30610, 30582, 34988, 20276, 34978, 34973, 34997, 34998, + + -- Quests + 10668 } + + + -- Event handler - gossipFrame:SetScript("OnEvent", function() + gossipFrame:SetScript("OnEvent", function(self, event, ...) + if event == "GOSSIP_SHOW" then -- Special treatment for specific NPCs local npcGuid = UnitGUID("target") or nil if npcGuid and not IsShiftKeyDown() then - local void, void, void, void, void, npcID = strsplit("-", npcGuid) + local npcID = LibCompat.GetUnitCreatureId("target") + -- print(npcID) if npcID then -- Open rogue doors in Dalaran (Broken Isles) automatically if npcID == "96782" -- Lucian Trias @@ -1587,7 +1609,12 @@ end -- Process gossip SkipGossip() - end) + + elseif event == "GOSSIP_CLOSED" then + -- Reset Message flag when gossip window is closed + ResetMessageFlag() + end + end) end diff --git a/Leatrix_Plus_Library.lua b/Leatrix_Plus_Library.lua index e867eba..3d2671a 100644 --- a/Leatrix_Plus_Library.lua +++ b/Leatrix_Plus_Library.lua @@ -1,1677 +1,1677 @@ --- L00: Leatrix Plus Library ----------------------------------------------------------------------- +-- -- L00: Leatrix Plus Library +-- ---------------------------------------------------------------------- --- LibDBIcon 10.0.1: --- 11: LibStub: (?s)-- LibStubStart\R?\K.*?(?=-- LibStubEnd) --- 12: LibCallbackHandler: (?s)-- CallbackStart\R?\K.*?(?=-- CallbackEnd) --- 13: LibDataBroker: (?s)-- DataBrokerStart\R?\K.*?(?=-- DataBrokerEnd) --- 14: LibDBIcon: (?s)-- LibDBIconStart\R?\K.*?(?=-- LibDBIconEnd) +-- -- LibDBIcon 10.0.1: +-- -- 11: LibStub: (?s)-- LibStubStart\R?\K.*?(?=-- LibStubEnd) +-- -- 12: LibCallbackHandler: (?s)-- CallbackStart\R?\K.*?(?=-- CallbackEnd) +-- -- 13: LibDataBroker: (?s)-- DataBrokerStart\R?\K.*?(?=-- DataBrokerEnd) +-- -- 14: LibDBIcon: (?s)-- LibDBIconStart\R?\K.*?(?=-- LibDBIconEnd) --- LibChatAnims 10.0.1: --- 15: LibChatAnims: (?s)-- LibChatAnimsStart\R?\K.*?(?=-- LibChatAnimsEnd) +-- -- LibChatAnims 10.0.1: +-- -- 15: LibChatAnims: (?s)-- LibChatAnimsStart\R?\K.*?(?=-- LibChatAnimsEnd) --- LibCandyBar 10.0.1: --- 16: LibCandyBar: (?s)-- LibCandyBarStart\R?\K.*?(?=-- LibCandyBarEnd) +-- -- LibCandyBar 10.0.1: +-- -- 16: LibCandyBar: (?s)-- LibCandyBarStart\R?\K.*?(?=-- LibCandyBarEnd) -local void, Leatrix_Plus = ... +-- local void, Leatrix_Plus = ... ----------------------------------------------------------------------- --- L11: LibDBIcon: LibStub ----------------------------------------------------------------------- +-- ---------------------------------------------------------------------- +-- -- L11: LibDBIcon: LibStub +-- ---------------------------------------------------------------------- -local function LeaLibStub() +-- local function LeaLibStub() --- LibStubStart --- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $ --- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info --- LibStub is hereby placed in the Public Domain --- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke -local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! -local LibStub = _G[LIBSTUB_MAJOR] +-- -- LibStubStart +-- -- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $ +-- -- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info +-- -- LibStub is hereby placed in the Public Domain +-- -- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke +-- local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! +-- local LibStub = _G[LIBSTUB_MAJOR] --- Check to see is this version of the stub is obsolete -if not LibStub or LibStub.minor < LIBSTUB_MINOR then - LibStub = LibStub or {libs = {}, minors = {} } - _G[LIBSTUB_MAJOR] = LibStub - LibStub.minor = LIBSTUB_MINOR +-- -- Check to see is this version of the stub is obsolete +-- if not LibStub or LibStub.minor < LIBSTUB_MINOR then +-- LibStub = LibStub or {libs = {}, minors = {} } +-- _G[LIBSTUB_MAJOR] = LibStub +-- LibStub.minor = LIBSTUB_MINOR - -- LibStub:NewLibrary(major, minor) - -- major (string) - the major version of the library - -- minor (string or number ) - the minor version of the library - -- - -- returns nil if a newer or same version of the lib is already present - -- returns empty library object or old library object if upgrade is needed - function LibStub:NewLibrary(major, minor) - assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") - minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") +-- -- LibStub:NewLibrary(major, minor) +-- -- major (string) - the major version of the library +-- -- minor (string or number ) - the minor version of the library +-- -- +-- -- returns nil if a newer or same version of the lib is already present +-- -- returns empty library object or old library object if upgrade is needed +-- function LibStub:NewLibrary(major, minor) +-- assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") +-- minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") - local oldminor = self.minors[major] - if oldminor and oldminor >= minor then return nil end - self.minors[major], self.libs[major] = minor, self.libs[major] or {} - return self.libs[major], oldminor - end +-- local oldminor = self.minors[major] +-- if oldminor and oldminor >= minor then return nil end +-- self.minors[major], self.libs[major] = minor, self.libs[major] or {} +-- return self.libs[major], oldminor +-- end - -- LibStub:GetLibrary(major, [silent]) - -- major (string) - the major version of the library - -- silent (boolean) - if true, library is optional, silently return nil if its not found - -- - -- throws an error if the library can not be found (except silent is set) - -- returns the library object if found - function LibStub:GetLibrary(major, silent) - if not self.libs[major] and not silent then - error(("Cannot find a library instance of %q."):format(tostring(major)), 2) - end - return self.libs[major], self.minors[major] - end +-- -- LibStub:GetLibrary(major, [silent]) +-- -- major (string) - the major version of the library +-- -- silent (boolean) - if true, library is optional, silently return nil if its not found +-- -- +-- -- throws an error if the library can not be found (except silent is set) +-- -- returns the library object if found +-- function LibStub:GetLibrary(major, silent) +-- if not self.libs[major] and not silent then +-- error(("Cannot find a library instance of %q."):format(tostring(major)), 2) +-- end +-- return self.libs[major], self.minors[major] +-- end - -- LibStub:IterateLibraries() - -- - -- Returns an iterator for the currently registered libraries - function LibStub:IterateLibraries() - return pairs(self.libs) - end +-- -- LibStub:IterateLibraries() +-- -- +-- -- Returns an iterator for the currently registered libraries +-- function LibStub:IterateLibraries() +-- return pairs(self.libs) +-- end - setmetatable(LibStub, { __call = LibStub.GetLibrary }) -end --- LibStubEnd - -end -LeaLibStub() - ----------------------------------------------------------------------- --- L12: LibDBIcon: CallbackHandler ----------------------------------------------------------------------- - -local function LeaCallbackHandler() - --- CallbackStart ---[[ $Id: CallbackHandler-1.0.lua 26 2022-12-12 15:09:39Z nevcairiel $ ]] -local MAJOR, MINOR = "CallbackHandler-1.0", 8 -local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR) - -if not CallbackHandler then return end -- No upgrade needed - -local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end} - --- Lua APIs -local securecallfunction, error = securecallfunction, error -local setmetatable, rawget = setmetatable, rawget -local next, select, pairs, type, tostring = next, select, pairs, type, tostring - - -local function Dispatch(handlers, ...) - local index, method = next(handlers) - if not method then return end - repeat - securecallfunction(method, ...) - index, method = next(handlers, index) - until not method -end - --------------------------------------------------------------------------- --- CallbackHandler:New --- --- target - target object to embed public APIs in --- RegisterName - name of the callback registration API, default "RegisterCallback" --- UnregisterName - name of the callback unregistration API, default "UnregisterCallback" --- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API. - -function CallbackHandler.New(_self, target, RegisterName, UnregisterName, UnregisterAllName) - - RegisterName = RegisterName or "RegisterCallback" - UnregisterName = UnregisterName or "UnregisterCallback" - if UnregisterAllName==nil then -- false is used to indicate "don't want this method" - UnregisterAllName = "UnregisterAllCallbacks" - end - - -- we declare all objects and exported APIs inside this closure to quickly gain access - -- to e.g. function names, the "target" parameter, etc - - - -- Create the registry object - local events = setmetatable({}, meta) - local registry = { recurse=0, events=events } - - -- registry:Fire() - fires the given event/message into the registry - function registry:Fire(eventname, ...) - if not rawget(events, eventname) or not next(events[eventname]) then return end - local oldrecurse = registry.recurse - registry.recurse = oldrecurse + 1 - - Dispatch(events[eventname], eventname, ...) - - registry.recurse = oldrecurse - - if registry.insertQueue and oldrecurse==0 then - -- Something in one of our callbacks wanted to register more callbacks; they got queued - for event,callbacks in pairs(registry.insertQueue) do - local first = not rawget(events, event) or not next(events[event]) -- test for empty before. not test for one member after. that one member may have been overwritten. - for object,func in pairs(callbacks) do - events[event][object] = func - -- fire OnUsed callback? - if first and registry.OnUsed then - registry.OnUsed(registry, target, event) - first = nil - end - end - end - registry.insertQueue = nil - end - end - - -- Registration of a callback, handles: - -- self["method"], leads to self["method"](self, ...) - -- self with function ref, leads to functionref(...) - -- "addonId" (instead of self) with function ref, leads to functionref(...) - -- all with an optional arg, which, if present, gets passed as first argument (after self if present) - target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]]) - if type(eventname) ~= "string" then - error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2) - end - - method = method or eventname - - local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten. - - if type(method) ~= "string" and type(method) ~= "function" then - error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2) - end - - local regfunc - - if type(method) == "string" then - -- self["method"] calling style - if type(self) ~= "table" then - error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2) - elseif self==target then - error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2) - elseif type(self[method]) ~= "function" then - error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2) - end - - if select("#",...)>=1 then -- this is not the same as testing for arg==nil! - local arg=select(1,...) - regfunc = function(...) self[method](self,arg,...) end - else - regfunc = function(...) self[method](self,...) end - end - else - -- function ref with self=object or self="addonId" or self=thread - if type(self)~="table" and type(self)~="string" and type(self)~="thread" then - error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2) - end - - if select("#",...)>=1 then -- this is not the same as testing for arg==nil! - local arg=select(1,...) - regfunc = function(...) method(arg,...) end - else - regfunc = method - end - end - - - if events[eventname][self] or registry.recurse<1 then - -- if registry.recurse<1 then - -- we're overwriting an existing entry, or not currently recursing. just set it. - events[eventname][self] = regfunc - -- fire OnUsed callback? - if registry.OnUsed and first then - registry.OnUsed(registry, target, eventname) - end - else - -- we're currently processing a callback in this registry, so delay the registration of this new entry! - -- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency - registry.insertQueue = registry.insertQueue or setmetatable({},meta) - registry.insertQueue[eventname][self] = regfunc - end - end - - -- Unregister a callback - target[UnregisterName] = function(self, eventname) - if not self or self==target then - error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2) - end - if type(eventname) ~= "string" then - error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2) - end - if rawget(events, eventname) and events[eventname][self] then - events[eventname][self] = nil - -- Fire OnUnused callback? - if registry.OnUnused and not next(events[eventname]) then - registry.OnUnused(registry, target, eventname) - end - end - if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then - registry.insertQueue[eventname][self] = nil - end - end - - -- OPTIONAL: Unregister all callbacks for given selfs/addonIds - if UnregisterAllName then - target[UnregisterAllName] = function(...) - if select("#",...)<1 then - error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2) - end - if select("#",...)==1 and ...==target then - error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2) - end - - - for i=1,select("#",...) do - local self = select(i,...) - if registry.insertQueue then - for eventname, callbacks in pairs(registry.insertQueue) do - if callbacks[self] then - callbacks[self] = nil - end - end - end - for eventname, callbacks in pairs(events) do - if callbacks[self] then - callbacks[self] = nil - -- Fire OnUnused callback? - if registry.OnUnused and not next(callbacks) then - registry.OnUnused(registry, target, eventname) - end - end - end - end - end - end - - return registry -end - - --- CallbackHandler purposefully does NOT do explicit embedding. Nor does it --- try to upgrade old implicit embeds since the system is selfcontained and --- relies on closures to work. - --- CallbackEnd -end - -LeaCallbackHandler() - ----------------------------------------------------------------------- --- L13: LibDBIcon: LibDataBroker ----------------------------------------------------------------------- - -local function LeaDataBroker() - --- DataBrokerStart - -assert(LibStub, "LibDataBroker-1.1 requires LibStub") -assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0") - -local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4) -if not lib then return end -oldminor = oldminor or 0 - - -lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib) -lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {} -local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks - -if oldminor < 2 then - lib.domt = { - __metatable = "access denied", - __index = function(self, key) return attributestorage[self] and attributestorage[self][key] end, - } -end - -if oldminor < 3 then - lib.domt.__newindex = function(self, key, value) - if not attributestorage[self] then attributestorage[self] = {} end - if attributestorage[self][key] == value then return end - attributestorage[self][key] = value - local name = namestorage[self] - if not name then return end - callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self) - callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self) - callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self) - callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self) - end -end - -if oldminor < 2 then - function lib:NewDataObject(name, dataobj) - if self.proxystorage[name] then return end - - if dataobj then - assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table") - self.attributestorage[dataobj] = {} - for i,v in pairs(dataobj) do - self.attributestorage[dataobj][i] = v - dataobj[i] = nil - end - end - dataobj = setmetatable(dataobj or {}, self.domt) - self.proxystorage[name], self.namestorage[dataobj] = dataobj, name - self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj) - return dataobj - end -end - -if oldminor < 1 then - function lib:DataObjectIterator() - return pairs(self.proxystorage) - end - - function lib:GetDataObjectByName(dataobjectname) - return self.proxystorage[dataobjectname] - end - - function lib:GetNameByDataObject(dataobject) - return self.namestorage[dataobject] - end -end - -if oldminor < 4 then - local next = pairs(attributestorage) - function lib:pairs(dataobject_or_name) - local t = type(dataobject_or_name) - assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)") - - local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name - assert(attributestorage[dataobj], "Data object not found") - - return next, attributestorage[dataobj], nil - end - - local ipairs_iter = ipairs(attributestorage) - function lib:ipairs(dataobject_or_name) - local t = type(dataobject_or_name) - assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)") - - local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name - assert(attributestorage[dataobj], "Data object not found") - - return ipairs_iter, attributestorage[dataobj], 0 - end -end --- DataBrokerEnd - -end -LeaDataBroker() - ----------------------------------------------------------------------- --- L14: LibDBIcon: LibDBIcon ----------------------------------------------------------------------- - -local function LeaLibDBIcon() - --- LibDBIconStart ---@curseforge-project-slug: libdbicon-1-0@ ------------------------------------------------------------------------ --- LibDBIcon-1.0 --- --- Allows addons to easily create a lightweight minimap icon as an alternative to heavier LDB displays. --- - -local DBICON10 = "LibDBIcon-1.0" -local DBICON10_MINOR = 45 -- Bump on changes -if not LibStub then error(DBICON10 .. " requires LibStub.") end -local ldb = LibStub("LibDataBroker-1.1", true) -if not ldb then error(DBICON10 .. " requires LibDataBroker-1.1.") end -local lib = LibStub:NewLibrary(DBICON10, DBICON10_MINOR) -if not lib then return end - -lib.objects = lib.objects or {} -lib.callbackRegistered = lib.callbackRegistered or nil -lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib) -lib.notCreated = lib.notCreated or {} -lib.radius = lib.radius or 5 -local next, Minimap, CreateFrame = next, Minimap, CreateFrame -lib.tooltip = lib.tooltip or CreateFrame("GameTooltip", "LibDBIconTooltip", UIParent, "GameTooltipTemplate") -local isDraggingButton = false - -function lib:IconCallback(event, name, key, value) - if lib.objects[name] then - if key == "icon" then - lib.objects[name].icon:SetTexture(value) - elseif key == "iconCoords" then - lib.objects[name].icon:UpdateCoord() - elseif key == "iconR" then - local _, g, b = lib.objects[name].icon:GetVertexColor() - lib.objects[name].icon:SetVertexColor(value, g, b) - elseif key == "iconG" then - local r, _, b = lib.objects[name].icon:GetVertexColor() - lib.objects[name].icon:SetVertexColor(r, value, b) - elseif key == "iconB" then - local r, g = lib.objects[name].icon:GetVertexColor() - lib.objects[name].icon:SetVertexColor(r, g, value) - end - end -end -if not lib.callbackRegistered then - ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__icon", "IconCallback") - ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconCoords", "IconCallback") - ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconR", "IconCallback") - ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconG", "IconCallback") - ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconB", "IconCallback") - lib.callbackRegistered = true -end - -local function getAnchors(frame) - local x, y = frame:GetCenter() - if not x or not y then return "CENTER" end - local hhalf = (x > UIParent:GetWidth()*2/3) and "RIGHT" or (x < UIParent:GetWidth()/3) and "LEFT" or "" - local vhalf = (y > UIParent:GetHeight()/2) and "TOP" or "BOTTOM" - return vhalf..hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP")..hhalf -end - -local function onEnter(self) - if isDraggingButton then return end - - for _, button in next, lib.objects do - if button.showOnMouseover then - button.fadeOut:Stop() - button:SetAlpha(1) - end - end - - local obj = self.dataObject - if obj.OnTooltipShow then - lib.tooltip:SetOwner(self, "ANCHOR_NONE") - lib.tooltip:SetPoint(getAnchors(self)) - obj.OnTooltipShow(lib.tooltip) - lib.tooltip:Show() - elseif obj.OnEnter then - obj.OnEnter(self) - end -end - -local function onLeave(self) - lib.tooltip:Hide() - - if not isDraggingButton then - for _, button in next, lib.objects do - if button.showOnMouseover then - button.fadeOut:Play() - end - end - end - - local obj = self.dataObject - if obj.OnLeave then - obj.OnLeave(self) - end -end - --------------------------------------------------------------------------------- - -local onDragStart, updatePosition - -do - local minimapShapes = { - ["ROUND"] = {true, true, true, true}, - ["SQUARE"] = {false, false, false, false}, - ["CORNER-TOPLEFT"] = {false, false, false, true}, - ["CORNER-TOPRIGHT"] = {false, false, true, false}, - ["CORNER-BOTTOMLEFT"] = {false, true, false, false}, - ["CORNER-BOTTOMRIGHT"] = {true, false, false, false}, - ["SIDE-LEFT"] = {false, true, false, true}, - ["SIDE-RIGHT"] = {true, false, true, false}, - ["SIDE-TOP"] = {false, false, true, true}, - ["SIDE-BOTTOM"] = {true, true, false, false}, - ["TRICORNER-TOPLEFT"] = {false, true, true, true}, - ["TRICORNER-TOPRIGHT"] = {true, false, true, true}, - ["TRICORNER-BOTTOMLEFT"] = {true, true, false, true}, - ["TRICORNER-BOTTOMRIGHT"] = {true, true, true, false}, - } - - local rad, cos, sin, sqrt, max, min = math.rad, math.cos, math.sin, math.sqrt, math.max, math.min - function updatePosition(button, position) - local angle = rad(position or 225) - local x, y, q = cos(angle), sin(angle), 1 - if x < 0 then q = q + 1 end - if y > 0 then q = q + 2 end - local minimapShape = GetMinimapShape and GetMinimapShape() or "ROUND" - local quadTable = minimapShapes[minimapShape] - local w = (Minimap:GetWidth() / 2) + lib.radius - local h = (Minimap:GetHeight() / 2) + lib.radius - if quadTable[q] then - x, y = x*w, y*h - else - local diagRadiusW = sqrt(2*(w)^2)-10 - local diagRadiusH = sqrt(2*(h)^2)-10 - x = max(-w, min(x*diagRadiusW, w)) - y = max(-h, min(y*diagRadiusH, h)) - end - button:SetPoint("CENTER", Minimap, "CENTER", x, y) - end -end - -local function onClick(self, b) - if self.dataObject.OnClick then - self.dataObject.OnClick(self, b) - end -end - -local function onMouseDown(self) - self.isMouseDown = true - self.icon:UpdateCoord() -end - -local function onMouseUp(self) - self.isMouseDown = false - self.icon:UpdateCoord() -end - -do - local deg, atan2 = math.deg, math.atan2 - local function onUpdate(self) - local mx, my = Minimap:GetCenter() - local px, py = GetCursorPosition() - local scale = Minimap:GetEffectiveScale() - px, py = px / scale, py / scale - local pos = 225 - if self.db then - pos = deg(atan2(py - my, px - mx)) % 360 - self.db.minimapPos = pos - else - pos = deg(atan2(py - my, px - mx)) % 360 - self.minimapPos = pos - end - updatePosition(self, pos) - end - - function onDragStart(self) - self:LockHighlight() - self.isMouseDown = true - self.icon:UpdateCoord() - self:SetScript("OnUpdate", onUpdate) - isDraggingButton = true - lib.tooltip:Hide() - for _, button in next, lib.objects do - if button.showOnMouseover then - button.fadeOut:Stop() - button:SetAlpha(1) - end - end - end -end - -local function onDragStop(self) - self:SetScript("OnUpdate", nil) - self.isMouseDown = false - self.icon:UpdateCoord() - self:UnlockHighlight() - isDraggingButton = false - for _, button in next, lib.objects do - if button.showOnMouseover then - button.fadeOut:Play() - end - end -end - -local defaultCoords = {0, 1, 0, 1} -local function updateCoord(self) - local coords = self:GetParent().dataObject.iconCoords or defaultCoords - local deltaX, deltaY = 0, 0 - if not self:GetParent().isMouseDown then - deltaX = (coords[2] - coords[1]) * 0.05 - deltaY = (coords[4] - coords[3]) * 0.05 - end - self:SetTexCoord(coords[1] + deltaX, coords[2] - deltaX, coords[3] + deltaY, coords[4] - deltaY) -end - -local function createButton(name, object, db) - local button = CreateFrame("Button", "LibDBIcon10_"..name, Minimap) - button.dataObject = object - button.db = db - button:SetFrameStrata("MEDIUM") - -- button:SetFixedFrameStrata(true) - button:SetFrameLevel(8) - -- button:SetFixedFrameLevel(true) - button:SetSize(31, 31) - button:RegisterForClicks("anyUp") - button:RegisterForDrag("LeftButton") - button:SetHighlightTexture(136477) --"Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight" - if WOW_PROJECT_ID == WOW_PROJECT_MAINLINE then - local overlay = button:CreateTexture(nil, "OVERLAY") - overlay:SetSize(50, 50) - overlay:SetTexture(136430) --"Interface\\Minimap\\MiniMap-TrackingBorder" - overlay:SetPoint("TOPLEFT", button, "TOPLEFT", 0, 0) - local background = button:CreateTexture(nil, "BACKGROUND") - background:SetSize(24, 24) - background:SetTexture(136467) --"Interface\\Minimap\\UI-Minimap-Background" - background:SetPoint("CENTER", button, "CENTER", 0, 1) - local icon = button:CreateTexture(nil, "ARTWORK") - icon:SetSize(18, 18) - icon:SetTexture(object.icon) - icon:SetPoint("CENTER", button, "CENTER", 0, 1) - button.icon = icon - else - local overlay = button:CreateTexture(nil, "OVERLAY") - overlay:SetSize(53, 53) - overlay:SetTexture(136430) --"Interface\\Minimap\\MiniMap-TrackingBorder" - overlay:SetPoint("TOPLEFT") - local background = button:CreateTexture(nil, "BACKGROUND") - background:SetSize(20, 20) - background:SetTexture(136467) --"Interface\\Minimap\\UI-Minimap-Background" - background:SetPoint("TOPLEFT", 7, -5) - local icon = button:CreateTexture(nil, "ARTWORK") - icon:SetSize(17, 17) - icon:SetTexture(object.icon) - icon:SetPoint("TOPLEFT", 7, -6) - button.icon = icon - end - - button.isMouseDown = false - local r, g, b = button.icon:GetVertexColor() - button.icon:SetVertexColor(object.iconR or r, object.iconG or g, object.iconB or b) - - button.icon.UpdateCoord = updateCoord - button.icon:UpdateCoord() - - button:SetScript("OnEnter", onEnter) - button:SetScript("OnLeave", onLeave) - button:SetScript("OnClick", onClick) - if not db or not db.lock then - button:SetScript("OnDragStart", onDragStart) - button:SetScript("OnDragStop", onDragStop) - end - button:SetScript("OnMouseDown", onMouseDown) - button:SetScript("OnMouseUp", onMouseUp) - - button.fadeOut = button:CreateAnimationGroup() - local animOut = button.fadeOut:CreateAnimation("Alpha") - -- animOut:SetOrder(1) - -- animOut:SetDuration(0.2) - -- animOut:SetFromAlpha(1) - -- animOut:SetToAlpha(0) - -- animOut:SetStartDelay(1) - -- button.fadeOut:SetToFinalAlpha(true) - - lib.objects[name] = button - - if lib.loggedIn then - updatePosition(button, db and db.minimapPos) - if not db or not db.hide then - button:Show() - else - button:Hide() - end - end - lib.callbacks:Fire("LibDBIcon_IconCreated", button, name) -- Fire 'Icon Created' callback -end - --- We could use a metatable.__index on lib.objects, but then we'd create --- the icons when checking things like :IsRegistered, which is not necessary. -local function check(name) - if lib.notCreated[name] then - createButton(name, lib.notCreated[name][1], lib.notCreated[name][2]) - lib.notCreated[name] = nil - end -end - --- Wait a bit with the initial positioning to let any GetMinimapShape addons --- load up. -if not lib.loggedIn then - local f = CreateFrame("Frame") - f:SetScript("OnEvent", function(f) - for _, button in next, lib.objects do - updatePosition(button, button.db and button.db.minimapPos) - if not button.db or not button.db.hide then - button:Show() - else - button:Hide() - end - end - lib.loggedIn = true - f:SetScript("OnEvent", nil) - end) - f:RegisterEvent("PLAYER_LOGIN") -end - -local function getDatabase(name) - return lib.notCreated[name] and lib.notCreated[name][2] or lib.objects[name].db -end - -function lib:Register(name, object, db) - if not object.icon then error("Can't register LDB objects without icons set!") end - if lib.objects[name] or lib.notCreated[name] then error(DBICON10.. ": Object '".. name .."' is already registered.") end - if not db or not db.hide then - createButton(name, object, db) - else - lib.notCreated[name] = {object, db} - end -end - -function lib:Lock(name) - if not lib:IsRegistered(name) then return end - if lib.objects[name] then - lib.objects[name]:SetScript("OnDragStart", nil) - lib.objects[name]:SetScript("OnDragStop", nil) - end - local db = getDatabase(name) - if db then - db.lock = true - end -end - -function lib:Unlock(name) - if not lib:IsRegistered(name) then return end - if lib.objects[name] then - lib.objects[name]:SetScript("OnDragStart", onDragStart) - lib.objects[name]:SetScript("OnDragStop", onDragStop) - end - local db = getDatabase(name) - if db then - db.lock = nil - end -end - -function lib:Hide(name) - if not lib.objects[name] then return end - lib.objects[name]:Hide() -end - -function lib:Show(name) - check(name) - local button = lib.objects[name] - if button then - button:Show() - updatePosition(button, button.db and button.db.minimapPos or button.minimapPos) - end -end - -function lib:IsRegistered(name) - return (lib.objects[name] or lib.notCreated[name]) and true or false -end - -function lib:Refresh(name, db) - check(name) - local button = lib.objects[name] - if db then - button.db = db - end - updatePosition(button, button.db and button.db.minimapPos or button.minimapPos) - if not button.db or not button.db.hide then - button:Show() - else - button:Hide() - end - if not button.db or not button.db.lock then - button:SetScript("OnDragStart", onDragStart) - button:SetScript("OnDragStop", onDragStop) - else - button:SetScript("OnDragStart", nil) - button:SetScript("OnDragStop", nil) - end -end - -function lib:GetMinimapButton(name) - return lib.objects[name] -end - -do - local function OnMinimapEnter() - if isDraggingButton then return end - for _, button in next, lib.objects do - if button.showOnMouseover then - button.fadeOut:Stop() - button:SetAlpha(1) - end - end - end - local function OnMinimapLeave() - if isDraggingButton then return end - for _, button in next, lib.objects do - if button.showOnMouseover then - button.fadeOut:Play() - end - end - end - Minimap:HookScript("OnEnter", OnMinimapEnter) - Minimap:HookScript("OnLeave", OnMinimapLeave) - - function lib:ShowOnEnter(name, value) - local button = lib.objects[name] - if button then - if value then - button.showOnMouseover = true - button.fadeOut:Stop() - button:SetAlpha(0) - else - button.showOnMouseover = false - button.fadeOut:Stop() - button:SetAlpha(1) - end - end - end -end - -function lib:GetButtonList() - local t = {} - for name in next, lib.objects do - t[#t+1] = name - end - return t -end - -function lib:SetButtonRadius(radius) - if type(radius) == "number" then - lib.radius = radius - for _, button in next, lib.objects do - updatePosition(button, button.db and button.db.minimapPos or button.minimapPos) - end - end -end - -function lib:SetButtonToPosition(button, position) - updatePosition(lib.objects[button] or button, position) -end - --- Upgrade! -for name, button in next, lib.objects do - local db = getDatabase(name) - if not db or not db.lock then - button:SetScript("OnDragStart", onDragStart) - button:SetScript("OnDragStop", onDragStop) - end - button:SetScript("OnEnter", onEnter) - button:SetScript("OnLeave", onLeave) - button:SetScript("OnClick", onClick) - button:SetScript("OnMouseDown", onMouseDown) - button:SetScript("OnMouseUp", onMouseUp) - - if not button.fadeOut then -- Upgrade to 39 - button.fadeOut = button:CreateAnimationGroup() - local animOut = button.fadeOut:CreateAnimation("Alpha") - animOut:SetOrder(1) - animOut:SetDuration(0.2) - animOut:SetFromAlpha(1) - animOut:SetToAlpha(0) - animOut:SetStartDelay(1) - button.fadeOut:SetToFinalAlpha(true) - end -end -lib:SetButtonRadius(lib.radius) -- Upgrade to 40 --- LibDBIconEnd - -end --- LeaLibDBIcon() -- disabled in 3.3.5, was causing red things - - ----------------------------------------------------------------------- --- L15: LibChatAnims (load on demand) ----------------------------------------------------------------------- - -function Leatrix_Plus:LeaPlusLCA() - --- LibChatAnimsStart ---@curseforge-project-slug: libchatanims@ -local MAJOR, MINOR = "LibChatAnims", 4 -- Bump minor on changes -local LCA = LibStub:NewLibrary(MAJOR, MINOR) -if not LCA then return end -- No upgrade needed - -LCA.animations = LCA.animations or {} -- Animation storage -LCA.alerting = LCA.alerting or {} -- Chat tab alerting storage -local anims = LCA.animations -local alerting = LCA.alerting - -function LCA:IsAlerting(tab) - if alerting[tab] then - return true - end -end - ----------------------------------------------------- --- Note, most of this code is simply replicated from --- Blizzard's FloatingChatFrame.lua file. --- The only real changes are the creation and use --- of animations vs the use of UIFrameFlash. --- - ---FCFDockOverflowButton_UpdatePulseState = function(self) --- local dock = self:GetParent() --- local shouldPulse = false --- for _, chatFrame in pairs(FCFDock_GetChatFrames(dock)) do --- local chatTab = _G[chatFrame:GetName().."Tab"] --- if ( not chatFrame.isStaticDocked and chatTab.alerting) then --- -- Make sure the rects are valid. (Not always the case when resizing the WoW client --- if ( not chatTab:GetRight() or not dock.scrollFrame:GetRight() ) then --- return false --- end --- -- Check if it's off the screen. --- local DELTA = 3 -- Chosen through experimentation --- if ( chatTab:GetRight() < (dock.scrollFrame:GetLeft() + DELTA) or chatTab:GetLeft() > (dock.scrollFrame:GetRight() - DELTA) ) then --- shouldPulse = true --- break --- end --- end --- end --- --- local tex = self:GetHighlightTexture() --- if shouldPulse then --- if not anims[tex] then --- anims[tex] = tex:CreateAnimationGroup() --- --- local fade1 = anims[tex]:CreateAnimation("Alpha") --- fade1:SetDuration(1) --- fade1:SetFromAlpha(0) --- fade1:SetToAlpha(1) --- fade1:SetOrder(1) --- --- local fade2 = anims[tex]:CreateAnimation("Alpha") --- fade2:SetDuration(1) --- fade2:SetFromAlpha(1) --- fade2:SetToAlpha(0) --- fade2:SetOrder(2) --- end --- tex:Show() --- tex:SetAlpha(0) --- anims[tex]:SetLooping("REPEAT") --- anims[tex]:Play() --- --- self:LockHighlight() --- self.alerting = true --- else --- if anims[tex] then --- anims[tex]:Stop() --- end --- self:UnlockHighlight() --- tex:SetAlpha(1) --- tex:Show() --- self.alerting = false --- end --- --- if self.list:IsShown() then --- FCFDockOverflowList_Update(self.list, dock) --- end --- return true ---end - ---FCFDockOverflowListButton_SetValue = function(button, chatFrame) --- local chatTab = _G[chatFrame:GetName().."Tab"] --- button.chatFrame = chatFrame --- button:SetText(chatFrame.name) --- --- local colorTable = chatTab.selectedColorTable or DEFAULT_TAB_SELECTED_COLOR_TABLE --- --- if chatTab.selectedColorTable then --- button:GetFontString():SetTextColor(colorTable.r, colorTable.g, colorTable.b) --- else --- button:GetFontString():SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b) --- end --- --- button.glow:SetVertexColor(colorTable.r, colorTable.g, colorTable.b) --- --- if chatTab.conversationIcon then --- button.conversationIcon:SetVertexColor(colorTable.r, colorTable.g, colorTable.b) --- button.conversationIcon:Show() --- else --- button.conversationIcon:Hide() --- end --- --- if chatTab.alerting then --- button.alerting = true --- if not anims[button.glow] then --- anims[button.glow] = button.glow:CreateAnimationGroup() --- --- local fade1 = anims[button.glow]:CreateAnimation("Alpha") --- fade1:SetDuration(1) --- fade1:SetFromAlpha(0) --- fade1:SetToAlpha(1) --- fade1:SetOrder(1) --- --- local fade2 = anims[button.glow]:CreateAnimation("Alpha") --- fade2:SetDuration(1) --- fade2:SetFromAlpha(1) --- fade2:SetToAlpha(0) --- fade2:SetOrder(2) --- end --- button.glow:Show() --- button.glow:SetAlpha(0) --- anims[button.glow]:SetLooping("REPEAT") --- anims[button.glow]:Play() --- else --- button.alerting = false --- if anims[button.glow] then --- anims[button.glow]:Stop() --- end --- button.glow:Hide() --- end --- button:Show() ---end - -FCF_StartAlertFlash = function(chatFrame) - local chatTab = _G[chatFrame:GetName().."Tab"] - - if chatFrame.minFrame then - if not anims[chatFrame.minFrame] then - anims[chatFrame.minFrame] = chatFrame.minFrame.glow:CreateAnimationGroup() - - local fade1 = anims[chatFrame.minFrame]:CreateAnimation("Alpha") - fade1:SetDuration(1) - fade1:SetFromAlpha(0) - fade1:SetToAlpha(1) - fade1:SetOrder(1) - - local fade2 = anims[chatFrame.minFrame]:CreateAnimation("Alpha") - fade2:SetDuration(1) - fade2:SetFromAlpha(1) - fade2:SetToAlpha(0) - fade2:SetOrder(2) - end - chatFrame.minFrame.glow:Show() - chatFrame.minFrame.glow:SetAlpha(0) - anims[chatFrame.minFrame]:SetLooping("REPEAT") - anims[chatFrame.minFrame]:Play() - --chatFrame.minFrame.alerting = true - alerting[chatFrame.minFrame] = true - end - - if not anims[chatTab.glow] then - anims[chatTab.glow] = chatTab.glow:CreateAnimationGroup() - - local fade1 = anims[chatTab.glow]:CreateAnimation("Alpha") - fade1:SetDuration(1) - fade1:SetFromAlpha(0) - fade1:SetToAlpha(1) - fade1:SetOrder(1) - - local fade2 = anims[chatTab.glow]:CreateAnimation("Alpha") - fade2:SetDuration(1) - fade2:SetFromAlpha(1) - fade2:SetToAlpha(0) - fade2:SetOrder(2) - end - chatTab.glow:Show() - chatTab.glow:SetAlpha(0) - anims[chatTab.glow]:SetLooping("REPEAT") - anims[chatTab.glow]:Play() - --chatTab.alerting = true - alerting[chatTab] = true - - - -- START function FCFTab_UpdateAlpha(chatFrame) - local mouseOverAlpha, noMouseAlpha = 0, 0 - if not chatFrame.isDocked or chatFrame == FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK) then - mouseOverAlpha = 1.0 --CHAT_FRAME_TAB_SELECTED_MOUSEOVER_ALPHA - noMouseAlpha = 0.4 -- CHAT_FRAME_TAB_SELECTED_NOMOUSE_ALPHA - else - mouseOverAlpha = 1.0 -- CHAT_FRAME_TAB_ALERTING_MOUSEOVER_ALPHA - noMouseAlpha = 1.0 -- CHAT_FRAME_TAB_ALERTING_NOMOUSE_ALPHA - end - if chatFrame.hasBeenFaded then - chatTab:SetAlpha(mouseOverAlpha) - else - chatTab:SetAlpha(noMouseAlpha) - end - --END function FCFTab_UpdateAlpha(chatFrame) - - --FCFDockOverflowButton_UpdatePulseState(GENERAL_CHAT_DOCK.overflowButton) -end - -FCF_StopAlertFlash = function(chatFrame) - local chatTab = _G[chatFrame:GetName().."Tab"] - - if chatFrame.minFrame then - if anims[chatFrame.minFrame] then - anims[chatFrame.minFrame]:Stop() - end - chatFrame.minFrame.glow:Hide() - --chatFrame.minFrame.alerting = false - alerting[chatFrame.minFrame] = nil - end - - if anims[chatTab.glow] then - anims[chatTab.glow]:Stop() - end - chatTab.glow:Hide() - --chatTab.alerting = false - alerting[chatTab] = nil - - -- START function FCFTab_UpdateAlpha(chatFrame) - local mouseOverAlpha, noMouseAlpha = 0, 0 - if not chatFrame.isDocked or chatFrame == FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK) then - mouseOverAlpha = 1.0 --CHAT_FRAME_TAB_SELECTED_MOUSEOVER_ALPHA - noMouseAlpha = 0.4 -- CHAT_FRAME_TAB_SELECTED_NOMOUSE_ALPHA - else - mouseOverAlpha = 0.6 --CHAT_FRAME_TAB_NORMAL_MOUSEOVER_ALPHA - noMouseAlpha = 0.2 --CHAT_FRAME_TAB_NORMAL_NOMOUSE_ALPHA - end - if chatFrame.hasBeenFaded then - chatTab:SetAlpha(mouseOverAlpha) - else - chatTab:SetAlpha(noMouseAlpha) - end - --END function FCFTab_UpdateAlpha(chatFrame) - - --FCFDockOverflowButton_UpdatePulseState(GENERAL_CHAT_DOCK.overflowButton) -end - --- LibChatAnimsEnd - -end - ----------------------------------------------------------------------- --- L16: LibDBIcon: LibCandyBar ----------------------------------------------------------------------- - -function Leatrix_Plus:LeaPlusCandyBar() - --- LibCandyBarStart ---@curseforge-project-slug: libcandybar-3-0@ ---- **LibCandyBar-3.0** provides elegant timerbars with icons for use in addons. --- It is based of the original ideas of the CandyBar and CandyBar-2.0 library. --- In contrary to the earlier libraries LibCandyBar-3.0 provides you with a timerbar object with a simple API. --- --- Creating a new timerbar using the ':New' function will return a new timerbar object. This timerbar object inherits all of the barPrototype functions listed here. \\ --- --- @usage --- local candy = LibStub("LibCandyBar-3.0") --- local texture = "Interface\\AddOns\\MyAddOn\\statusbar" --- local mybar = candy:New(texture, 100, 16) --- mybar:SetLabel("Yay!") --- mybar:SetDuration(60) --- mybar:Start() --- @class file --- @name LibCandyBar-3.0 - -local GetTime, floor, next = GetTime, floor, next -local CreateFrame, error, setmetatable, UIParent = CreateFrame, error, setmetatable, UIParent - -if not LibStub then error("LibCandyBar-3.0 requires LibStub.") end -local cbh = LibStub:GetLibrary("CallbackHandler-1.0") -if not cbh then error("LibCandyBar-3.0 requires CallbackHandler-1.0") end -local lib = LibStub:NewLibrary("LibCandyBar-3.0", 100) -- Bump minor on changes -if not lib then return end -lib.callbacks = lib.callbacks or cbh:New(lib) -local cb = lib.callbacks -lib.dummyFrame = lib.dummyFrame or CreateFrame("Frame") -lib.barFrameMT = lib.barFrameMT or {__index = lib.dummyFrame} -lib.barPrototype = lib.barPrototype or setmetatable({}, lib.barFrameMT) -lib.barPrototype_mt = lib.barPrototype_mt or {__index = lib.barPrototype} -lib.barCache = lib.barCache or {} - -local barPrototype = lib.barPrototype -local barPrototype_meta = lib.barPrototype_mt -local barCache = lib.barCache - -local scripts = { - "OnUpdate", "OnDragStart", "OnDragStop", - "OnEnter", "OnLeave", "OnHide", - "OnShow", "OnMouseDown", "OnMouseUp", - "OnMouseWheel", "OnSizeChanged", "OnEvent" -} -local numScripts = #scripts -local GameFontHighlightSmallOutline = GameFontHighlightSmallOutline -local _fontName, _fontSize = GameFontHighlightSmallOutline:GetFont() -local _fontShadowX, _fontShadowY = GameFontHighlightSmallOutline:GetShadowOffset() -local _fontShadowR, _fontShadowG, _fontShadowB, _fontShadowA = GameFontHighlightSmallOutline:GetShadowColor() -local SetWidth, SetHeight, SetSize = lib.dummyFrame.SetWidth, lib.dummyFrame.SetHeight, lib.dummyFrame.SetSize - -local function stopBar(bar) - bar.updater:Stop() - bar.data = nil - bar.funcs = nil - bar.running = nil - bar.paused = nil - bar:Hide() - bar:SetParent(UIParent) -end - -local tformat1 = "%d:%02d:%02d" -local tformat2 = "%d:%02d" -local tformat3 = "%.1f" -local tformat4 = "%.0f" -local function barUpdate(updater) - local bar = updater.parent - local t = GetTime() - if t >= bar.exp then - bar:Stop() - else - local time = bar.exp - t - bar.remaining = time - - bar.candyBarBar:SetValue(bar.fill and (t-bar.start)+bar.gap or time) - - if time > 3599.9 then -- > 1 hour - local h = floor(time/3600) - local m = floor((time - (h*3600))/60) - local s = (time - (m*60)) - (h*3600) - bar.candyBarDuration:SetFormattedText(tformat1, h, m, s) - elseif time > 59.9 then -- 1 minute to 1 hour - local m = floor(time/60) - local s = time - (m*60) - bar.candyBarDuration:SetFormattedText(tformat2, m, s) - elseif time < 10 then -- 0 to 10 seconds - bar.candyBarDuration:SetFormattedText(tformat3, time) - else -- 10 seconds to one minute - bar.candyBarDuration:SetFormattedText(tformat4, time) - end - - if bar.funcs then - for i = 1, #bar.funcs do - bar.funcs[i](bar) - end - end - end -end - -local atformat1 = "~%d:%02d:%02d" -local atformat2 = "~%d:%02d" -local atformat3 = "~%.1f" -local atformat4 = "~%.0f" -local function barUpdateApprox(updater) - local bar = updater.parent - local t = GetTime() - if t >= bar.exp then - bar:Stop() - else - local time = bar.exp - t - bar.remaining = time - - bar.candyBarBar:SetValue(bar.fill and (t-bar.start)+bar.gap or time) - - if time > 3599.9 then -- > 1 hour - local h = floor(time/3600) - local m = floor((time - (h*3600))/60) - local s = (time - (m*60)) - (h*3600) - bar.candyBarDuration:SetFormattedText(atformat1, h, m, s) - elseif time > 59.9 then -- 1 minute to 1 hour - local m = floor(time/60) - local s = time - (m*60) - bar.candyBarDuration:SetFormattedText(atformat2, m, s) - elseif time < 10 then -- 0 to 10 seconds - bar.candyBarDuration:SetFormattedText(atformat3, time) - else -- 10 seconds to one minute - bar.candyBarDuration:SetFormattedText(atformat4, time) - end - - if bar.funcs then - for i = 1, #bar.funcs do - bar.funcs[i](bar) - end - end - end -end - --- ------------------------------------------------------------------------------ --- Bar functions --- - -local function restyleBar(self) - if not self.running then return end - self.candyBarIconFrame:ClearAllPoints() - self.candyBarBar:ClearAllPoints() - -- In the past we used a :GetTexture check here, but as of WoW v5 it randomly returns nil, so use our own trustworthy variable. - if self.candyBarIconFrame.icon then - self.candyBarIconFrame:SetWidth(self.height) - if self.iconPosition == "RIGHT" then - self.candyBarIconFrame:SetPoint("TOPRIGHT", self) - self.candyBarIconFrame:SetPoint("BOTTOMRIGHT", self) - self.candyBarBar:SetPoint("TOPRIGHT", self.candyBarIconFrame, "TOPLEFT") - self.candyBarBar:SetPoint("BOTTOMRIGHT", self.candyBarIconFrame, "BOTTOMLEFT") - self.candyBarBar:SetPoint("TOPLEFT", self) - self.candyBarBar:SetPoint("BOTTOMLEFT", self) - else - self.candyBarIconFrame:SetPoint("TOPLEFT") - self.candyBarIconFrame:SetPoint("BOTTOMLEFT") - self.candyBarBar:SetPoint("TOPLEFT", self.candyBarIconFrame, "TOPRIGHT") - self.candyBarBar:SetPoint("BOTTOMLEFT", self.candyBarIconFrame, "BOTTOMRIGHT") - self.candyBarBar:SetPoint("TOPRIGHT", self) - self.candyBarBar:SetPoint("BOTTOMRIGHT", self) - end - self.candyBarIconFrame:Show() - else - self.candyBarBar:SetPoint("TOPLEFT", self) - self.candyBarBar:SetPoint("BOTTOMRIGHT", self) - self.candyBarIconFrame:Hide() - end - if self.showLabel and self.candyBarLabel.text then - self.candyBarLabel:Show() - else - self.candyBarLabel:Hide() - end - if self.showTime then - self.candyBarDuration:Show() - else - self.candyBarDuration:Hide() - end -end - ---- Set whether the bar should drain (default) or fill up. --- @param fill Boolean true/false -function barPrototype:SetFill(fill) - self.fill = fill -end ---- Adds a function to the timerbar. The function will run every update and will receive the bar as a parameter. --- @param func Function to run every update. --- @usage --- -- The example below will print the time remaining to the chatframe every update. Yes, that's a whole lot of spam --- mybar:AddUpdateFunction( function(bar) print(bar.remaining) end ) -function barPrototype:AddUpdateFunction(func) if not self.funcs then self.funcs = {} end; self.funcs[#self.funcs+1] = func end ---- Sets user data in the timerbar object. --- @param key Key to use for the data storage. --- @param data Data to store. -function barPrototype:Set(key, data) if not self.data then self.data = {} end; self.data[key] = data end ---- Retrieves user data from the timerbar object. --- @param key Key to retrieve -function barPrototype:Get(key) return self.data and self.data[key] end ---- Sets the color of the bar. --- This is basically a wrapper to SetStatusBarColor. --- @paramsig r, g, b, a --- @param r Red component (0-1) --- @param g Green component (0-1) --- @param b Blue component (0-1) --- @param a Alpha (0-1) -function barPrototype:SetColor(...) self.candyBarBar:SetStatusBarColor(...) end ---- Sets the color of the bar label and bar duration text. --- @paramsig r, g, b, a --- @param r Red component (0-1) --- @param g Green component (0-1) --- @param b Blue component (0-1) --- @param a Alpha (0-1) -function barPrototype:SetTextColor(...) - self.candyBarLabel:SetTextColor(...) - self.candyBarDuration:SetTextColor(...) -end ---- Sets the shadow color of the bar label and bar duration text. --- @paramsig r, g, b, a --- @param r Red component (0-1) --- @param g Green component (0-1) --- @param b Blue component (0-1) --- @param a Alpha (0-1) -function barPrototype:SetShadowColor(...) - self.candyBarLabel:SetShadowColor(...) - self.candyBarDuration:SetShadowColor(...) -end ---- Sets the texture of the bar. --- This should only be needed on running bars that get changed on the fly. --- @param texture Path to the bar texture. -function barPrototype:SetTexture(texture) - self.candyBarBar:SetStatusBarTexture(texture) - self.candyBarBackground:SetTexture(texture) -end ---- Sets the width of the bar. --- This should only be needed on running bars that get changed on the fly. --- @param width Width of the bar. -function barPrototype:SetWidth(width) - self.width = width - SetWidth(self, width) -end ---- Sets the height of the bar. --- This should only be needed on running bars that get changed on the fly. --- @param height Height of the bar. -function barPrototype:SetHeight(height) - self.height = height - SetHeight(self, height) - restyleBar(self) -end ---- Sets the size of the bar. --- This should only be needed on running bars that get changed on the fly. --- @param width Width of the bar. --- @param height Height of the bar. -function barPrototype:SetSize(width, height) - self.width = width - self.height = height - SetSize(self, width, height) - restyleBar(self) -end ---- Returns the label (text) currently set on the bar. -function barPrototype:GetLabel() - return self.candyBarLabel.text -end ---- Sets the label on the bar. --- @param text Label text. -function barPrototype:SetLabel(text) - self.candyBarLabel.text = text - self.candyBarLabel:SetText(text) - if text then - self.candyBarLabel:Show() - else - self.candyBarLabel:Hide() - end -end ---- Returns the icon texture path currently set on the bar, if it has an icon set. -function barPrototype:GetIcon() - return self.candyBarIconFrame.icon -end ---- Sets the icon next to the bar. --- @param icon Path to the icon texture or nil to not display an icon. --- @param ... Optional icon coordinates for texture trimming. -function barPrototype:SetIcon(icon, ...) - self.candyBarIconFrame.icon = icon - self.candyBarIconFrame:SetTexture(icon) - if ... then - self.candyBarIconFrame:SetTexCoord(...) - else - self.candyBarIconFrame:SetTexCoord(0.07, 0.93, 0.07, 0.93) - end - restyleBar(self) -end ---- Sets which side of the bar the icon should appear. --- @param position Position of the icon according to the bar, either "LEFT" or "RIGHT" as a string. Set to "LEFT" by default. -function barPrototype:SetIconPosition(position) - self.iconPosition = position - restyleBar(self) -end ---- Sets wether or not the time indicator on the right of the bar should be shown. --- Time is shown by default. --- @param bool true to show the time, false/nil to hide the time. -function barPrototype:SetTimeVisibility(bool) - self.showTime = bool - if bool then - self.candyBarDuration:Show() - else - self.candyBarDuration:Hide() - end -end ---- Sets wether or not the label on the left of the bar should be shown. --- label is shown by default. --- @param bool true to show the label, false/nil to hide the label. -function barPrototype:SetLabelVisibility(bool) - self.showLabel = bool - if bool then - self.candyBarLabel:Show() - else - self.candyBarLabel:Hide() - end -end ---- Sets the duration of the bar. --- This can also be used while the bar is running to adjust the time remaining, within the bounds of the original duration. --- @param duration Duration of the bar in seconds. --- @param isApprox Boolean. True if you wish the time display to be an approximate "~5" instead of "5" -function barPrototype:SetDuration(duration, isApprox) self.remaining = duration; self.isApproximate = isApprox end ---- Shows the bar and starts it. --- @param maxValue Number. If you don't wish your bar to start full, you can set a max value. A maxValue of 10 on a bar with a duration of 5 would start it at 50%. -function barPrototype:Start(maxValue) - self.running = true - local time = self.remaining - self.gap = maxValue and maxValue-time or 0 - restyleBar(self) - self.start = GetTime() - self.exp = self.start + time - - self.candyBarBar:SetMinMaxValues(0, maxValue or time) - self.candyBarBar:SetValue(self.fill and 0 or time) - - if self.isApproximate then - if time > 3599.9 then -- > 1 hour - local h = floor(time/3600) - local m = floor((time - (h*3600))/60) - local s = (time - (m*60)) - (h*3600) - self.candyBarDuration:SetFormattedText(atformat1, h, m, s) - elseif time > 59.9 then -- 1 minute to 1 hour - local m = floor(time/60) - local s = time - (m*60) - self.candyBarDuration:SetFormattedText(atformat2, m, s) - elseif time < 10 then -- 0 to 10 seconds - self.candyBarDuration:SetFormattedText(atformat3, time) - else -- 10 seconds to one minute - self.candyBarDuration:SetFormattedText(atformat4, time) - end - self.updater:SetScript("OnLoop", barUpdateApprox) - else - if time > 3599.9 then -- > 1 hour - local h = floor(time/3600) - local m = floor((time - (h*3600))/60) - local s = (time - (m*60)) - (h*3600) - self.candyBarDuration:SetFormattedText(tformat1, h, m, s) - elseif time > 59.9 then -- 1 minute to 1 hour - local m = floor(time/60) - local s = time - (m*60) - self.candyBarDuration:SetFormattedText(tformat2, m, s) - elseif time < 10 then -- 0 to 10 seconds - self.candyBarDuration:SetFormattedText(tformat3, time) - else -- 10 seconds to one minute - self.candyBarDuration:SetFormattedText(tformat4, time) - end - self.updater:SetScript("OnLoop", barUpdate) - end - self.updater:Play() - self:Show() -end ---- Pauses a running bar -function barPrototype:Pause() - if not self.paused then - self.updater:Pause() - self.paused = GetTime() - end -end ---- Resumes a paused bar -function barPrototype:Resume() - if self.paused then - local t = GetTime() - self.exp = t + self.remaining - self.start = self.start + (t-self.paused) - self.updater:Play() - self.paused = nil - end -end ---- Stops the bar. --- This will stop the bar, fire the LibCandyBar_Stop callback, and recycle the bar into the candybar pool. --- Note: make sure you remove all references to the bar in your addon upon receiving the LibCandyBar_Stop callback. --- @usage --- -- The example below shows the use of the LibCandyBar_Stop callback by printing the contents of the label in the chatframe --- local function barstopped( callback, bar ) --- print( bar:GetLabel(), "stopped") +-- setmetatable(LibStub, { __call = LibStub.GetLibrary }) -- end --- LibStub("LibCandyBar-3.0"):RegisterCallback(myaddonobject, "LibCandyBar_Stop", barstopped) --- @param ... Optional args to pass across in the LibCandyBar_Stop callback. -function barPrototype:Stop(...) - cb:Fire("LibCandyBar_Stop", self, ...) - stopBar(self) - barCache[self] = true -end +-- -- LibStubEnd --- ------------------------------------------------------------------------------ --- Library functions --- +-- end +-- LeaLibStub() ---- Creates a new timerbar object and returns it. Don't forget to set the duration, label and :Start the timer bar after you get a hold of it! --- @paramsig texture, width, height --- @param texture Path to the texture used for the bar. --- @param width Width of the bar. --- @param height Height of the bar. --- @usage --- mybar = LibStub("LibCandyBar-3.0"):New("Interface\\AddOns\\MyAddOn\\media\\statusbar", 100, 16) -function lib:New(texture, width, height) - local bar = next(barCache) - if not bar then - local frame = CreateFrame("Frame", nil, UIParent) - bar = setmetatable(frame, barPrototype_meta) +-- ---------------------------------------------------------------------- +-- -- L12: LibDBIcon: CallbackHandler +-- ---------------------------------------------------------------------- - local icon = bar:CreateTexture() - icon:SetPoint("TOPLEFT") - icon:SetPoint("BOTTOMLEFT") - icon:Show() - bar.candyBarIconFrame = icon +-- local function LeaCallbackHandler() - local statusbar = CreateFrame("StatusBar", nil, bar) - statusbar:SetPoint("TOPRIGHT") - statusbar:SetPoint("BOTTOMRIGHT") - bar.candyBarBar = statusbar +-- -- CallbackStart +-- --[[ $Id: CallbackHandler-1.0.lua 26 2022-12-12 15:09:39Z nevcairiel $ ]] +-- local MAJOR, MINOR = "CallbackHandler-1.0", 8 +-- local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR) - local bg = statusbar:CreateTexture(nil, "BACKGROUND") - bg:SetAllPoints() - bar.candyBarBackground = bg +-- if not CallbackHandler then return end -- No upgrade needed - local backdrop = CreateFrame("Frame", nil, bar, "BackdropTemplate") -- Used by bar stylers for backdrops - backdrop:SetFrameLevel(0) - bar.candyBarBackdrop = backdrop +-- local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end} - local iconBackdrop = CreateFrame("Frame", nil, bar, "BackdropTemplate") -- Used by bar stylers for backdrops - iconBackdrop:SetFrameLevel(0) - bar.candyBarIconFrameBackdrop = iconBackdrop - - local duration = statusbar:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmallOutline") - duration:SetPoint("TOPLEFT", statusbar, "TOPLEFT", 2, 0) - duration:SetPoint("BOTTOMRIGHT", statusbar, "BOTTOMRIGHT", -2, 0) - bar.candyBarDuration = duration - - local label = statusbar:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmallOutline") - label:SetPoint("TOPLEFT", statusbar, "TOPLEFT", 2, 0) - label:SetPoint("BOTTOMRIGHT", statusbar, "BOTTOMRIGHT", -2, 0) - bar.candyBarLabel = label - - local updater = bar:CreateAnimationGroup() - updater:SetLooping("REPEAT") - updater.parent = bar - local anim = updater:CreateAnimation() - anim:SetDuration(0.04) - bar.updater = updater - bar.repeater = anim - else - barCache[bar] = nil - end - - bar:SetFrameStrata("MEDIUM") - bar:SetFrameLevel(100) -- Lots of room to create above or below this level - bar.candyBarBar:SetStatusBarTexture(texture) - bar.candyBarBackground:SetTexture(texture) - bar.width = width - bar.height = height - - -- RESET ALL THE THINGS! - bar.fill = nil - bar.showTime = true - bar.showLabel = true - bar.iconPosition = nil - for i = 1, numScripts do -- Update if scripts table is changed, faster than doing #scripts - bar:SetScript(scripts[i], nil) - end - - bar.candyBarBackground:SetVertexColor(0.5, 0.5, 0.5, 0.3) - bar.candyBarBar:SetStatusBarColor(0.5, 0.5, 0.5, 1) - bar:ClearAllPoints() - SetWidth(bar, width) - SetHeight(bar, height) - bar:SetMovable(1) - bar:SetScale(1) - bar:SetAlpha(1) - bar:SetClampedToScreen(false) - bar:EnableMouse(false) - - bar.candyBarLabel:SetTextColor(1,1,1,1) - bar.candyBarLabel:SetJustifyH("LEFT") - bar.candyBarLabel:SetJustifyV("MIDDLE") - bar.candyBarLabel:SetFont(_fontName, _fontSize) - bar.candyBarLabel:SetShadowOffset(_fontShadowX, _fontShadowY) - bar.candyBarLabel:SetShadowColor(_fontShadowR, _fontShadowG, _fontShadowB, _fontShadowA) - - bar.candyBarDuration:SetTextColor(1,1,1,1) - bar.candyBarDuration:SetJustifyH("RIGHT") - bar.candyBarDuration:SetJustifyV("MIDDLE") - bar.candyBarDuration:SetFont(_fontName, _fontSize) - bar.candyBarDuration:SetShadowOffset(_fontShadowX, _fontShadowY) - bar.candyBarDuration:SetShadowColor(_fontShadowR, _fontShadowG, _fontShadowB, _fontShadowA) +-- -- Lua APIs +-- local securecallfunction, error = securecallfunction, error +-- local setmetatable, rawget = setmetatable, rawget +-- local next, select, pairs, type, tostring = next, select, pairs, type, tostring - bar:SetLabel() - bar:SetIcon() - bar:SetDuration() +-- local function Dispatch(handlers, ...) +-- local index, method = next(handlers) +-- if not method then return end +-- repeat +-- securecallfunction(method, ...) +-- index, method = next(handlers, index) +-- until not method +-- end - return bar -end +-- -------------------------------------------------------------------------- +-- -- CallbackHandler:New +-- -- +-- -- target - target object to embed public APIs in +-- -- RegisterName - name of the callback registration API, default "RegisterCallback" +-- -- UnregisterName - name of the callback unregistration API, default "UnregisterCallback" +-- -- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API. --- LibCandyBarEnd +-- function CallbackHandler.New(_self, target, RegisterName, UnregisterName, UnregisterAllName) -end +-- RegisterName = RegisterName or "RegisterCallback" +-- UnregisterName = UnregisterName or "UnregisterCallback" +-- if UnregisterAllName==nil then -- false is used to indicate "don't want this method" +-- UnregisterAllName = "UnregisterAllCallbacks" +-- end --- L17: End +-- -- we declare all objects and exported APIs inside this closure to quickly gain access +-- -- to e.g. function names, the "target" parameter, etc + + +-- -- Create the registry object +-- local events = setmetatable({}, meta) +-- local registry = { recurse=0, events=events } + +-- -- registry:Fire() - fires the given event/message into the registry +-- function registry:Fire(eventname, ...) +-- if not rawget(events, eventname) or not next(events[eventname]) then return end +-- local oldrecurse = registry.recurse +-- registry.recurse = oldrecurse + 1 + +-- Dispatch(events[eventname], eventname, ...) + +-- registry.recurse = oldrecurse + +-- if registry.insertQueue and oldrecurse==0 then +-- -- Something in one of our callbacks wanted to register more callbacks; they got queued +-- for event,callbacks in pairs(registry.insertQueue) do +-- local first = not rawget(events, event) or not next(events[event]) -- test for empty before. not test for one member after. that one member may have been overwritten. +-- for object,func in pairs(callbacks) do +-- events[event][object] = func +-- -- fire OnUsed callback? +-- if first and registry.OnUsed then +-- registry.OnUsed(registry, target, event) +-- first = nil +-- end +-- end +-- end +-- registry.insertQueue = nil +-- end +-- end + +-- -- Registration of a callback, handles: +-- -- self["method"], leads to self["method"](self, ...) +-- -- self with function ref, leads to functionref(...) +-- -- "addonId" (instead of self) with function ref, leads to functionref(...) +-- -- all with an optional arg, which, if present, gets passed as first argument (after self if present) +-- target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]]) +-- if type(eventname) ~= "string" then +-- error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2) +-- end + +-- method = method or eventname + +-- local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten. + +-- if type(method) ~= "string" and type(method) ~= "function" then +-- error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2) +-- end + +-- local regfunc + +-- if type(method) == "string" then +-- -- self["method"] calling style +-- if type(self) ~= "table" then +-- error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2) +-- elseif self==target then +-- error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2) +-- elseif type(self[method]) ~= "function" then +-- error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2) +-- end + +-- if select("#",...)>=1 then -- this is not the same as testing for arg==nil! +-- local arg=select(1,...) +-- regfunc = function(...) self[method](self,arg,...) end +-- else +-- regfunc = function(...) self[method](self,...) end +-- end +-- else +-- -- function ref with self=object or self="addonId" or self=thread +-- if type(self)~="table" and type(self)~="string" and type(self)~="thread" then +-- error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2) +-- end + +-- if select("#",...)>=1 then -- this is not the same as testing for arg==nil! +-- local arg=select(1,...) +-- regfunc = function(...) method(arg,...) end +-- else +-- regfunc = method +-- end +-- end + + +-- if events[eventname][self] or registry.recurse<1 then +-- -- if registry.recurse<1 then +-- -- we're overwriting an existing entry, or not currently recursing. just set it. +-- events[eventname][self] = regfunc +-- -- fire OnUsed callback? +-- if registry.OnUsed and first then +-- registry.OnUsed(registry, target, eventname) +-- end +-- else +-- -- we're currently processing a callback in this registry, so delay the registration of this new entry! +-- -- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency +-- registry.insertQueue = registry.insertQueue or setmetatable({},meta) +-- registry.insertQueue[eventname][self] = regfunc +-- end +-- end + +-- -- Unregister a callback +-- target[UnregisterName] = function(self, eventname) +-- if not self or self==target then +-- error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2) +-- end +-- if type(eventname) ~= "string" then +-- error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2) +-- end +-- if rawget(events, eventname) and events[eventname][self] then +-- events[eventname][self] = nil +-- -- Fire OnUnused callback? +-- if registry.OnUnused and not next(events[eventname]) then +-- registry.OnUnused(registry, target, eventname) +-- end +-- end +-- if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then +-- registry.insertQueue[eventname][self] = nil +-- end +-- end + +-- -- OPTIONAL: Unregister all callbacks for given selfs/addonIds +-- if UnregisterAllName then +-- target[UnregisterAllName] = function(...) +-- if select("#",...)<1 then +-- error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2) +-- end +-- if select("#",...)==1 and ...==target then +-- error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2) +-- end + + +-- for i=1,select("#",...) do +-- local self = select(i,...) +-- if registry.insertQueue then +-- for eventname, callbacks in pairs(registry.insertQueue) do +-- if callbacks[self] then +-- callbacks[self] = nil +-- end +-- end +-- end +-- for eventname, callbacks in pairs(events) do +-- if callbacks[self] then +-- callbacks[self] = nil +-- -- Fire OnUnused callback? +-- if registry.OnUnused and not next(callbacks) then +-- registry.OnUnused(registry, target, eventname) +-- end +-- end +-- end +-- end +-- end +-- end + +-- return registry +-- end + + +-- -- CallbackHandler purposefully does NOT do explicit embedding. Nor does it +-- -- try to upgrade old implicit embeds since the system is selfcontained and +-- -- relies on closures to work. + +-- -- CallbackEnd +-- end + +-- LeaCallbackHandler() + +-- ---------------------------------------------------------------------- +-- -- L13: LibDBIcon: LibDataBroker +-- ---------------------------------------------------------------------- + +-- local function LeaDataBroker() + +-- -- DataBrokerStart + +-- assert(LibStub, "LibDataBroker-1.1 requires LibStub") +-- assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0") + +-- local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4) +-- if not lib then return end +-- oldminor = oldminor or 0 + + +-- lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib) +-- lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {} +-- local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks + +-- if oldminor < 2 then +-- lib.domt = { +-- __metatable = "access denied", +-- __index = function(self, key) return attributestorage[self] and attributestorage[self][key] end, +-- } +-- end + +-- if oldminor < 3 then +-- lib.domt.__newindex = function(self, key, value) +-- if not attributestorage[self] then attributestorage[self] = {} end +-- if attributestorage[self][key] == value then return end +-- attributestorage[self][key] = value +-- local name = namestorage[self] +-- if not name then return end +-- callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self) +-- callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self) +-- callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self) +-- callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self) +-- end +-- end + +-- if oldminor < 2 then +-- function lib:NewDataObject(name, dataobj) +-- if self.proxystorage[name] then return end + +-- if dataobj then +-- assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table") +-- self.attributestorage[dataobj] = {} +-- for i,v in pairs(dataobj) do +-- self.attributestorage[dataobj][i] = v +-- dataobj[i] = nil +-- end +-- end +-- dataobj = setmetatable(dataobj or {}, self.domt) +-- self.proxystorage[name], self.namestorage[dataobj] = dataobj, name +-- self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj) +-- return dataobj +-- end +-- end + +-- if oldminor < 1 then +-- function lib:DataObjectIterator() +-- return pairs(self.proxystorage) +-- end + +-- function lib:GetDataObjectByName(dataobjectname) +-- return self.proxystorage[dataobjectname] +-- end + +-- function lib:GetNameByDataObject(dataobject) +-- return self.namestorage[dataobject] +-- end +-- end + +-- if oldminor < 4 then +-- local next = pairs(attributestorage) +-- function lib:pairs(dataobject_or_name) +-- local t = type(dataobject_or_name) +-- assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)") + +-- local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name +-- assert(attributestorage[dataobj], "Data object not found") + +-- return next, attributestorage[dataobj], nil +-- end + +-- local ipairs_iter = ipairs(attributestorage) +-- function lib:ipairs(dataobject_or_name) +-- local t = type(dataobject_or_name) +-- assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)") + +-- local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name +-- assert(attributestorage[dataobj], "Data object not found") + +-- return ipairs_iter, attributestorage[dataobj], 0 +-- end +-- end +-- -- DataBrokerEnd + +-- end +-- LeaDataBroker() + +-- ---------------------------------------------------------------------- +-- -- L14: LibDBIcon: LibDBIcon +-- ---------------------------------------------------------------------- + +-- local function LeaLibDBIcon() + +-- -- LibDBIconStart +-- --@curseforge-project-slug: libdbicon-1-0@ +-- ----------------------------------------------------------------------- +-- -- LibDBIcon-1.0 +-- -- +-- -- Allows addons to easily create a lightweight minimap icon as an alternative to heavier LDB displays. +-- -- + +-- local DBICON10 = "LibDBIcon-1.0" +-- local DBICON10_MINOR = 45 -- Bump on changes +-- if not LibStub then error(DBICON10 .. " requires LibStub.") end +-- local ldb = LibStub("LibDataBroker-1.1", true) +-- if not ldb then error(DBICON10 .. " requires LibDataBroker-1.1.") end +-- local lib = LibStub:NewLibrary(DBICON10, DBICON10_MINOR) +-- if not lib then return end + +-- lib.objects = lib.objects or {} +-- lib.callbackRegistered = lib.callbackRegistered or nil +-- lib.callbacks = lib.callbacks or LibStub("CallbackHandler-1.0"):New(lib) +-- lib.notCreated = lib.notCreated or {} +-- lib.radius = lib.radius or 5 +-- local next, Minimap, CreateFrame = next, Minimap, CreateFrame +-- lib.tooltip = lib.tooltip or CreateFrame("GameTooltip", "LibDBIconTooltip", UIParent, "GameTooltipTemplate") +-- local isDraggingButton = false + +-- function lib:IconCallback(event, name, key, value) +-- if lib.objects[name] then +-- if key == "icon" then +-- lib.objects[name].icon:SetTexture(value) +-- elseif key == "iconCoords" then +-- lib.objects[name].icon:UpdateCoord() +-- elseif key == "iconR" then +-- local _, g, b = lib.objects[name].icon:GetVertexColor() +-- lib.objects[name].icon:SetVertexColor(value, g, b) +-- elseif key == "iconG" then +-- local r, _, b = lib.objects[name].icon:GetVertexColor() +-- lib.objects[name].icon:SetVertexColor(r, value, b) +-- elseif key == "iconB" then +-- local r, g = lib.objects[name].icon:GetVertexColor() +-- lib.objects[name].icon:SetVertexColor(r, g, value) +-- end +-- end +-- end +-- if not lib.callbackRegistered then +-- ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__icon", "IconCallback") +-- ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconCoords", "IconCallback") +-- ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconR", "IconCallback") +-- ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconG", "IconCallback") +-- ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__iconB", "IconCallback") +-- lib.callbackRegistered = true +-- end + +-- local function getAnchors(frame) +-- local x, y = frame:GetCenter() +-- if not x or not y then return "CENTER" end +-- local hhalf = (x > UIParent:GetWidth()*2/3) and "RIGHT" or (x < UIParent:GetWidth()/3) and "LEFT" or "" +-- local vhalf = (y > UIParent:GetHeight()/2) and "TOP" or "BOTTOM" +-- return vhalf..hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP")..hhalf +-- end + +-- local function onEnter(self) +-- if isDraggingButton then return end + +-- for _, button in next, lib.objects do +-- if button.showOnMouseover then +-- button.fadeOut:Stop() +-- button:SetAlpha(1) +-- end +-- end + +-- local obj = self.dataObject +-- if obj.OnTooltipShow then +-- lib.tooltip:SetOwner(self, "ANCHOR_NONE") +-- lib.tooltip:SetPoint(getAnchors(self)) +-- obj.OnTooltipShow(lib.tooltip) +-- lib.tooltip:Show() +-- elseif obj.OnEnter then +-- obj.OnEnter(self) +-- end +-- end + +-- local function onLeave(self) +-- lib.tooltip:Hide() + +-- if not isDraggingButton then +-- for _, button in next, lib.objects do +-- if button.showOnMouseover then +-- button.fadeOut:Play() +-- end +-- end +-- end + +-- local obj = self.dataObject +-- if obj.OnLeave then +-- obj.OnLeave(self) +-- end +-- end + +-- -------------------------------------------------------------------------------- + +-- local onDragStart, updatePosition + +-- do +-- local minimapShapes = { +-- ["ROUND"] = {true, true, true, true}, +-- ["SQUARE"] = {false, false, false, false}, +-- ["CORNER-TOPLEFT"] = {false, false, false, true}, +-- ["CORNER-TOPRIGHT"] = {false, false, true, false}, +-- ["CORNER-BOTTOMLEFT"] = {false, true, false, false}, +-- ["CORNER-BOTTOMRIGHT"] = {true, false, false, false}, +-- ["SIDE-LEFT"] = {false, true, false, true}, +-- ["SIDE-RIGHT"] = {true, false, true, false}, +-- ["SIDE-TOP"] = {false, false, true, true}, +-- ["SIDE-BOTTOM"] = {true, true, false, false}, +-- ["TRICORNER-TOPLEFT"] = {false, true, true, true}, +-- ["TRICORNER-TOPRIGHT"] = {true, false, true, true}, +-- ["TRICORNER-BOTTOMLEFT"] = {true, true, false, true}, +-- ["TRICORNER-BOTTOMRIGHT"] = {true, true, true, false}, +-- } + +-- local rad, cos, sin, sqrt, max, min = math.rad, math.cos, math.sin, math.sqrt, math.max, math.min +-- function updatePosition(button, position) +-- local angle = rad(position or 225) +-- local x, y, q = cos(angle), sin(angle), 1 +-- if x < 0 then q = q + 1 end +-- if y > 0 then q = q + 2 end +-- local minimapShape = GetMinimapShape and GetMinimapShape() or "ROUND" +-- local quadTable = minimapShapes[minimapShape] +-- local w = (Minimap:GetWidth() / 2) + lib.radius +-- local h = (Minimap:GetHeight() / 2) + lib.radius +-- if quadTable[q] then +-- x, y = x*w, y*h +-- else +-- local diagRadiusW = sqrt(2*(w)^2)-10 +-- local diagRadiusH = sqrt(2*(h)^2)-10 +-- x = max(-w, min(x*diagRadiusW, w)) +-- y = max(-h, min(y*diagRadiusH, h)) +-- end +-- button:SetPoint("CENTER", Minimap, "CENTER", x, y) +-- end +-- end + +-- local function onClick(self, b) +-- if self.dataObject.OnClick then +-- self.dataObject.OnClick(self, b) +-- end +-- end + +-- local function onMouseDown(self) +-- self.isMouseDown = true +-- self.icon:UpdateCoord() +-- end + +-- local function onMouseUp(self) +-- self.isMouseDown = false +-- self.icon:UpdateCoord() +-- end + +-- do +-- local deg, atan2 = math.deg, math.atan2 +-- local function onUpdate(self) +-- local mx, my = Minimap:GetCenter() +-- local px, py = GetCursorPosition() +-- local scale = Minimap:GetEffectiveScale() +-- px, py = px / scale, py / scale +-- local pos = 225 +-- if self.db then +-- pos = deg(atan2(py - my, px - mx)) % 360 +-- self.db.minimapPos = pos +-- else +-- pos = deg(atan2(py - my, px - mx)) % 360 +-- self.minimapPos = pos +-- end +-- updatePosition(self, pos) +-- end + +-- function onDragStart(self) +-- self:LockHighlight() +-- self.isMouseDown = true +-- self.icon:UpdateCoord() +-- self:SetScript("OnUpdate", onUpdate) +-- isDraggingButton = true +-- lib.tooltip:Hide() +-- for _, button in next, lib.objects do +-- if button.showOnMouseover then +-- button.fadeOut:Stop() +-- button:SetAlpha(1) +-- end +-- end +-- end +-- end + +-- local function onDragStop(self) +-- self:SetScript("OnUpdate", nil) +-- self.isMouseDown = false +-- self.icon:UpdateCoord() +-- self:UnlockHighlight() +-- isDraggingButton = false +-- for _, button in next, lib.objects do +-- if button.showOnMouseover then +-- button.fadeOut:Play() +-- end +-- end +-- end + +-- local defaultCoords = {0, 1, 0, 1} +-- local function updateCoord(self) +-- local coords = self:GetParent().dataObject.iconCoords or defaultCoords +-- local deltaX, deltaY = 0, 0 +-- if not self:GetParent().isMouseDown then +-- deltaX = (coords[2] - coords[1]) * 0.05 +-- deltaY = (coords[4] - coords[3]) * 0.05 +-- end +-- self:SetTexCoord(coords[1] + deltaX, coords[2] - deltaX, coords[3] + deltaY, coords[4] - deltaY) +-- end + +-- local function createButton(name, object, db) +-- local button = CreateFrame("Button", "LibDBIcon10_"..name, Minimap) +-- button.dataObject = object +-- button.db = db +-- button:SetFrameStrata("MEDIUM") +-- -- button:SetFixedFrameStrata(true) +-- button:SetFrameLevel(8) +-- -- button:SetFixedFrameLevel(true) +-- button:SetSize(31, 31) +-- button:RegisterForClicks("anyUp") +-- button:RegisterForDrag("LeftButton") +-- button:SetHighlightTexture(136477) --"Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight" +-- if WOW_PROJECT_ID == WOW_PROJECT_MAINLINE then +-- local overlay = button:CreateTexture(nil, "OVERLAY") +-- overlay:SetSize(50, 50) +-- overlay:SetTexture(136430) --"Interface\\Minimap\\MiniMap-TrackingBorder" +-- overlay:SetPoint("TOPLEFT", button, "TOPLEFT", 0, 0) +-- local background = button:CreateTexture(nil, "BACKGROUND") +-- background:SetSize(24, 24) +-- background:SetTexture(136467) --"Interface\\Minimap\\UI-Minimap-Background" +-- background:SetPoint("CENTER", button, "CENTER", 0, 1) +-- local icon = button:CreateTexture(nil, "ARTWORK") +-- icon:SetSize(18, 18) +-- icon:SetTexture(object.icon) +-- icon:SetPoint("CENTER", button, "CENTER", 0, 1) +-- button.icon = icon +-- else +-- local overlay = button:CreateTexture(nil, "OVERLAY") +-- overlay:SetSize(53, 53) +-- overlay:SetTexture(136430) --"Interface\\Minimap\\MiniMap-TrackingBorder" +-- overlay:SetPoint("TOPLEFT") +-- local background = button:CreateTexture(nil, "BACKGROUND") +-- background:SetSize(20, 20) +-- background:SetTexture(136467) --"Interface\\Minimap\\UI-Minimap-Background" +-- background:SetPoint("TOPLEFT", 7, -5) +-- local icon = button:CreateTexture(nil, "ARTWORK") +-- icon:SetSize(17, 17) +-- icon:SetTexture(object.icon) +-- icon:SetPoint("TOPLEFT", 7, -6) +-- button.icon = icon +-- end + +-- button.isMouseDown = false +-- local r, g, b = button.icon:GetVertexColor() +-- button.icon:SetVertexColor(object.iconR or r, object.iconG or g, object.iconB or b) + +-- button.icon.UpdateCoord = updateCoord +-- button.icon:UpdateCoord() + +-- button:SetScript("OnEnter", onEnter) +-- button:SetScript("OnLeave", onLeave) +-- button:SetScript("OnClick", onClick) +-- if not db or not db.lock then +-- button:SetScript("OnDragStart", onDragStart) +-- button:SetScript("OnDragStop", onDragStop) +-- end +-- button:SetScript("OnMouseDown", onMouseDown) +-- button:SetScript("OnMouseUp", onMouseUp) + +-- button.fadeOut = button:CreateAnimationGroup() +-- local animOut = button.fadeOut:CreateAnimation("Alpha") +-- -- animOut:SetOrder(1) +-- -- animOut:SetDuration(0.2) +-- -- animOut:SetFromAlpha(1) +-- -- animOut:SetToAlpha(0) +-- -- animOut:SetStartDelay(1) +-- -- button.fadeOut:SetToFinalAlpha(true) + +-- lib.objects[name] = button + +-- if lib.loggedIn then +-- updatePosition(button, db and db.minimapPos) +-- if not db or not db.hide then +-- button:Show() +-- else +-- button:Hide() +-- end +-- end +-- lib.callbacks:Fire("LibDBIcon_IconCreated", button, name) -- Fire 'Icon Created' callback +-- end + +-- -- We could use a metatable.__index on lib.objects, but then we'd create +-- -- the icons when checking things like :IsRegistered, which is not necessary. +-- local function check(name) +-- if lib.notCreated[name] then +-- createButton(name, lib.notCreated[name][1], lib.notCreated[name][2]) +-- lib.notCreated[name] = nil +-- end +-- end + +-- -- Wait a bit with the initial positioning to let any GetMinimapShape addons +-- -- load up. +-- if not lib.loggedIn then +-- local f = CreateFrame("Frame") +-- f:SetScript("OnEvent", function(f) +-- for _, button in next, lib.objects do +-- updatePosition(button, button.db and button.db.minimapPos) +-- if not button.db or not button.db.hide then +-- button:Show() +-- else +-- button:Hide() +-- end +-- end +-- lib.loggedIn = true +-- f:SetScript("OnEvent", nil) +-- end) +-- f:RegisterEvent("PLAYER_LOGIN") +-- end + +-- local function getDatabase(name) +-- return lib.notCreated[name] and lib.notCreated[name][2] or lib.objects[name].db +-- end + +-- function lib:Register(name, object, db) +-- if not object.icon then error("Can't register LDB objects without icons set!") end +-- if lib.objects[name] or lib.notCreated[name] then error(DBICON10.. ": Object '".. name .."' is already registered.") end +-- if not db or not db.hide then +-- createButton(name, object, db) +-- else +-- lib.notCreated[name] = {object, db} +-- end +-- end + +-- function lib:Lock(name) +-- if not lib:IsRegistered(name) then return end +-- if lib.objects[name] then +-- lib.objects[name]:SetScript("OnDragStart", nil) +-- lib.objects[name]:SetScript("OnDragStop", nil) +-- end +-- local db = getDatabase(name) +-- if db then +-- db.lock = true +-- end +-- end + +-- function lib:Unlock(name) +-- if not lib:IsRegistered(name) then return end +-- if lib.objects[name] then +-- lib.objects[name]:SetScript("OnDragStart", onDragStart) +-- lib.objects[name]:SetScript("OnDragStop", onDragStop) +-- end +-- local db = getDatabase(name) +-- if db then +-- db.lock = nil +-- end +-- end + +-- function lib:Hide(name) +-- if not lib.objects[name] then return end +-- lib.objects[name]:Hide() +-- end + +-- function lib:Show(name) +-- check(name) +-- local button = lib.objects[name] +-- if button then +-- button:Show() +-- updatePosition(button, button.db and button.db.minimapPos or button.minimapPos) +-- end +-- end + +-- function lib:IsRegistered(name) +-- return (lib.objects[name] or lib.notCreated[name]) and true or false +-- end + +-- function lib:Refresh(name, db) +-- check(name) +-- local button = lib.objects[name] +-- if db then +-- button.db = db +-- end +-- updatePosition(button, button.db and button.db.minimapPos or button.minimapPos) +-- if not button.db or not button.db.hide then +-- button:Show() +-- else +-- button:Hide() +-- end +-- if not button.db or not button.db.lock then +-- button:SetScript("OnDragStart", onDragStart) +-- button:SetScript("OnDragStop", onDragStop) +-- else +-- button:SetScript("OnDragStart", nil) +-- button:SetScript("OnDragStop", nil) +-- end +-- end + +-- function lib:GetMinimapButton(name) +-- return lib.objects[name] +-- end + +-- do +-- local function OnMinimapEnter() +-- if isDraggingButton then return end +-- for _, button in next, lib.objects do +-- if button.showOnMouseover then +-- button.fadeOut:Stop() +-- button:SetAlpha(1) +-- end +-- end +-- end +-- local function OnMinimapLeave() +-- if isDraggingButton then return end +-- for _, button in next, lib.objects do +-- if button.showOnMouseover then +-- button.fadeOut:Play() +-- end +-- end +-- end +-- Minimap:HookScript("OnEnter", OnMinimapEnter) +-- Minimap:HookScript("OnLeave", OnMinimapLeave) + +-- function lib:ShowOnEnter(name, value) +-- local button = lib.objects[name] +-- if button then +-- if value then +-- button.showOnMouseover = true +-- button.fadeOut:Stop() +-- button:SetAlpha(0) +-- else +-- button.showOnMouseover = false +-- button.fadeOut:Stop() +-- button:SetAlpha(1) +-- end +-- end +-- end +-- end + +-- function lib:GetButtonList() +-- local t = {} +-- for name in next, lib.objects do +-- t[#t+1] = name +-- end +-- return t +-- end + +-- function lib:SetButtonRadius(radius) +-- if type(radius) == "number" then +-- lib.radius = radius +-- for _, button in next, lib.objects do +-- updatePosition(button, button.db and button.db.minimapPos or button.minimapPos) +-- end +-- end +-- end + +-- function lib:SetButtonToPosition(button, position) +-- updatePosition(lib.objects[button] or button, position) +-- end + +-- -- Upgrade! +-- for name, button in next, lib.objects do +-- local db = getDatabase(name) +-- if not db or not db.lock then +-- button:SetScript("OnDragStart", onDragStart) +-- button:SetScript("OnDragStop", onDragStop) +-- end +-- button:SetScript("OnEnter", onEnter) +-- button:SetScript("OnLeave", onLeave) +-- button:SetScript("OnClick", onClick) +-- button:SetScript("OnMouseDown", onMouseDown) +-- button:SetScript("OnMouseUp", onMouseUp) + +-- if not button.fadeOut then -- Upgrade to 39 +-- button.fadeOut = button:CreateAnimationGroup() +-- local animOut = button.fadeOut:CreateAnimation("Alpha") +-- animOut:SetOrder(1) +-- animOut:SetDuration(0.2) +-- animOut:SetFromAlpha(1) +-- animOut:SetToAlpha(0) +-- animOut:SetStartDelay(1) +-- button.fadeOut:SetToFinalAlpha(true) +-- end +-- end +-- lib:SetButtonRadius(lib.radius) -- Upgrade to 40 +-- -- LibDBIconEnd + +-- end +-- -- LeaLibDBIcon() -- disabled in 3.3.5, was causing red things + + +-- ---------------------------------------------------------------------- +-- -- L15: LibChatAnims (load on demand) +-- ---------------------------------------------------------------------- + +-- function Leatrix_Plus:LeaPlusLCA() + +-- -- LibChatAnimsStart +-- --@curseforge-project-slug: libchatanims@ +-- local MAJOR, MINOR = "LibChatAnims", 4 -- Bump minor on changes +-- local LCA = LibStub:NewLibrary(MAJOR, MINOR) +-- if not LCA then return end -- No upgrade needed + +-- LCA.animations = LCA.animations or {} -- Animation storage +-- LCA.alerting = LCA.alerting or {} -- Chat tab alerting storage +-- local anims = LCA.animations +-- local alerting = LCA.alerting + +-- function LCA:IsAlerting(tab) +-- if alerting[tab] then +-- return true +-- end +-- end + +-- ---------------------------------------------------- +-- -- Note, most of this code is simply replicated from +-- -- Blizzard's FloatingChatFrame.lua file. +-- -- The only real changes are the creation and use +-- -- of animations vs the use of UIFrameFlash. +-- -- + +-- --FCFDockOverflowButton_UpdatePulseState = function(self) +-- -- local dock = self:GetParent() +-- -- local shouldPulse = false +-- -- for _, chatFrame in pairs(FCFDock_GetChatFrames(dock)) do +-- -- local chatTab = _G[chatFrame:GetName().."Tab"] +-- -- if ( not chatFrame.isStaticDocked and chatTab.alerting) then +-- -- -- Make sure the rects are valid. (Not always the case when resizing the WoW client +-- -- if ( not chatTab:GetRight() or not dock.scrollFrame:GetRight() ) then +-- -- return false +-- -- end +-- -- -- Check if it's off the screen. +-- -- local DELTA = 3 -- Chosen through experimentation +-- -- if ( chatTab:GetRight() < (dock.scrollFrame:GetLeft() + DELTA) or chatTab:GetLeft() > (dock.scrollFrame:GetRight() - DELTA) ) then +-- -- shouldPulse = true +-- -- break +-- -- end +-- -- end +-- -- end +-- -- +-- -- local tex = self:GetHighlightTexture() +-- -- if shouldPulse then +-- -- if not anims[tex] then +-- -- anims[tex] = tex:CreateAnimationGroup() +-- -- +-- -- local fade1 = anims[tex]:CreateAnimation("Alpha") +-- -- fade1:SetDuration(1) +-- -- fade1:SetFromAlpha(0) +-- -- fade1:SetToAlpha(1) +-- -- fade1:SetOrder(1) +-- -- +-- -- local fade2 = anims[tex]:CreateAnimation("Alpha") +-- -- fade2:SetDuration(1) +-- -- fade2:SetFromAlpha(1) +-- -- fade2:SetToAlpha(0) +-- -- fade2:SetOrder(2) +-- -- end +-- -- tex:Show() +-- -- tex:SetAlpha(0) +-- -- anims[tex]:SetLooping("REPEAT") +-- -- anims[tex]:Play() +-- -- +-- -- self:LockHighlight() +-- -- self.alerting = true +-- -- else +-- -- if anims[tex] then +-- -- anims[tex]:Stop() +-- -- end +-- -- self:UnlockHighlight() +-- -- tex:SetAlpha(1) +-- -- tex:Show() +-- -- self.alerting = false +-- -- end +-- -- +-- -- if self.list:IsShown() then +-- -- FCFDockOverflowList_Update(self.list, dock) +-- -- end +-- -- return true +-- --end + +-- --FCFDockOverflowListButton_SetValue = function(button, chatFrame) +-- -- local chatTab = _G[chatFrame:GetName().."Tab"] +-- -- button.chatFrame = chatFrame +-- -- button:SetText(chatFrame.name) +-- -- +-- -- local colorTable = chatTab.selectedColorTable or DEFAULT_TAB_SELECTED_COLOR_TABLE +-- -- +-- -- if chatTab.selectedColorTable then +-- -- button:GetFontString():SetTextColor(colorTable.r, colorTable.g, colorTable.b) +-- -- else +-- -- button:GetFontString():SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b) +-- -- end +-- -- +-- -- button.glow:SetVertexColor(colorTable.r, colorTable.g, colorTable.b) +-- -- +-- -- if chatTab.conversationIcon then +-- -- button.conversationIcon:SetVertexColor(colorTable.r, colorTable.g, colorTable.b) +-- -- button.conversationIcon:Show() +-- -- else +-- -- button.conversationIcon:Hide() +-- -- end +-- -- +-- -- if chatTab.alerting then +-- -- button.alerting = true +-- -- if not anims[button.glow] then +-- -- anims[button.glow] = button.glow:CreateAnimationGroup() +-- -- +-- -- local fade1 = anims[button.glow]:CreateAnimation("Alpha") +-- -- fade1:SetDuration(1) +-- -- fade1:SetFromAlpha(0) +-- -- fade1:SetToAlpha(1) +-- -- fade1:SetOrder(1) +-- -- +-- -- local fade2 = anims[button.glow]:CreateAnimation("Alpha") +-- -- fade2:SetDuration(1) +-- -- fade2:SetFromAlpha(1) +-- -- fade2:SetToAlpha(0) +-- -- fade2:SetOrder(2) +-- -- end +-- -- button.glow:Show() +-- -- button.glow:SetAlpha(0) +-- -- anims[button.glow]:SetLooping("REPEAT") +-- -- anims[button.glow]:Play() +-- -- else +-- -- button.alerting = false +-- -- if anims[button.glow] then +-- -- anims[button.glow]:Stop() +-- -- end +-- -- button.glow:Hide() +-- -- end +-- -- button:Show() +-- --end + +-- FCF_StartAlertFlash = function(chatFrame) +-- local chatTab = _G[chatFrame:GetName().."Tab"] + +-- if chatFrame.minFrame then +-- if not anims[chatFrame.minFrame] then +-- anims[chatFrame.minFrame] = chatFrame.minFrame.glow:CreateAnimationGroup() + +-- local fade1 = anims[chatFrame.minFrame]:CreateAnimation("Alpha") +-- fade1:SetDuration(1) +-- fade1:SetFromAlpha(0) +-- fade1:SetToAlpha(1) +-- fade1:SetOrder(1) + +-- local fade2 = anims[chatFrame.minFrame]:CreateAnimation("Alpha") +-- fade2:SetDuration(1) +-- fade2:SetFromAlpha(1) +-- fade2:SetToAlpha(0) +-- fade2:SetOrder(2) +-- end +-- chatFrame.minFrame.glow:Show() +-- chatFrame.minFrame.glow:SetAlpha(0) +-- anims[chatFrame.minFrame]:SetLooping("REPEAT") +-- anims[chatFrame.minFrame]:Play() +-- --chatFrame.minFrame.alerting = true +-- alerting[chatFrame.minFrame] = true +-- end + +-- if not anims[chatTab.glow] then +-- anims[chatTab.glow] = chatTab.glow:CreateAnimationGroup() + +-- local fade1 = anims[chatTab.glow]:CreateAnimation("Alpha") +-- fade1:SetDuration(1) +-- fade1:SetFromAlpha(0) +-- fade1:SetToAlpha(1) +-- fade1:SetOrder(1) + +-- local fade2 = anims[chatTab.glow]:CreateAnimation("Alpha") +-- fade2:SetDuration(1) +-- fade2:SetFromAlpha(1) +-- fade2:SetToAlpha(0) +-- fade2:SetOrder(2) +-- end +-- chatTab.glow:Show() +-- chatTab.glow:SetAlpha(0) +-- anims[chatTab.glow]:SetLooping("REPEAT") +-- anims[chatTab.glow]:Play() +-- --chatTab.alerting = true +-- alerting[chatTab] = true + + +-- -- START function FCFTab_UpdateAlpha(chatFrame) +-- local mouseOverAlpha, noMouseAlpha = 0, 0 +-- if not chatFrame.isDocked or chatFrame == FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK) then +-- mouseOverAlpha = 1.0 --CHAT_FRAME_TAB_SELECTED_MOUSEOVER_ALPHA +-- noMouseAlpha = 0.4 -- CHAT_FRAME_TAB_SELECTED_NOMOUSE_ALPHA +-- else +-- mouseOverAlpha = 1.0 -- CHAT_FRAME_TAB_ALERTING_MOUSEOVER_ALPHA +-- noMouseAlpha = 1.0 -- CHAT_FRAME_TAB_ALERTING_NOMOUSE_ALPHA +-- end +-- if chatFrame.hasBeenFaded then +-- chatTab:SetAlpha(mouseOverAlpha) +-- else +-- chatTab:SetAlpha(noMouseAlpha) +-- end +-- --END function FCFTab_UpdateAlpha(chatFrame) + +-- --FCFDockOverflowButton_UpdatePulseState(GENERAL_CHAT_DOCK.overflowButton) +-- end + +-- FCF_StopAlertFlash = function(chatFrame) +-- local chatTab = _G[chatFrame:GetName().."Tab"] + +-- if chatFrame.minFrame then +-- if anims[chatFrame.minFrame] then +-- anims[chatFrame.minFrame]:Stop() +-- end +-- chatFrame.minFrame.glow:Hide() +-- --chatFrame.minFrame.alerting = false +-- alerting[chatFrame.minFrame] = nil +-- end + +-- if anims[chatTab.glow] then +-- anims[chatTab.glow]:Stop() +-- end +-- chatTab.glow:Hide() +-- --chatTab.alerting = false +-- alerting[chatTab] = nil + +-- -- START function FCFTab_UpdateAlpha(chatFrame) +-- local mouseOverAlpha, noMouseAlpha = 0, 0 +-- if not chatFrame.isDocked or chatFrame == FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK) then +-- mouseOverAlpha = 1.0 --CHAT_FRAME_TAB_SELECTED_MOUSEOVER_ALPHA +-- noMouseAlpha = 0.4 -- CHAT_FRAME_TAB_SELECTED_NOMOUSE_ALPHA +-- else +-- mouseOverAlpha = 0.6 --CHAT_FRAME_TAB_NORMAL_MOUSEOVER_ALPHA +-- noMouseAlpha = 0.2 --CHAT_FRAME_TAB_NORMAL_NOMOUSE_ALPHA +-- end +-- if chatFrame.hasBeenFaded then +-- chatTab:SetAlpha(mouseOverAlpha) +-- else +-- chatTab:SetAlpha(noMouseAlpha) +-- end +-- --END function FCFTab_UpdateAlpha(chatFrame) + +-- --FCFDockOverflowButton_UpdatePulseState(GENERAL_CHAT_DOCK.overflowButton) +-- end + +-- -- LibChatAnimsEnd + +-- end + +-- ---------------------------------------------------------------------- +-- -- L16: LibDBIcon: LibCandyBar +-- ---------------------------------------------------------------------- + +-- function Leatrix_Plus:LeaPlusCandyBar() + +-- -- LibCandyBarStart +-- --@curseforge-project-slug: libcandybar-3-0@ +-- --- **LibCandyBar-3.0** provides elegant timerbars with icons for use in addons. +-- -- It is based of the original ideas of the CandyBar and CandyBar-2.0 library. +-- -- In contrary to the earlier libraries LibCandyBar-3.0 provides you with a timerbar object with a simple API. +-- -- +-- -- Creating a new timerbar using the ':New' function will return a new timerbar object. This timerbar object inherits all of the barPrototype functions listed here. \\ +-- -- +-- -- @usage +-- -- local candy = LibStub("LibCandyBar-3.0") +-- -- local texture = "Interface\\AddOns\\MyAddOn\\statusbar" +-- -- local mybar = candy:New(texture, 100, 16) +-- -- mybar:SetLabel("Yay!") +-- -- mybar:SetDuration(60) +-- -- mybar:Start() +-- -- @class file +-- -- @name LibCandyBar-3.0 + +-- local GetTime, floor, next = GetTime, floor, next +-- local CreateFrame, error, setmetatable, UIParent = CreateFrame, error, setmetatable, UIParent + +-- if not LibStub then error("LibCandyBar-3.0 requires LibStub.") end +-- local cbh = LibStub:GetLibrary("CallbackHandler-1.0") +-- if not cbh then error("LibCandyBar-3.0 requires CallbackHandler-1.0") end +-- local lib = LibStub:NewLibrary("LibCandyBar-3.0", 100) -- Bump minor on changes +-- if not lib then return end +-- lib.callbacks = lib.callbacks or cbh:New(lib) +-- local cb = lib.callbacks +-- lib.dummyFrame = lib.dummyFrame or CreateFrame("Frame") +-- lib.barFrameMT = lib.barFrameMT or {__index = lib.dummyFrame} +-- lib.barPrototype = lib.barPrototype or setmetatable({}, lib.barFrameMT) +-- lib.barPrototype_mt = lib.barPrototype_mt or {__index = lib.barPrototype} +-- lib.barCache = lib.barCache or {} + +-- local barPrototype = lib.barPrototype +-- local barPrototype_meta = lib.barPrototype_mt +-- local barCache = lib.barCache + +-- local scripts = { +-- "OnUpdate", "OnDragStart", "OnDragStop", +-- "OnEnter", "OnLeave", "OnHide", +-- "OnShow", "OnMouseDown", "OnMouseUp", +-- "OnMouseWheel", "OnSizeChanged", "OnEvent" +-- } +-- local numScripts = #scripts +-- local GameFontHighlightSmallOutline = GameFontHighlightSmallOutline +-- local _fontName, _fontSize = GameFontHighlightSmallOutline:GetFont() +-- local _fontShadowX, _fontShadowY = GameFontHighlightSmallOutline:GetShadowOffset() +-- local _fontShadowR, _fontShadowG, _fontShadowB, _fontShadowA = GameFontHighlightSmallOutline:GetShadowColor() +-- local SetWidth, SetHeight, SetSize = lib.dummyFrame.SetWidth, lib.dummyFrame.SetHeight, lib.dummyFrame.SetSize + +-- local function stopBar(bar) +-- bar.updater:Stop() +-- bar.data = nil +-- bar.funcs = nil +-- bar.running = nil +-- bar.paused = nil +-- bar:Hide() +-- bar:SetParent(UIParent) +-- end + +-- local tformat1 = "%d:%02d:%02d" +-- local tformat2 = "%d:%02d" +-- local tformat3 = "%.1f" +-- local tformat4 = "%.0f" +-- local function barUpdate(updater) +-- local bar = updater.parent +-- local t = GetTime() +-- if t >= bar.exp then +-- bar:Stop() +-- else +-- local time = bar.exp - t +-- bar.remaining = time + +-- bar.candyBarBar:SetValue(bar.fill and (t-bar.start)+bar.gap or time) + +-- if time > 3599.9 then -- > 1 hour +-- local h = floor(time/3600) +-- local m = floor((time - (h*3600))/60) +-- local s = (time - (m*60)) - (h*3600) +-- bar.candyBarDuration:SetFormattedText(tformat1, h, m, s) +-- elseif time > 59.9 then -- 1 minute to 1 hour +-- local m = floor(time/60) +-- local s = time - (m*60) +-- bar.candyBarDuration:SetFormattedText(tformat2, m, s) +-- elseif time < 10 then -- 0 to 10 seconds +-- bar.candyBarDuration:SetFormattedText(tformat3, time) +-- else -- 10 seconds to one minute +-- bar.candyBarDuration:SetFormattedText(tformat4, time) +-- end + +-- if bar.funcs then +-- for i = 1, #bar.funcs do +-- bar.funcs[i](bar) +-- end +-- end +-- end +-- end + +-- local atformat1 = "~%d:%02d:%02d" +-- local atformat2 = "~%d:%02d" +-- local atformat3 = "~%.1f" +-- local atformat4 = "~%.0f" +-- local function barUpdateApprox(updater) +-- local bar = updater.parent +-- local t = GetTime() +-- if t >= bar.exp then +-- bar:Stop() +-- else +-- local time = bar.exp - t +-- bar.remaining = time + +-- bar.candyBarBar:SetValue(bar.fill and (t-bar.start)+bar.gap or time) + +-- if time > 3599.9 then -- > 1 hour +-- local h = floor(time/3600) +-- local m = floor((time - (h*3600))/60) +-- local s = (time - (m*60)) - (h*3600) +-- bar.candyBarDuration:SetFormattedText(atformat1, h, m, s) +-- elseif time > 59.9 then -- 1 minute to 1 hour +-- local m = floor(time/60) +-- local s = time - (m*60) +-- bar.candyBarDuration:SetFormattedText(atformat2, m, s) +-- elseif time < 10 then -- 0 to 10 seconds +-- bar.candyBarDuration:SetFormattedText(atformat3, time) +-- else -- 10 seconds to one minute +-- bar.candyBarDuration:SetFormattedText(atformat4, time) +-- end + +-- if bar.funcs then +-- for i = 1, #bar.funcs do +-- bar.funcs[i](bar) +-- end +-- end +-- end +-- end + +-- -- ------------------------------------------------------------------------------ +-- -- Bar functions +-- -- + +-- local function restyleBar(self) +-- if not self.running then return end +-- self.candyBarIconFrame:ClearAllPoints() +-- self.candyBarBar:ClearAllPoints() +-- -- In the past we used a :GetTexture check here, but as of WoW v5 it randomly returns nil, so use our own trustworthy variable. +-- if self.candyBarIconFrame.icon then +-- self.candyBarIconFrame:SetWidth(self.height) +-- if self.iconPosition == "RIGHT" then +-- self.candyBarIconFrame:SetPoint("TOPRIGHT", self) +-- self.candyBarIconFrame:SetPoint("BOTTOMRIGHT", self) +-- self.candyBarBar:SetPoint("TOPRIGHT", self.candyBarIconFrame, "TOPLEFT") +-- self.candyBarBar:SetPoint("BOTTOMRIGHT", self.candyBarIconFrame, "BOTTOMLEFT") +-- self.candyBarBar:SetPoint("TOPLEFT", self) +-- self.candyBarBar:SetPoint("BOTTOMLEFT", self) +-- else +-- self.candyBarIconFrame:SetPoint("TOPLEFT") +-- self.candyBarIconFrame:SetPoint("BOTTOMLEFT") +-- self.candyBarBar:SetPoint("TOPLEFT", self.candyBarIconFrame, "TOPRIGHT") +-- self.candyBarBar:SetPoint("BOTTOMLEFT", self.candyBarIconFrame, "BOTTOMRIGHT") +-- self.candyBarBar:SetPoint("TOPRIGHT", self) +-- self.candyBarBar:SetPoint("BOTTOMRIGHT", self) +-- end +-- self.candyBarIconFrame:Show() +-- else +-- self.candyBarBar:SetPoint("TOPLEFT", self) +-- self.candyBarBar:SetPoint("BOTTOMRIGHT", self) +-- self.candyBarIconFrame:Hide() +-- end +-- if self.showLabel and self.candyBarLabel.text then +-- self.candyBarLabel:Show() +-- else +-- self.candyBarLabel:Hide() +-- end +-- if self.showTime then +-- self.candyBarDuration:Show() +-- else +-- self.candyBarDuration:Hide() +-- end +-- end + +-- --- Set whether the bar should drain (default) or fill up. +-- -- @param fill Boolean true/false +-- function barPrototype:SetFill(fill) +-- self.fill = fill +-- end +-- --- Adds a function to the timerbar. The function will run every update and will receive the bar as a parameter. +-- -- @param func Function to run every update. +-- -- @usage +-- -- -- The example below will print the time remaining to the chatframe every update. Yes, that's a whole lot of spam +-- -- mybar:AddUpdateFunction( function(bar) print(bar.remaining) end ) +-- function barPrototype:AddUpdateFunction(func) if not self.funcs then self.funcs = {} end; self.funcs[#self.funcs+1] = func end +-- --- Sets user data in the timerbar object. +-- -- @param key Key to use for the data storage. +-- -- @param data Data to store. +-- function barPrototype:Set(key, data) if not self.data then self.data = {} end; self.data[key] = data end +-- --- Retrieves user data from the timerbar object. +-- -- @param key Key to retrieve +-- function barPrototype:Get(key) return self.data and self.data[key] end +-- --- Sets the color of the bar. +-- -- This is basically a wrapper to SetStatusBarColor. +-- -- @paramsig r, g, b, a +-- -- @param r Red component (0-1) +-- -- @param g Green component (0-1) +-- -- @param b Blue component (0-1) +-- -- @param a Alpha (0-1) +-- function barPrototype:SetColor(...) self.candyBarBar:SetStatusBarColor(...) end +-- --- Sets the color of the bar label and bar duration text. +-- -- @paramsig r, g, b, a +-- -- @param r Red component (0-1) +-- -- @param g Green component (0-1) +-- -- @param b Blue component (0-1) +-- -- @param a Alpha (0-1) +-- function barPrototype:SetTextColor(...) +-- self.candyBarLabel:SetTextColor(...) +-- self.candyBarDuration:SetTextColor(...) +-- end +-- --- Sets the shadow color of the bar label and bar duration text. +-- -- @paramsig r, g, b, a +-- -- @param r Red component (0-1) +-- -- @param g Green component (0-1) +-- -- @param b Blue component (0-1) +-- -- @param a Alpha (0-1) +-- function barPrototype:SetShadowColor(...) +-- self.candyBarLabel:SetShadowColor(...) +-- self.candyBarDuration:SetShadowColor(...) +-- end +-- --- Sets the texture of the bar. +-- -- This should only be needed on running bars that get changed on the fly. +-- -- @param texture Path to the bar texture. +-- function barPrototype:SetTexture(texture) +-- self.candyBarBar:SetStatusBarTexture(texture) +-- self.candyBarBackground:SetTexture(texture) +-- end +-- --- Sets the width of the bar. +-- -- This should only be needed on running bars that get changed on the fly. +-- -- @param width Width of the bar. +-- function barPrototype:SetWidth(width) +-- self.width = width +-- SetWidth(self, width) +-- end +-- --- Sets the height of the bar. +-- -- This should only be needed on running bars that get changed on the fly. +-- -- @param height Height of the bar. +-- function barPrototype:SetHeight(height) +-- self.height = height +-- SetHeight(self, height) +-- restyleBar(self) +-- end +-- --- Sets the size of the bar. +-- -- This should only be needed on running bars that get changed on the fly. +-- -- @param width Width of the bar. +-- -- @param height Height of the bar. +-- function barPrototype:SetSize(width, height) +-- self.width = width +-- self.height = height +-- SetSize(self, width, height) +-- restyleBar(self) +-- end +-- --- Returns the label (text) currently set on the bar. +-- function barPrototype:GetLabel() +-- return self.candyBarLabel.text +-- end +-- --- Sets the label on the bar. +-- -- @param text Label text. +-- function barPrototype:SetLabel(text) +-- self.candyBarLabel.text = text +-- self.candyBarLabel:SetText(text) +-- if text then +-- self.candyBarLabel:Show() +-- else +-- self.candyBarLabel:Hide() +-- end +-- end +-- --- Returns the icon texture path currently set on the bar, if it has an icon set. +-- function barPrototype:GetIcon() +-- return self.candyBarIconFrame.icon +-- end +-- --- Sets the icon next to the bar. +-- -- @param icon Path to the icon texture or nil to not display an icon. +-- -- @param ... Optional icon coordinates for texture trimming. +-- function barPrototype:SetIcon(icon, ...) +-- self.candyBarIconFrame.icon = icon +-- self.candyBarIconFrame:SetTexture(icon) +-- if ... then +-- self.candyBarIconFrame:SetTexCoord(...) +-- else +-- self.candyBarIconFrame:SetTexCoord(0.07, 0.93, 0.07, 0.93) +-- end +-- restyleBar(self) +-- end +-- --- Sets which side of the bar the icon should appear. +-- -- @param position Position of the icon according to the bar, either "LEFT" or "RIGHT" as a string. Set to "LEFT" by default. +-- function barPrototype:SetIconPosition(position) +-- self.iconPosition = position +-- restyleBar(self) +-- end +-- --- Sets wether or not the time indicator on the right of the bar should be shown. +-- -- Time is shown by default. +-- -- @param bool true to show the time, false/nil to hide the time. +-- function barPrototype:SetTimeVisibility(bool) +-- self.showTime = bool +-- if bool then +-- self.candyBarDuration:Show() +-- else +-- self.candyBarDuration:Hide() +-- end +-- end +-- --- Sets wether or not the label on the left of the bar should be shown. +-- -- label is shown by default. +-- -- @param bool true to show the label, false/nil to hide the label. +-- function barPrototype:SetLabelVisibility(bool) +-- self.showLabel = bool +-- if bool then +-- self.candyBarLabel:Show() +-- else +-- self.candyBarLabel:Hide() +-- end +-- end +-- --- Sets the duration of the bar. +-- -- This can also be used while the bar is running to adjust the time remaining, within the bounds of the original duration. +-- -- @param duration Duration of the bar in seconds. +-- -- @param isApprox Boolean. True if you wish the time display to be an approximate "~5" instead of "5" +-- function barPrototype:SetDuration(duration, isApprox) self.remaining = duration; self.isApproximate = isApprox end +-- --- Shows the bar and starts it. +-- -- @param maxValue Number. If you don't wish your bar to start full, you can set a max value. A maxValue of 10 on a bar with a duration of 5 would start it at 50%. +-- function barPrototype:Start(maxValue) +-- self.running = true +-- local time = self.remaining +-- self.gap = maxValue and maxValue-time or 0 +-- restyleBar(self) +-- self.start = GetTime() +-- self.exp = self.start + time + +-- self.candyBarBar:SetMinMaxValues(0, maxValue or time) +-- self.candyBarBar:SetValue(self.fill and 0 or time) + +-- if self.isApproximate then +-- if time > 3599.9 then -- > 1 hour +-- local h = floor(time/3600) +-- local m = floor((time - (h*3600))/60) +-- local s = (time - (m*60)) - (h*3600) +-- self.candyBarDuration:SetFormattedText(atformat1, h, m, s) +-- elseif time > 59.9 then -- 1 minute to 1 hour +-- local m = floor(time/60) +-- local s = time - (m*60) +-- self.candyBarDuration:SetFormattedText(atformat2, m, s) +-- elseif time < 10 then -- 0 to 10 seconds +-- self.candyBarDuration:SetFormattedText(atformat3, time) +-- else -- 10 seconds to one minute +-- self.candyBarDuration:SetFormattedText(atformat4, time) +-- end +-- self.updater:SetScript("OnLoop", barUpdateApprox) +-- else +-- if time > 3599.9 then -- > 1 hour +-- local h = floor(time/3600) +-- local m = floor((time - (h*3600))/60) +-- local s = (time - (m*60)) - (h*3600) +-- self.candyBarDuration:SetFormattedText(tformat1, h, m, s) +-- elseif time > 59.9 then -- 1 minute to 1 hour +-- local m = floor(time/60) +-- local s = time - (m*60) +-- self.candyBarDuration:SetFormattedText(tformat2, m, s) +-- elseif time < 10 then -- 0 to 10 seconds +-- self.candyBarDuration:SetFormattedText(tformat3, time) +-- else -- 10 seconds to one minute +-- self.candyBarDuration:SetFormattedText(tformat4, time) +-- end +-- self.updater:SetScript("OnLoop", barUpdate) +-- end +-- self.updater:Play() +-- self:Show() +-- end +-- --- Pauses a running bar +-- function barPrototype:Pause() +-- if not self.paused then +-- self.updater:Pause() +-- self.paused = GetTime() +-- end +-- end +-- --- Resumes a paused bar +-- function barPrototype:Resume() +-- if self.paused then +-- local t = GetTime() +-- self.exp = t + self.remaining +-- self.start = self.start + (t-self.paused) +-- self.updater:Play() +-- self.paused = nil +-- end +-- end +-- --- Stops the bar. +-- -- This will stop the bar, fire the LibCandyBar_Stop callback, and recycle the bar into the candybar pool. +-- -- Note: make sure you remove all references to the bar in your addon upon receiving the LibCandyBar_Stop callback. +-- -- @usage +-- -- -- The example below shows the use of the LibCandyBar_Stop callback by printing the contents of the label in the chatframe +-- -- local function barstopped( callback, bar ) +-- -- print( bar:GetLabel(), "stopped") +-- -- end +-- -- LibStub("LibCandyBar-3.0"):RegisterCallback(myaddonobject, "LibCandyBar_Stop", barstopped) +-- -- @param ... Optional args to pass across in the LibCandyBar_Stop callback. +-- function barPrototype:Stop(...) +-- cb:Fire("LibCandyBar_Stop", self, ...) +-- stopBar(self) +-- barCache[self] = true +-- end + +-- -- ------------------------------------------------------------------------------ +-- -- Library functions +-- -- + +-- --- Creates a new timerbar object and returns it. Don't forget to set the duration, label and :Start the timer bar after you get a hold of it! +-- -- @paramsig texture, width, height +-- -- @param texture Path to the texture used for the bar. +-- -- @param width Width of the bar. +-- -- @param height Height of the bar. +-- -- @usage +-- -- mybar = LibStub("LibCandyBar-3.0"):New("Interface\\AddOns\\MyAddOn\\media\\statusbar", 100, 16) +-- function lib:New(texture, width, height) +-- local bar = next(barCache) +-- if not bar then +-- local frame = CreateFrame("Frame", nil, UIParent) +-- bar = setmetatable(frame, barPrototype_meta) + +-- local icon = bar:CreateTexture() +-- icon:SetPoint("TOPLEFT") +-- icon:SetPoint("BOTTOMLEFT") +-- icon:Show() +-- bar.candyBarIconFrame = icon + +-- local statusbar = CreateFrame("StatusBar", nil, bar) +-- statusbar:SetPoint("TOPRIGHT") +-- statusbar:SetPoint("BOTTOMRIGHT") +-- bar.candyBarBar = statusbar + +-- local bg = statusbar:CreateTexture(nil, "BACKGROUND") +-- bg:SetAllPoints() +-- bar.candyBarBackground = bg + +-- local backdrop = CreateFrame("Frame", nil, bar, "BackdropTemplate") -- Used by bar stylers for backdrops +-- backdrop:SetFrameLevel(0) +-- bar.candyBarBackdrop = backdrop + +-- local iconBackdrop = CreateFrame("Frame", nil, bar, "BackdropTemplate") -- Used by bar stylers for backdrops +-- iconBackdrop:SetFrameLevel(0) +-- bar.candyBarIconFrameBackdrop = iconBackdrop + +-- local duration = statusbar:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmallOutline") +-- duration:SetPoint("TOPLEFT", statusbar, "TOPLEFT", 2, 0) +-- duration:SetPoint("BOTTOMRIGHT", statusbar, "BOTTOMRIGHT", -2, 0) +-- bar.candyBarDuration = duration + +-- local label = statusbar:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmallOutline") +-- label:SetPoint("TOPLEFT", statusbar, "TOPLEFT", 2, 0) +-- label:SetPoint("BOTTOMRIGHT", statusbar, "BOTTOMRIGHT", -2, 0) +-- bar.candyBarLabel = label + +-- local updater = bar:CreateAnimationGroup() +-- updater:SetLooping("REPEAT") +-- updater.parent = bar +-- local anim = updater:CreateAnimation() +-- anim:SetDuration(0.04) +-- bar.updater = updater +-- bar.repeater = anim +-- else +-- barCache[bar] = nil +-- end + +-- bar:SetFrameStrata("MEDIUM") +-- bar:SetFrameLevel(100) -- Lots of room to create above or below this level +-- bar.candyBarBar:SetStatusBarTexture(texture) +-- bar.candyBarBackground:SetTexture(texture) +-- bar.width = width +-- bar.height = height + +-- -- RESET ALL THE THINGS! +-- bar.fill = nil +-- bar.showTime = true +-- bar.showLabel = true +-- bar.iconPosition = nil +-- for i = 1, numScripts do -- Update if scripts table is changed, faster than doing #scripts +-- bar:SetScript(scripts[i], nil) +-- end + +-- bar.candyBarBackground:SetVertexColor(0.5, 0.5, 0.5, 0.3) +-- bar.candyBarBar:SetStatusBarColor(0.5, 0.5, 0.5, 1) +-- bar:ClearAllPoints() +-- SetWidth(bar, width) +-- SetHeight(bar, height) +-- bar:SetMovable(1) +-- bar:SetScale(1) +-- bar:SetAlpha(1) +-- bar:SetClampedToScreen(false) +-- bar:EnableMouse(false) + +-- bar.candyBarLabel:SetTextColor(1,1,1,1) +-- bar.candyBarLabel:SetJustifyH("LEFT") +-- bar.candyBarLabel:SetJustifyV("MIDDLE") +-- bar.candyBarLabel:SetFont(_fontName, _fontSize) +-- bar.candyBarLabel:SetShadowOffset(_fontShadowX, _fontShadowY) +-- bar.candyBarLabel:SetShadowColor(_fontShadowR, _fontShadowG, _fontShadowB, _fontShadowA) + +-- bar.candyBarDuration:SetTextColor(1,1,1,1) +-- bar.candyBarDuration:SetJustifyH("RIGHT") +-- bar.candyBarDuration:SetJustifyV("MIDDLE") +-- bar.candyBarDuration:SetFont(_fontName, _fontSize) +-- bar.candyBarDuration:SetShadowOffset(_fontShadowX, _fontShadowY) +-- bar.candyBarDuration:SetShadowColor(_fontShadowR, _fontShadowG, _fontShadowB, _fontShadowA) + + +-- bar:SetLabel() +-- bar:SetIcon() +-- bar:SetDuration() + +-- return bar +-- end + +-- -- LibCandyBarEnd + +-- end + +-- -- L17: End