forked from i2ichardt/HealersMate
-
Notifications
You must be signed in to change notification settings - Fork 0
/
HealUIGroup.lua
359 lines (310 loc) · 12.5 KB
/
HealUIGroup.lua
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
HealUIGroup = {}
HealUIGroup.name = "???"
HealUIGroup.profile = nil
HealUIGroup.container = nil
HealUIGroup.borderFrame = nil
HealUIGroup.header = nil
HealUIGroup.label = nil
HealUIGroup.uis = nil
HealUIGroup.units = nil
HealUIGroup.petGroup = false
HealUIGroup.environment = "all" -- party, raid, or all
HealUIGroup.moveContainer = CreateFrame("Frame", "HealUIGroupBulkMoveContainer", UIParent)
HealUIGroup.moveContainer:EnableMouse(true)
HealUIGroup.moveContainer:SetMovable(true)
-- Singleton references, assigned in constructor
local HM
local util
function HealUIGroup:New(name, environment, units, petGroup, profile)
HM = HealersMate -- Need to do this in the constructor or else it doesn't exist yet
util = HMUtil
local obj = {name = name, environment = environment, uis = {}, units = units, petGroup = petGroup, profile = profile}
setmetatable(obj, self)
self.__index = self
obj:Initialize()
return obj
end
function HealUIGroup:ShowCondition()
for _, ui in pairs(self.uis) do
if ui:IsShown() then
return true
end
end
return false
end
function HealUIGroup:AddUI(ui)
self.uis[ui:GetUnit()] = ui
ui:SetOwningGroup(self)
self:UpdateUIPositions()
end
function HealUIGroup:GetContainer()
return self.container
end
function HealUIGroup:GetEnvironment()
return self.environment
end
function HealUIGroup:CanShowInEnvironment(environment)
return self.environment == "all" or self.environment == environment
end
function HealUIGroup:Show()
self.container:Show()
for _, ui in pairs(self.uis) do
ui:UpdateAll()
end
end
function HealUIGroup:Hide()
self.container:Hide()
end
function HealUIGroup:Initialize()
local container = CreateFrame("Frame", self.name.."HealUIGroupContainer", UIParent) --type, name, parent
self.container = container
container:SetToplevel(true)
container:SetPoint("CENTER", 0, 0) -- position it at the center of the screen
container:SetBackdrop({bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background"}) -- set a light gray background
container:SetBackdropColor(0, 0, 0, 0.5)
container:EnableMouse(true)
container:SetMovable(true)
container:SetScript("OnMouseDown", function()
local button = arg1
if button ~= "LeftButton" or container.isMoving then
return
end
container.isMoving = true
if (util.GetKeyModifier() == HMOptions.FrameDrag.AltMoveKey) == HMOptions.FrameDrag.MoveAll then
container:StartMoving()
return
end
container.bulkMovement = true
local moveContainer = HealUIGroup.moveContainer
moveContainer:ClearAllPoints()
moveContainer:SetPoint("TOPLEFT", 0, 0)
-- If the container doesn't have a size, it doesn't move
moveContainer:SetWidth(1)
moveContainer:SetHeight(1)
for _, group in pairs(HealersMate.HealUIGroups) do
local gc = group:GetContainer()
local point, relativeTo, relativePoint, xofs, yofs = gc:GetPoint(1)
gc:ClearAllPoints()
gc:SetPoint("TOPLEFT", moveContainer, relativePoint, xofs, yofs)
end
moveContainer:StartMoving()
end)
container:SetScript("OnMouseUp", function()
local button = arg1
if (button ~= "LeftButton" or not container.isMoving) then
return
end
container.isMoving = false
if not container.bulkMovement then
container:StopMovingOrSizing()
return
end
container.bulkMovement = false
local moveContainer = HealUIGroup.moveContainer
moveContainer:StopMovingOrSizing()
for _, group in pairs(HealersMate.HealUIGroups) do
local gc = group:GetContainer()
local mcpoint, mcrelativeTo, mcrelativePoint, mcxofs, mcyofs = moveContainer:GetPoint(1)
local point, relativeTo, relativePoint, xofs, yofs = gc:GetPoint(1)
gc:ClearAllPoints()
gc:SetPoint("TOPLEFT", UIParent, mcrelativePoint, mcxofs + xofs, mcyofs + yofs)
end
-- Prevent container from potentially blocking mouse by setting it back to 0 size
moveContainer:SetWidth(0)
moveContainer:SetHeight(0)
end)
container:SetScript("OnHide", function()
if not container.isMoving then
return
end
local prevArg = arg1
arg1 = "LeftButton"
container:GetScript("OnMouseUp")()
arg1 = prevArg
end)
local header = CreateFrame("Frame", self.name.."HealUIGroupContainerHeader", container) --type, name, parent
self.header = header
header:SetPoint("TOPLEFT", container, 0, 0)
header:SetBackdrop({bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background"})
header:SetBackdropColor(0, 0, 0, 0.5)
local borderFrame = CreateFrame("Frame", self.name.."HealUIGroupContainerBorder", container)
self.borderFrame = borderFrame
borderFrame:SetPoint("CENTER", container, 0, 0)
local label = header:CreateFontString(header, "OVERLAY", "GameFontNormal")
self.label = label
label:SetPoint("CENTER", header, "CENTER", 0, 0)
label:SetText(self.name)
self:ApplyProfile()
self:UpdateUIPositions()
end
function HealUIGroup:ApplyProfile()
local profile = self:GetProfile()
local borderFrame = self.borderFrame
if profile.BorderStyle == "Tooltip" then
borderFrame:SetBackdrop({edgeFile="Interface\\Tooltips\\UI-Tooltip-Border", edgeSize = 16,
insets = { left = 6, right = 6, top = 6, bottom = 6 }, tile = true, tileSize = 16})
elseif profile.BorderStyle == "Dialog Box" then
borderFrame:SetBackdrop({edgeFile="Interface\\DialogFrame\\UI-DialogBox-Border", edgeSize = 24,
insets = { left = 8, right = 8, top = 8, bottom = 8 }, tile = true, tileSize = 24})
else
borderFrame:SetBackdrop({})
end
end
function HealUIGroup:UpdateUIPositions()
local profile = self:GetProfile()
local profileWidth = profile.Width
local profileHeight = profile:GetHeight()
local maxUnitsInAxis = profile.MaxUnitsInAxis
local orientation = profile.Orientation
local sortedUIs = self:GetSortedUIs()
local splitSortedUIs = {}
for _, group in ipairs(sortedUIs) do
local currentTable = {}
local unitsUntilShift = maxUnitsInAxis
for _, ui in ipairs(group) do
if unitsUntilShift == 0 then
table.insert(splitSortedUIs, currentTable)
currentTable = {}
unitsUntilShift = maxUnitsInAxis
end
table.insert(currentTable, ui)
unitsUntilShift = unitsUntilShift - 1
end
if table.getn(currentTable) > 0 then
table.insert(splitSortedUIs, currentTable)
end
end
-- IMPORTANT: "Column" does not necessarily mean vertical!
local largestColumn = 0
for _, column in ipairs(splitSortedUIs) do
largestColumn = math.max(largestColumn, table.getn(column))
end
for columnIndex, column in ipairs(splitSortedUIs) do
for i, ui in ipairs(column) do -- Column is guaranteed to be less than max units
local container = ui:GetRootContainer()
local x = orientation == "Vertical" and (profileWidth * (columnIndex - 1)) or (profileWidth * (i - 1))
local y = orientation == "Vertical" and (profileHeight * (i - 1)) or (profileHeight * (columnIndex - 1))
container:SetPoint("TOPLEFT", self.container, "TOPLEFT", x, -y - 20)
end
end
local width = orientation == "Vertical" and (profileWidth * table.getn(splitSortedUIs)) or (profileWidth * largestColumn)
local height = orientation == "Vertical" and (profileHeight * largestColumn) or (profileHeight * table.getn(splitSortedUIs))
height = height + 20
self.container:SetWidth(width)
self.container:SetHeight(height)
local header = self.header
header:SetWidth(width)
header:SetHeight(20)
local borderPadding = 0
if profile.BorderStyle == "Tooltip" then
borderPadding = 10
elseif profile.BorderStyle == "Dialog Box" then
borderPadding = 18
end
self.borderFrame:SetWidth(width + borderPadding)
self.borderFrame:SetHeight(height + borderPadding)
local label = self.label
label:SetPoint("CENTER", header, "CENTER", 0, 0)
end
-- Returns an array with the index being the group number, and the value being an array of units
function HealUIGroup:GetSortedUIs()
local profile = self:GetProfile()
local uis = self.uis
local groups = {}
if self.environment == "raid" and profile.SplitRaidIntoGroups and not self.petGroup then
local foundRaidNumbers = {} -- Used for testing UI
for i = 1, 8 do
groups[i] = {}
local group = groups[i]
if RAID_SUBGROUP_LISTS then
for frameNumber, raidNumber in pairs(RAID_SUBGROUP_LISTS[i]) do
table.insert(group, uis["raid"..raidNumber]) -- Effectively sorts raid members by ID at this point
foundRaidNumbers[raidNumber] = 1
end
end
end
-- If testing, fill empty slots with fake players
if HealersMate.TestUI and RAID_SUBGROUP_LISTS then
local unoccupied = {}
for i = 1, 40 do
if not foundRaidNumbers[i] then
table.insert(unoccupied, i)
end
end
for i = 1, 8 do
local group = groups[i]
for frameNumber = 1, 5 do
if not RAID_SUBGROUP_LISTS[i][frameNumber] then
table.insert(group, uis["raid"..table.remove(unoccupied, table.getn(unoccupied))])
end
end
end
end
else
groups[1] = {}
local group = groups[1]
for _, ui in pairs(uis) do
if ui:IsShown() then
table.insert(group, ui)
end
end
end
local sortedGroups = {}
if profile.SortUnitsBy == "ID" then
for groupNumber, group in ipairs(groups) do
if table.getn(group) > 0 then
local groupSet = {} -- Convert group UI array to a set with the key as the Unit ID
for _, ui in ipairs(group) do
groupSet[ui:GetUnit()] = ui
end
if self.environment == "raid" then
if not self.petGroup then -- Should already be sorted if we're not dealing with the pets
table.insert(sortedGroups, group)
else -- Pets need to be sorted manually
local sortedGroup = {}
for _, unit in ipairs(self.units) do -- Iterate through all unit IDs this UI group can handle, in order
if groupSet[unit] then
table.insert(sortedGroup, groupSet[unit])
end
end
table.insert(sortedGroups, sortedGroup)
end
else
local sortedGroup = {}
for _, unit in ipairs(self.units) do -- Iterate through all unit IDs this UI group can handle, in order
if groupSet[unit] then
table.insert(sortedGroup, groupSet[unit])
end
end
table.insert(sortedGroups, sortedGroup)
end
end
end
elseif profile.SortUnitsBy == "Name" then
for groupNumber, group in ipairs(groups) do
if table.getn(group) > 0 then
table.sort(group, function(a, b)
local aName = UnitName(a:GetUnit()) or a:GetUnit()
local bName = UnitName(b:GetUnit()) or b:GetUnit()
return aName < bName
end)
table.insert(sortedGroups, group)
end
end
elseif profile.SortUnitsBy == "Class Name" then
for groupNumber, group in ipairs(groups) do
if table.getn(group) > 0 then
table.sort(group, function(a, b)
local aName = HM.GetClass(a:GetUnit()) or a.testClass
local bName = HM.GetClass(b:GetUnit()) or b.testClass
return aName < bName
end)
table.insert(sortedGroups, group)
end
end
end
return sortedGroups
end
function HealUIGroup:GetProfile()
return self.profile
end