-
Notifications
You must be signed in to change notification settings - Fork 28
Expand file tree
/
Copy pathGridUtils.lua
More file actions
415 lines (386 loc) · 12.2 KB
/
GridUtils.lua
File metadata and controls
415 lines (386 loc) · 12.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
-- Misc functions
local media = LibStub("LibSharedMedia-3.0", true)
local L = LibStub:GetLibrary("AceLocale-3.0"):GetLocale("Grid2")
local Grid2 = Grid2
local select = select
local strtrim = strtrim
local type = type
local pairs = pairs
local tonumber = tonumber
local tremove = table.remove
local issecretvalue = issecretvalue or function() return false end
local canaccessvalue = canaccessvalue or function() return true end
-- Dummy function
Grid2.Dummy = function() end
-- Empty table
Grid2.EmptyTable = {}
-- Midnight Secrets check
Grid2.issecretvalue = issecretvalue
Grid2.canaccessvalue = canaccessvalue
-- SetAlphaFromBoolean() supporting nonbooleans values for non secret statuses
function Grid2.SetAlphaFromBoolean(widget, value, aTrue, aFalse, secret, invert)
if not secret then
value = not not value
end
if invert then
widget:SetAlphaFromBoolean(value, aFalse, aTrue)
else
widget:SetAlphaFromBoolean(value, aTrue, aFalse)
end
end
-- Fetch LibSharedMedia resources
function Grid2:MediaFetch(mediatype, key, def)
return (key and media:Fetch(mediatype, key)) or (def and media:Fetch(mediatype, def))
end
-- Default Colors
do
local defaultColors = {
TRANSPARENT = {r=0,g=0,b=0,a=0},
BLACK = {r=0,g=0,b=0,a=1},
WHITE = {r=1,g=1,b=1,a=1},
RED = {r=1,g=0,b=0,a=1},
GREEN = {r=0,g=1,b=0,a=1},
BLUE = {r=0,g=0,b=1,a=1},
}
function Grid2.MakeColor(color, default)
return color or defaultColors[default or "TRANSPARENT"]
end
function Grid2.UnpackColor(color)
return color.r, color.g, color.b, color.a
end
Grid2.defaultColors = defaultColors
end
-- Repeating Timer Management
do
local frame = CreateFrame("Frame")
local timers = {}
local function SetDuration(self, duration)
self.animation:SetDuration(duration)
end
-- Grid2:CreateTimer(func, duration, play)
-- play=true|nil => timer running; play=false => timer paused
-- timer methods: timer:Play() timer:Stop() timer:SetDuration()
function Grid2:CreateTimer( func, duration, play )
local timer = tremove(timers)
if not timer then
timer = frame:CreateAnimationGroup()
timer.animation = timer:CreateAnimation()
timer.SetDuration = SetDuration
timer:SetLooping("REPEAT")
end
timer:SetScript("OnLoop", func)
if duration then
timer:SetDuration(duration)
if play~=false then timer:Play() end
end
return timer
end
-- Grid2:CancelTimer(timer)
function Grid2:CancelTimer( timer )
if timer then
timer:Stop()
timers[#timers+1] = timer
end
end
end
-- hook helper functions
function Grid2:PreHookFunc(obj, funcName, hook)
local prev = obj[funcName]
obj[funcName] = function(...) prev(...); hook(...); end
end
function Grid2:PostHookFunc(obj, funcName, hook)
local prev = obj[funcName]
obj[funcName] = function(...) hook(...); prev(...); end
end
-- iterate over a list of values example: for value in Grid2.IterateValues(4,2,7,1) do
function Grid2.IterateValues(...)
local i, t = 0, {...}
return function() i = i + 1; return t[i] end
end
-- retrieve config value, falling back to default
function Grid2.GetSetupValue(condition, value, default)
if condition and value~=nil then
return value
else
return default
end
end
-- UTF8 string truncate
do
local issecretvalue = Grid2.issecretvalue
local strbyte = string.byte
function Grid2.strcututf8(s, c)
if issecretvalue(s) then return s end
local l, i = #s, 1
while c>0 and i<=l do
local b = strbyte(s, i)
if b < 192 then i = i + 1
elseif b < 224 then i = i + 2
elseif b < 240 then i = i + 3
else i = i + 4
end
c = c - 1
end
return s:sub(1, i-1)
end
end
-- Transliterate texts, cyrilic to latin conversion
do
local gsub = string.gsub
local Cyr2Lat = {
["А"] = "A", ["а"] = "a", ["Б"] = "B", ["б"] = "b", ["В"] = "V", ["в"] = "v", ["Г"] = "G", ["г"] = "g", ["Д"] = "D", ["д"] = "d", ["Е"] = "E",
["е"] = "e", ["Ё"] = "e", ["ё"] = "e", ["Ж"] = "Zh", ["ж"] = "zh", ["З"] = "Z", ["з"] = "z", ["И"] = "I", ["и"] = "i", ["Й"] = "Y", ["й"] = "y",
["К"] = "K", ["к"] = "k", ["Л"] = "L", ["л"] = "l", ["М"] = "M", ["м"] = "m", ["Н"] = "N", ["н"] = "n", ["О"] = "O", ["о"] = "o", ["П"] = "P",
["п"] = "p", ["Р"] = "R", ["р"] = "r", ["С"] = "S", ["с"] = "s", ["Т"] = "T", ["т"] = "t", ["У"] = "U", ["у"] = "u", ["Ф"] = "F", ["ф"] = "f",
["Х"] = "Kh", ["х"] = "kh", ["Ц"] = "Ts", ["ц"] = "ts", ["Ч"] = "Ch", ["ч"] = "ch", ["Ш"] = "Sh", ["ш"] = "sh", ["Щ"] = "Shch", ["щ"] = "shch",
["Ъ"] = "", ["ъ"] = "", ["Ы"] = "Y", ["ы"] = "y", ["Ь"] = "", ["ь"] = "", ["Э"] = "E", ["э"] = "e", ["Ю"] = "Yu", ["ю"] = "yu", ["Я"] = "Ya",
["я"] = "ya"
}
function Grid2.strCyr2Lat(str)
return canaccessvalue(str) and gsub(str, "..", Cyr2Lat) or str
end
end
-- Table Deep Copy used by GridDefaults.lua
function Grid2.CopyTable(src, dst)
if type(dst)~="table" then dst = {} end
for k,v in pairs(src) do
if type(v)=="table" then
dst[k] = Grid2.CopyTable(v,dst[k])
elseif dst[k]==nil then
dst[k] = v
end
end
return dst
end
-- Remove item by value in a ipairs table
function Grid2.TableRemoveByValue(t,v)
for i=#t,1,-1 do
if t[i]==v then
tremove(t, i)
return
end
end
end
-- Creates a location table, used by GridDefaults.lua
function Grid2.CreateLocation(a,b,c,d)
local p = a or "TOPLEFT"
if type(b)=="string" then
return { relPoint = p, point = b, x = c or 0, y = d or 0 }
else
return { relPoint = p, point = p, x = b or 0, y = c or 0 }
end
end
-- Common methods repository for statuses
Grid2.statusLibrary = {
IsActive = function()
return true
end,
GetColor = function(self)
local c = self.dbx.color1
return c.r, c.g, c.b, c.a
end,
GetPercent = function(self)
return self.dbx.color1.a
end,
UpdateAllUnits = function(self)
for unit in Grid2:IterateRosterUnits() do
self:UpdateIndicators(unit)
end
end,
GetTexCoord = function()
return 0.05, 0.95, 0.05, 0.95
end,
GetTexCoordZoomed = function()
return 0.08, 0.92, 0.08, 0.92
end,
}
-- Used by bar indicators
Grid2.AlignPoints= {
HORIZONTAL = {
[true] = { "TOPLEFT", "TOPRIGHT", "BOTTOMLEFT", "BOTTOMRIGHT" }, -- normal Fill
[false] = { "BOTTOMRIGHT", "BOTTOMLEFT", "TOPRIGHT", "TOPLEFT" }, -- reverse Fill
},
VERTICAL = {
[true] = { "BOTTOMLEFT","TOPLEFT","BOTTOMRIGHT","TOPRIGHT" }, -- normal Fill
[false] = { "TOPRIGHT", "BOTTOMRIGHT","TOPLEFT","BOTTOMLEFT" }, -- reverse Fill
}
}
-- Create/Manage/Sets frame backdrops
do
local format = string.format
local tostring = tostring
local backdrops = {}
-- Generates a backdrop table, reuses tables avoiding to create duplicates
function Grid2:GetBackdropTable(edgeFile, edgeSize, bgFile, tile, tileSize, inset)
inset = inset or edgeSize
local key = format("%s;%s;%d;%s;%d;%d", bgFile or "", edgeFile or "", edgeSize or -1, tostring(tile), tileSize or -1, inset or -1)
local backdrop = backdrops[key]
if not backdrop then
backdrop = {
bgFile = bgFile,
tile = tile,
tileSize = tileSize,
edgeFile = edgeFile,
edgeSize = edgeSize,
insets = { left = inset, right = inset, top = inset, bottom = inset },
}
backdrops[key] = backdrop
end
return backdrop
end
-- Sets a backdrop only if necessary to alleviate game freezes, see ticket #640
function Grid2:SetFrameBackdrop(frame, backdrop)
if backdrop~=frame.currentBackdrop then
frame:SetBackdrop(backdrop)
frame.currentBackdrop = backdrop
end
end
end
-- Grid2:RunSecure(priority, object, method, arg)
-- Queue some methods to be executed when out of combat, if we are not in combat do nothing.
-- Methods with lower priority value override the execution of methods with higher priority value.
-- Methods executed (in order of priority):
-- ReloadProfile(1), ReloadTheme(2), ReloadLayout(3), ReloadFilter(4), FixRoster(5), UpdateFramesSizeByRaidSize(6), UpdateSize(7), UpdateVisibility(8)
do
local InCombatLockdown = InCombatLockdown
local sec_priority, sec_object, sec_method, sec_arg
function Grid2:PLAYER_REGEN_ENABLED()
if sec_priority then
sec_priority = nil
sec_object[sec_method](sec_object, sec_arg)
end
end
function Grid2:RunSecure(priority, object, method, arg)
if InCombatLockdown() then
if not sec_priority or priority<sec_priority then
sec_priority, sec_object, sec_method, sec_arg = priority, object, method, arg
end
return true
end
end
end
-- Grid2:RunThrottled(object or arg1, method or func, delay)
-- Delays and throttles the execution of a method or function
do
local After = C_Timer.After
local counts = {}
function Grid2:RunThrottled(object, method, delay)
local func = object[method] or method
local count = counts[func]
counts[func] = (count or 0) + 1
if not count then
local callback
callback = function()
if counts[func]>0 then
counts[func] = 0
func(object)
After(delay or 0.1, callback)
else
counts[func] = nil
end
end
After(delay or 0.1, callback)
end
end
end
-- Change default theme, theme = number(theme index starting in 0) or string(theme name)
function Grid2:SetDefaultTheme(theme)
local themes = self.db.profile.themes
if type(theme)~='number' then
for index,name in pairs(themes.names) do
if theme==name then theme = index; break; end
end
if type(theme)~='number' and (theme=='Default' or theme==L['Default']) then
theme = 0
end
end
if theme==0 or themes.names[theme] then
themes.enabled.default = theme
self:ReloadTheme()
return true
end
end
-- Enable or disable profiles per specialization
function Grid2:EnableProfilesPerSpec(enabled)
local db = self.profiles.char
if not enabled ~= not (db[1] and db.enabled) and self.versionCli>=30000 then
wipe(db)
db.enabled = enabled or nil
if enabled then
local pro = self.db:GetCurrentProfile()
for i=1,self.GetNumSpecializations() or 0 do
db[i] = pro
end
end
self:ReloadProfile()
end
end
-- Set a profile for the specified specIndex or the general profile if specIndex==nil
function Grid2:SetProfileForSpec(profileName, specIndex)
if self.db.profiles[profileName] then
if not specIndex then
self.db:SetProfile(profileName)
elseif self.profiles.char[specIndex] then
self.profiles.char[specIndex] = profileName
self:ReloadProfile()
end
end
end
-- MinimapIcon visibility: value = true | false | nil => toggle
function Grid2:SetMinimapIcon(value)
local minimapIcon = Grid2.db.global.minimapIcon or Grid2Layout.db.shared.minimapIcon
if value~='query' then
if value==nil then
minimapIcon.hide = not minimapIcon.hide
else
minimapIcon.hide = not value
end
if minimapIcon.hide then
Grid2Layout.minimapIcon:Hide("Grid2")
else
Grid2Layout.minimapIcon:Show("Grid2")
end
end
return not minimapIcon.hide
end
-- Icons coloring using color curves, used by icon/icons indicators
do
local timer
local icons = {}
local function ApplyColors(icon, r, g, b, a)
if icon.colorCurveText then
icon.colorCurveText:SetTextColor(r, g, b, 1)
end
if icon.colorCurveBar then
icon.colorCurveBar:SetStatusBarColor(r, g, b, a)
end
if icon.colorCurveBorder then
icon:colorCurveBorder(r, g, b, a)
end
end
local function Update()
for icon, durationObject in pairs(icons) do
if icon:IsVisible() then
ApplyColors(icon, durationObject:EvaluateRemainingDuration(icon.colorCurveObject):GetRGBA())
else
icons[icon] = nil
end
end
if not next(icons) then timer:Stop() end
end
timer = Grid2:CreateTimer(Update, 0.2, false)
-- icon must have the fields: icon.colorCurveObject, icon.colorCurveText , icon.colorCurveBorder
function Grid2.UpdateIconColorCurve(icon, durationObject)
local curve = icon.colorCurveObject
if durationObject then
if not timer:IsPlaying() then timer:Play() end
icons[icon] = durationObject
ApplyColors(icon, durationObject:EvaluateRemainingDuration(curve):GetRGBA())
else
ApplyColors(icon, curve:GetPoint(curve:GetPointCount()).y:GetRGBA())
end
end
function Grid2.RemoveIconColorCurve(icon)
icons[icon] = nil
end
end