Back to Home

ESO Lua File v100036

pregameandingame/zo_addonmanager/zo_addonmanager.lua

[◄ back to folders ]
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
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
local LIST_HEIGHT = 660
ZO_ADDON_ROW_HEIGHT = 30
ZO_ADDON_SECTION_HEADER_ROW_HEIGHT = 50
local ADDON_DATA = 1
local SECTION_HEADER_DATA = 2
local IS_LIBRARY = true
local IS_ADDON = false
local AddOnManager = GetAddOnManager()
ZO_AddOnManager = ZO_SortFilterList:Subclass()
function ZO_AddOnManager:New(...)
    local control = CreateControlFromVirtual("ZO_AddOns", GuiRoot, "ZO_AddOnManagerTemplate")
    return ZO_SortFilterList.New(self, control, ...)
end
function ZO_AddOnManager:Initialize(control, allowReload)
    ZO_SortFilterList.Initialize(self, control, allowReload)
    self.allowReload = allowReload
    self.control:SetHandler("OnShow", function() self:OnShow() end)
    self.sizerLabel = CreateControlFromVirtual("", self.control, "ZO_AddOn_SizerLabel")
    self.currentSortKey = "strippedAddOnName"
    self.currentSortDirection = ZO_SORT_ORDER_UP
    self.sortKeys =
    {
        addOnFileName = { },
        strippedAddOnName = { tiebreaker = "addOnFileName" },
    }
    self.sortCallback = function(entry1, entry2)
        return ZO_TableOrderingFunction(entry1, entry2, self.currentSortKey, self.sortKeys, self.currentSortDirection)
    end
    ZO_ScrollList_SetHeight(self.list, LIST_HEIGHT)
    ZO_ScrollList_AddDataType(self.list, ADDON_DATA, "ZO_AddOnRow", ZO_ADDON_ROW_HEIGHT, self:GetRowSetupFunction())
    ZO_ScrollList_AddDataType(self.list, SECTION_HEADER_DATA, "ZO_AddOnSectionHeaderRow", ZO_ADDON_SECTION_HEADER_ROW_HEIGHT, function(...) self:SetupSectionHeaderRow(...) end)
    self.characterDropdown = ZO_ComboBox:New(GetControl(self.control, "CharacterSelectDropdown"))
    self.characterDropdown:SetSortsItems(false)
    local function OnAddOnEulaHidden()
        local hasAgreed = HasAgreedToEULA(EULA_TYPE_ADDON_EULA)
        self.characterDropdown:SetEnabled(hasAgreed)
        self.isDirty = true
        self:RefreshMultiButton()
        self:RefreshData()
    end
    CALLBACK_MANAGER:RegisterCallback("AddOnEULAHidden", OnAddOnEulaHidden)
    ADDONS_FRAGMENT = ZO_FadeSceneFragment:New(self.control)
    ADDONS_FRAGMENT:RegisterCallback("StateChange",   function(oldState, newState)
                                                if(newState == SCENE_FRAGMENT_SHOWING) then
                                                    PushActionLayerByName("Addons")
                                                elseif(newState == SCENE_FRAGMENT_HIDING) then
                                                    RemoveActionLayerByName("Addons")
                                                end
                                            end)
    --Uses a namespace event registration because ZO_ReanchorControlForLeftSidePanel registers EVENT_SCREEN_RESIZED on the control
    EVENT_MANAGER:RegisterForEvent("AddOnManager", EVENT_SCREEN_RESIZED, function() self:RefreshData() end)
end
local function GetCharacterNameFromDatum(datum)
    return zo_strformat(SI_UNIT_NAME, datum.name)
end
local g_uniqueNamesByCharacterName = {}
local function CreateAddOnFilter(characterName)
    local uniqueName = g_uniqueNamesByCharacterName[characterName]
    if not uniqueName then
        uniqueName = GetUniqueNameForCharacter(characterName)
        g_uniqueNamesByCharacterName[characterName] = uniqueName
    end
    return uniqueName
end
local COMBINED_STATE_RESULT_NO_DEP_ERRORS = 1
local COMBINED_STATE_RESULT_SOME_DEP_ERRORS = 2
local COMBINED_STATE_RESULT_ALL_DEP_ERRORS = 3
function ZO_AddOnManager:GetRowSetupFunction()
    local function SetSimpleTriStateCheckButton(enabled, data)
        if data.addOnEnabled then
            ZO_TriStateCheckButton_SetState(enabled, TRISTATE_CHECK_BUTTON_CHECKED)
        else
            ZO_TriStateCheckButton_SetState(enabled, TRISTATE_CHECK_BUTTON_UNCHECKED)
        end
    end
    local function SetupNotes(state, data)
        local stateText = ""
        if data.isOutOfDate then
            stateText = GetString("SI_ADDONLOADSTATE", ADDON_STATE_VERSION_MISMATCH)
        end
        if not self.isAllFilterSelected then
            if data.hasDependencyError then
                if stateText == "" then
                    stateText = ZO_ERROR_COLOR:Colorize(GetString("SI_ADDONLOADSTATE", ADDON_STATE_DEPENDENCIES_DISABLED))
                else
                    stateText = zo_strformat(SI_ADDON_MANAGER_STATE_STRING, stateText, ZO_ERROR_COLOR:Colorize(GetString("SI_ADDONLOADSTATE", ADDON_STATE_DEPENDENCIES_DISABLED)))
                end
            end
        end
        state:SetText(stateText)
    end
    local function UpdateNameAndAuthor(control, isEnabled, data)
        local checkboxControl = GetControl(control, "Enabled")
        local checkState = ZO_TriStateCheckButton_GetState(checkboxControl)
        local nameControl = GetControl(control, "Name")
        local authorControl = GetControl(control, "Author")
        local color
        local stripColorMarkup
        if not isEnabled then
            color = ZO_ERROR_COLOR
            stripColorMarkup = true
        elseif checkState == TRISTATE_CHECK_BUTTON_UNCHECKED then
            color = ZO_DEFAULT_DISABLED_COLOR
            stripColorMarkup = true
        else
            color = ZO_DEFAULT_ENABLED_COLOR
            stripColorMarkup = false
        end
        nameControl:SetColor(color:UnpackRGBA())
        authorControl:SetColor(color:UnpackRGBA())
        nameControl:SetText(stripColorMarkup and data.strippedAddOnName or data.addOnName)
        local authorByLine = stripColorMarkup and data.strippedAddOnAuthorByLine or data.addOnAuthorByLine
        authorControl:SetText(authorByLine)
    end
    return function(control, data)
        control.owner = self
        control.data = data
        local name = control:GetNamedChild("Name")
        local enabledControl = control:GetNamedChild("Enabled") 
        local state = control:GetNamedChild("State") 
        local description = control:GetNamedChild("Description") 
        local dependencies = control:GetNamedChild("Dependencies") 
        local expandButton = control:GetNamedChild("ExpandButton")
        control:SetHeight(data.height)
        expandButton:SetHidden(not data.expandable)
        if data.expandable then
            ZO_ToggleButton_SetState(expandButton, data.expanded and TOGGLE_BUTTON_OPEN or TOGGLE_BUTTON_CLOSED)
        end
        local showDescription = data.expanded and data.addOnDescription ~= ""
        description:SetHidden(not showDescription)
        description:ClearAnchors()
        if showDescription then
            description:SetText(data.addOnDescription)
            description:SetAnchor(TOPLEFT, name, BOTTOMLEFT, 20, 18)
        else
            description:SetText("")
            description:SetAnchor(TOPLEFT, name, BOTTOMLEFT, 20, 0)
        end
        local showDependencies = data.expanded and data.addOnDependencyText ~= ""
        dependencies:SetHidden(not showDependencies)
        if showDependencies then
            dependencies:SetText(GetString(SI_ADDON_MANAGER_DEPENDENCIES)..data.addOnDependencyText)
        else
            dependencies:SetText("")
        end
        local isEnabled = HasAgreedToEULA(EULA_TYPE_ADDON_EULA)
        if self.isAllFilterSelected then
            local allEnabled, allDisabled
            allEnabled, allDisabled = self:GetCombinedAddOnStates(data.index)
            if allEnabled then
                ZO_TriStateCheckButton_SetState(enabledControl, TRISTATE_CHECK_BUTTON_CHECKED)
            elseif allDisabled then
                ZO_TriStateCheckButton_SetState(enabledControl, TRISTATE_CHECK_BUTTON_UNCHECKED)
            else
                ZO_TriStateCheckButton_SetState(enabledControl, TRISTATE_CHECK_BUTTON_INDETERMINATE)
            end
            enabledControl:SetHidden(not isEnabled)
        else
            SetSimpleTriStateCheckButton(enabledControl, data)
            isEnabled = isEnabled and not data.hasDependencyError
            enabledControl:SetHidden(not isEnabled)
        end
        UpdateNameAndAuthor(control, isEnabled, data)
        ZO_TriStateCheckButton_SetStateChangeFunction(enabledControl, function(control, checkState) self:OnEnabledButtonClicked(control, checkState) end)
        SetupNotes(state, data)
    end
end
function ZO_AddOnManager:SetupSectionHeaderRow(control, data)
end
function ZO_AddOnManager:GetCombinedAddOnStates(index)
    local allEnabled = true
    local allDisabled = true
    local combinedStateResult = nil
    if self.isAllFilterSelected and self.characterData then
        for i, dataEntry in ipairs(self.characterData) do
            local datum = dataEntry.data
            local filter = CreateAddOnFilter(datum.name)
            AddOnManager:SetAddOnFilter(filter)
            local enabled, state = select(5, AddOnManager:GetAddOnInfo(index))
            if enabled then
                allDisabled = false
            else
                allEnabled = false
            end
            if combinedStateResult == nil then
                if state == ADDON_STATE_DEPENDENCIES_DISABLED then
                    combinedStateResult = COMBINED_STATE_RESULT_ALL_DEP_ERRORS
                else
                    combinedStateResult = COMBINED_STATE_RESULT_NO_DEP_ERRORS
                end
            else
                if state == ADDON_STATE_DEPENDENCIES_DISABLED then
                    if combinedStateResult == COMBINED_STATE_RESULT_NO_DEP_ERRORS then
                        combinedStateResult = COMBINED_STATE_RESULT_SOME_DEP_ERRORS
                    end
                else
                    if combinedStateResult == COMBINED_STATE_RESULT_ALL_DEP_ERRORS then
                        combinedStateResult = COMBINED_STATE_RESULT_SOME_DEP_ERRORS
                    end
                end
            end
        end
        AddOnManager:RemoveAddOnFilter()
    end
    return allEnabled, allDisabled, combinedStateResult or COMBINED_STATE_RESULT_NO_DEP_ERRORS
end
function ZO_AddOnManager:SetCharacterData(characterData)
    self.characterData = characterData
    AddOnManager:ResetRelevantFilters()
    if self.characterData then
        for i, dataEntry in ipairs(self.characterData) do
            local datum = dataEntry.data
            AddOnManager:AddRelevantFilter(CreateAddOnFilter(datum.name))
        end
    end
end
function ZO_AddOnManager:GetNumCharacters()
    if self.characterData then
        return #self.characterData
    end
    return 0
end
function ZO_AddOnManager:GetCharacterInfo(characterIndex)
    if self.characterData then
        local characterDataEntry = self.characterData[characterIndex]
        local characterDatum = characterDataEntry.data
        return characterDatum and GetCharacterNameFromDatum(characterDatum) or nil
    end
end
function ZO_AddOnManager:OnCharacterChanged(name, entry)
    self.selectedCharacterEntry = entry
    self:RefreshData()
end
function ZO_AddOnManager:BuildCharacterDropdown()
    self.characterDropdown:ClearItems()
    local function OnCharacterChanged(comboBox, name, entry)
        self:OnCharacterChanged(name, entry)
    end
    if self.characterData then
        self.characterDropdown:GetContainer():SetHidden(false)
        local allCharactersEntry = self.characterDropdown:CreateItemEntry(GetString(SI_ADDON_MANAGER_CHARACTER_SELECT_ALL), OnCharacterChanged)
        allCharactersEntry.allCharacters = true
        self.characterDropdown:AddItem(allCharactersEntry)
        local characterNames = {}
        for i=1, self:GetNumCharacters() do
            local name = self:GetCharacterInfo(i)
            table.insert(characterNames, name)
        end
        table.sort(characterNames)
        for _, characterName in ipairs(characterNames) do
            local entry = self.characterDropdown:CreateItemEntry(characterName, OnCharacterChanged)
            entry.allCharacters = false
            self.characterDropdown:AddItem(entry)
        end
        self.characterDropdown:SelectFirstItem()
    else
        self.characterDropdown:GetContainer():SetHidden(true)
        local playerName = GetUnitName("player")
        self.selectedCharacterEntry = { name = playerName ~= "" and playerName or nil, allCharacters = false }
        self.isAllFilterSelected = false
    end
end
function ZO_AddOnManager:ChangeEnabledState(index, checkState)
    AddOnManager:SetAddOnEnabled(index, checkState == TRISTATE_CHECK_BUTTON_CHECKED)
    self:RefreshData()
end
local expandedAddons = {}
local heightIds = {}
local g_currentTypeId = 2
local function GetHeightTypeId(height)
    if heightIds[height] then
        return heightIds[height]
    else
        heightIds[height] = g_currentTypeId
        g_currentTypeId = g_currentTypeId + 1
        return heightIds[height]
    end
end
function ZO_AddOnManager:SetupTypeId(description, dependencyText)
    local descriptionHeight = 0
    if description ~= "" then
        self.sizerLabel:SetText(description)
        descriptionHeight = self.sizerLabel:GetTextHeight() + 18
    end
    local dependencyHeight = 0
    if dependencyText ~= "" then
        self.sizerLabel:SetText(dependencyText)
        dependencyHeight = self.sizerLabel:GetTextHeight() + 23
    end
    local useHeight = zo_ceil(ZO_ADDON_ROW_HEIGHT + descriptionHeight + dependencyHeight + 31)
    local typeId = GetHeightTypeId(useHeight)
    local existingDataTypeTable = ZO_ScrollList_GetDataTypeTable(self.list, typeId)
    if not existingDataTypeTable then
        ZO_ScrollList_AddDataType(self.list, typeId, "ZO_AddOnRow", useHeight, self:GetRowSetupFunction())
    else
        existingDataTypeTable.height = useHeight
    end
    return useHeight, typeId
end
function ZO_AddOnManager:ResetDataTypes()
    g_currentTypeId = 3
    heightIds = {}
end
local function StripText(text)
    return text:gsub("|c%x%x%x%x%x%x", "")
end
function ZO_AddOnManager:BuildMasterList()
    self.addonTypes = {}
    self.addonTypes[IS_LIBRARY] = {}
    self.addonTypes[IS_ADDON] = {}
    if self.selectedCharacterEntry and not self.selectedCharacterEntry.allCharacters then
        self.isAllFilterSelected = false
        AddOnManager:SetAddOnFilter(CreateAddOnFilter(self.selectedCharacterEntry.name))
    else
        self.isAllFilterSelected = true
        AddOnManager:RemoveAddOnFilter()
    end
    for i = 1, AddOnManager:GetNumAddOns() do
        local name, title, author, description, enabled, state, isOutOfDate, isLibrary = AddOnManager:GetAddOnInfo(i)
        local entryData = {
            index = i,
            addOnFileName = name,
            addOnName = title,
            strippedAddOnName = StripText(title),
            addOnDescription = description,
            addOnEnabled = enabled,
            addOnState = state,
            isOutOfDate = isOutOfDate,
            isLibrary = isLibrary,
        }
        if author ~= "" then
            local strippedAuthor = StripText(author)
            entryData.addOnAuthorByLine = zo_strformat(SI_ADD_ON_AUTHOR_LINE, author)
            entryData.strippedAddOnAuthorByLine = zo_strformat(SI_ADD_ON_AUTHOR_LINE, strippedAuthor)
        else
            entryData.addOnAuthorByLine = ""
            entryData.strippedAddOnAuthorByLine = ""
        end
        local dependencyText = ""
        for j = 1, AddOnManager:GetAddOnNumDependencies(i) do
            local dependencyName, dependencyExists, dependencyActive, dependencyMinVersion, dependencyVersion = AddOnManager:GetAddOnDependencyInfo(i, j)
            local dependencyTooLowVersion = dependencyVersion < dependencyMinVersion
            local dependencyInfoLine = dependencyName
            if not self.isAllFilterSelected and (not dependencyActive or not dependencyExists or dependencyTooLowVersion) then
                entryData.hasDependencyError = true
                if not dependencyExists then
                    dependencyInfoLine = zo_strformat(SI_ADDON_MANAGER_DEPENDENCY_MISSING, dependencyName)
                elseif not dependencyActive then
                    dependencyInfoLine = zo_strformat(SI_ADDON_MANAGER_DEPENDENCY_DISABLED, dependencyName)
                elseif dependencyTooLowVersion then
                    dependencyInfoLine = zo_strformat(SI_ADDON_MANAGER_DEPENDENCY_TOO_LOW_VERSION, dependencyName)
                end
                dependencyInfoLine = ZO_ERROR_COLOR:Colorize(dependencyInfoLine)
            end
            dependencyText = string.format("%s\n %s %s", dependencyText, GetString(SI_BULLET), dependencyInfoLine)
        end
        entryData.addOnDependencyText = dependencyText
        entryData.expandable = (description ~= "") or (dependencyText ~= "")
        
        table.insert(self.addonTypes[isLibrary], entryData)
    end
end
function ZO_AddOnManager:AddAddonTypeSection(isLibrary, sectionTitleText)
    local addonEntries = self.addonTypes[isLibrary]
    table.sort(addonEntries, self.sortCallback)
    local scrollData = ZO_ScrollList_GetDataList(self.list)
    scrollData[#scrollData + 1] = ZO_ScrollList_CreateDataEntry(SECTION_HEADER_DATA, { text = sectionTitleText })
    for _, entryData in ipairs(addonEntries) do
        if entryData.expandable and expandedAddons[entryData.index] then
            entryData.expanded = true
            local useHeight, typeId = self:SetupTypeId(entryData.addOnDescription, entryData.addOnDependencyText)
            entryData.height = useHeight
            scrollData[#scrollData + 1] = ZO_ScrollList_CreateDataEntry(typeId, entryData)
        else
            entryData.height = ZO_ADDON_ROW_HEIGHT
            scrollData[#scrollData + 1] = ZO_ScrollList_CreateDataEntry(ADDON_DATA, entryData)
        end
    end
end
function ZO_AddOnManager:SortScrollList()
    self:ResetDataTypes()
    local scrollData = ZO_ScrollList_GetDataList(self.list)        
    ZO_ClearNumericallyIndexedTable(scrollData)
    self:AddAddonTypeSection(IS_ADDON, GetString(SI_WINDOW_TITLE_ADDON_MANAGER))
    self:AddAddonTypeSection(IS_LIBRARY, GetString(SI_ADDON_MANAGER_SECTION_LIBRARIES))
end
function ZO_AddOnManager:OnShow()
    self:RefreshData()
    CALLBACK_MANAGER:FireCallbacks("ShowAddOnEULAIfNecessary")
end
function ZO_AddOnManager:RefreshMultiButton()
    local multiButton = self.control:GetNamedChild("MultiButton")
    if(HasAgreedToEULA(EULA_TYPE_ADDON_EULA)) then
        local isShown = self:AllowReload()
        multiButton:SetHidden(not isShown)
        multiButton:SetText(GetString(SI_ADDON_MANAGER_RELOAD))
    else
        multiButton:SetHidden(false)
        multiButton:SetText(GetString(SI_ADDON_MANAGER_VIEW_EULA))
    end
end
function ZO_AddOnManager:OnMouseEnter(control)
    if self.isAllFilterSelected then
        InitializeTooltip(InformationTooltip, control, TOPLEFT, 0, 0, BOTTOMRIGHT)
        local state = ZO_TriStateCheckButton_GetState(control)
        if state == TRISTATE_CHECK_BUTTON_CHECKED then
            SetTooltipText(InformationTooltip, GetString(SI_ADDON_MANAGER_TOOLTIP_ENABLED_ALL))
        elseif state == TRISTATE_CHECK_BUTTON_UNCHECKED then
            SetTooltipText(InformationTooltip, GetString(SI_ADDON_MANAGER_TOOLTIP_ENABLED_NONE))
        elseif state == TRISTATE_CHECK_BUTTON_INDETERMINATE then
            SetTooltipText(InformationTooltip, GetString(SI_ADDON_MANAGER_TOOLTIP_ENABLED_SOME))
        end
    end
end
function ZO_AddOnManager:OnEnabledButtonClicked(control, checkState)
    local row = control:GetParent()
    self:ChangeEnabledState(row.data.index, checkState)
    self.isDirty = true
end
function ZO_AddOnManager:OnExpandButtonClicked(row)
    local scrollData = ZO_ScrollList_GetDataList(self.list)
    local data = ZO_ScrollList_GetData(row)
    if expandedAddons[data.index] then
        expandedAddons[data.index] = false
        data.expanded = false
        data.height = ZO_ADDON_ROW_HEIGHT
        scrollData[data.sortIndex] = ZO_ScrollList_CreateDataEntry(ADDON_DATA, data)
    else
        expandedAddons[data.index] = true
        local useHeight, typeId = self:SetupTypeId(data.addOnDescription, data.addOnDependencyText)
        data.expanded = true
        data.height = useHeight
        scrollData[data.sortIndex] = ZO_ScrollList_CreateDataEntry(typeId, data)
    end
end
function ZO_AddOnManager:AllowReload()
    return (self.allowReload and self.isDirty)
end
    local row = control:GetParent()
    row.owner:OnExpandButtonClicked(row)
end
    local row = control:GetParent()
    row.owner:OnMouseEnter(control)
end
    if(HasAgreedToEULA(EULA_TYPE_ADDON_EULA)) then
        if ADD_ON_MANAGER:AllowReload() then
            ReloadUI("ingame")
        end
    else
        CALLBACK_MANAGER:FireCallbacks("ShowAddOnEULAIfNecessary")
    end
end