Skip to content

Commit 7f182d6

Browse files
committed
add option to import compared builds from local build folder
1 parent a837359 commit 7f182d6

3 files changed

Lines changed: 253 additions & 123 deletions

File tree

src/Classes/CompareTab.lua

Lines changed: 107 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ local dkjson = require "dkjson"
1313
local tradeHelpers = LoadModule("Classes/CompareTradeHelpers")
1414
local buySimilar = LoadModule("Classes/CompareBuySimilar")
1515
local calcsHelpers = LoadModule("Classes/CompareCalcsHelpers")
16+
local buildListHelpers = LoadModule("Modules/BuildListHelpers")
1617

1718
-- Node IDs below this value are normal passive tree nodes; IDs at or above are cluster jewel nodes
1819
local CLUSTER_NODE_OFFSET = 65536
@@ -183,11 +184,6 @@ function CompareTabClass:InitControls()
183184
end
184185
end
185186

186-
-- Notes sub-tab controls
187-
self.controls.notesDesc = new("LabelControl", nil, {0, 0, 0, 16}, "^7These are the notes from the compared build. Any edits here are saved with this comparison and do not affect the main build's notes.")
188-
self.controls.notesDesc.shown = function()
189-
return self.compareViewMode == "NOTES" and #self.compareEntries > 0
190-
end
191187
self.controls.notesEdit = new("EditControl", nil, {0, 0, 0, 0}, "", nil, "^%C\t\n", nil, nil, 16, true)
192188
self.controls.notesEdit.shown = function()
193189
return self.compareViewMode == "NOTES" and #self.compareEntries > 0
@@ -1396,7 +1392,7 @@ function CompareTabClass:OpenImportPopup()
13961392
controls.state.label = function()
13971393
return stateText or ""
13981394
end
1399-
controls.go = new("ButtonControl", nil, {-45, 130, 80, 20}, "Import", function()
1395+
controls.go = new("ButtonControl", nil, {-118, 130, 80, 20}, "Import", function()
14001396
local buf = controls.input.buf
14011397
if not buf or buf == "" then
14021398
return
@@ -1433,12 +1429,115 @@ function CompareTabClass:OpenImportPopup()
14331429
stateText = colorCodes.NEGATIVE .. "Invalid build code"
14341430
end
14351431
end)
1436-
controls.cancel = new("ButtonControl", nil, {45, 130, 80, 20}, "Cancel", function()
1432+
controls.importFolder = new("ButtonControl", nil, {0, 130, 140, 20}, "Import from Folder", function()
1433+
main:ClosePopup()
1434+
self:OpenImportFolderPopup()
1435+
end)
1436+
controls.cancel = new("ButtonControl", nil, {118, 130, 80, 20}, "Cancel", function()
14371437
main:ClosePopup()
14381438
end)
14391439
main:OpenPopup(500, 160, "Import Comparison Build", controls, "go", "input", "cancel")
14401440
end
14411441

1442+
-- Open the "Import from Folder" popup: browse the user's local builds folder and
1443+
-- import the selected build file as a comparison.
1444+
function CompareTabClass:OpenImportFolderPopup()
1445+
local controls = {}
1446+
local searchText = ""
1447+
local sortMode = main.buildSortMode
1448+
1449+
-- Minimal listMode-like host consumed by BuildListControl/PathControl.
1450+
local listHost = {
1451+
subPath = "",
1452+
list = { },
1453+
controls = { },
1454+
}
1455+
function listHost:BuildList()
1456+
wipeTable(self.list)
1457+
local scanned = buildListHelpers.ScanFolder(self.subPath, searchText)
1458+
for _, entry in ipairs(scanned) do
1459+
t_insert(self.list, entry)
1460+
end
1461+
buildListHelpers.SortList(self.list, sortMode)
1462+
end
1463+
function listHost:SelectControl(control)
1464+
-- Focus is managed by the popup's ControlHost; this is a no-op for the popup list.
1465+
end
1466+
1467+
-- Import the given build entry (xml file on disk) as a comparison.
1468+
local function importBuildEntry(build)
1469+
local fileHnd = io.open(build.fullFileName, "r")
1470+
if not fileHnd then
1471+
main:OpenMessagePopup("Import Error", "Couldn't open '"..build.fullFileName.."'.")
1472+
return
1473+
end
1474+
local xmlText = fileHnd:read("*a")
1475+
fileHnd:close()
1476+
if not xmlText or xmlText == "" then
1477+
main:OpenMessagePopup("Import Error", "Build file is empty or unreadable.")
1478+
return
1479+
end
1480+
if self:ImportBuild(xmlText, build.buildName) then
1481+
main:ClosePopup()
1482+
else
1483+
main:OpenMessagePopup("Import Error", "Failed to import build for comparison.")
1484+
end
1485+
end
1486+
1487+
-- Search box and sort dropdown sit above the build list.
1488+
controls.searchText = new("EditControl", {"TOPLEFT", nil, "TOPLEFT"}, {15, 25, 450, 20}, "", "Search", "%c%(%)", 100, function(buf)
1489+
searchText = buf
1490+
listHost:BuildList()
1491+
end, nil, nil, true)
1492+
controls.sort = new("DropDownControl", {"TOPLEFT", nil, "TOPLEFT"}, {475, 25, 210, 20}, buildListHelpers.buildSortDropList, function(index, value)
1493+
sortMode = value.sortMode
1494+
main.buildSortMode = value.sortMode
1495+
buildListHelpers.SortList(listHost.list, sortMode)
1496+
end)
1497+
controls.sort:SelByValue(sortMode, "sortMode")
1498+
1499+
-- Build list itself. Reuses BuildListControl (which provides the PathControl breadcrumbs)
1500+
controls.buildList = new("BuildListControl", {"TOPLEFT", nil, "TOPLEFT"}, {15, 75, 0, 0}, listHost)
1501+
controls.buildList.width = function() return 670 end
1502+
controls.buildList.height = function() return 355 end
1503+
1504+
-- Override instance methods on the BuildListControl to tailor it for the popup:
1505+
-- navigate folders, import builds, and suppress rename/delete/drag behaviors.
1506+
function controls.buildList:LoadBuild(build)
1507+
if build.folderName then
1508+
self.controls.path:SetSubPath(self.listMode.subPath .. build.folderName .. "/")
1509+
else
1510+
importBuildEntry(build)
1511+
end
1512+
end
1513+
function controls.buildList:OnSelKeyDown(index, build, key)
1514+
if key == "RETURN" then
1515+
self:LoadBuild(build)
1516+
end
1517+
end
1518+
function controls.buildList:CanReceiveDrag() return false end
1519+
function controls.buildList:OnSelCopy() end
1520+
function controls.buildList:OnSelCut() end
1521+
function controls.buildList:OnSelDelete() end
1522+
function controls.buildList.controls.path:CanReceiveDrag() return false end
1523+
1524+
-- Populate the initial list now that the control (and its path control) exist.
1525+
listHost:BuildList()
1526+
1527+
controls.open = new("ButtonControl", {"TOPLEFT", nil, "TOPLEFT"}, {255, 465, 80, 20}, "Open", function()
1528+
local sel = controls.buildList.selValue
1529+
if sel then
1530+
controls.buildList:LoadBuild(sel)
1531+
end
1532+
end)
1533+
controls.open.enabled = function() return controls.buildList.selValue ~= nil end
1534+
controls.close = new("ButtonControl", {"TOPLEFT", nil, "TOPLEFT"}, {365, 465, 80, 20}, "Close", function()
1535+
main:ClosePopup()
1536+
end)
1537+
1538+
main:OpenPopup(700, 500, "Import from Folder", controls, "open", "searchText", "close")
1539+
end
1540+
14421541
-- ============================================================
14431542
-- DRAW - Main render method
14441543
-- ============================================================
@@ -4364,13 +4463,8 @@ function CompareTabClass:DrawNotes(vp, compareEntry, inputEvents)
43644463
end
43654464
end
43664465

4367-
-- Position label and edit control
4368-
self.controls.notesDesc.x = vp.x + 8
4369-
self.controls.notesDesc.y = vp.y + 8
4370-
4371-
local editY = vp.y + 30
43724466
self.controls.notesEdit.x = vp.x + 8
4373-
self.controls.notesEdit.y = editY
4467+
self.controls.notesEdit.y = vp.y + 8
43744468
self.controls.notesEdit.width = function()
43754469
return vp.width - 16
43764470
end

src/Modules/BuildList.lua

Lines changed: 6 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,8 @@ local pairs = pairs
77
local ipairs = ipairs
88
local t_insert = table.insert
99

10-
local buildSortDropList = {
11-
{ label = "Sort by Name", sortMode = "NAME" },
12-
{ label = "Sort by Class", sortMode = "CLASS" },
13-
{ label = "Sort by Last Edited", sortMode = "EDITED"},
14-
{ label = "Sort by Level", sortMode = "LEVEL"},
15-
}
10+
local buildListHelpers = LoadModule("Modules/BuildListHelpers")
11+
local buildSortDropList = buildListHelpers.buildSortDropList
1612

1713
local listMode = new("ControlHost")
1814

@@ -197,116 +193,16 @@ end
197193

198194
function listMode:BuildList()
199195
wipeTable(self.list)
200-
local filterList = main.filterBuildList or ""
201-
local handle = nil
202-
if filterList ~= "" then
203-
handle = NewFileSearch(main.buildPath..self.subPath.."*"..filterList.."*.xml")
204-
else
205-
handle = NewFileSearch(main.buildPath..self.subPath.."*.xml")
206-
end
207-
while handle do
208-
local fileName = handle:GetFileName()
209-
local build = { }
210-
build.fileName = fileName
211-
build.subPath = self.subPath
212-
build.fullFileName = main.buildPath..self.subPath..fileName
213-
build.modified = handle:GetFileModifiedTime()
214-
build.buildName = fileName:gsub("%.xml$","")
215-
local fileHnd = io.open(build.fullFileName, "r")
216-
if fileHnd then
217-
local fileText = fileHnd:read("*a")
218-
fileHnd:close()
219-
if not fileText then
220-
main:OpenCloudErrorPopup(build.fullFileName)
221-
return
222-
end
223-
fileText = fileText:match("(<Build.->)")
224-
if fileText then
225-
local xml = common.xml.ParseXML(fileText.."</Build>")
226-
if xml and xml[1] then
227-
build.level = tonumber(xml[1].attrib.level)
228-
build.className = xml[1].attrib.className
229-
build.ascendClassName = xml[1].attrib.ascendClassName
230-
end
231-
end
232-
end
233-
t_insert(self.list, build)
234-
if not handle:NextFile() then
235-
break
236-
end
237-
end
238-
handle = NewFileSearch(main.buildPath..self.subPath.."*", true)
239-
while handle do
240-
local folderName = handle:GetFileName()
241-
t_insert(self.list, {
242-
folderName = folderName,
243-
subPath = self.subPath,
244-
fullFileName = main.buildPath..self.subPath..folderName,
245-
modified = handle:GetFileModifiedTime()
246-
})
247-
if not handle:NextFile() then
248-
break
249-
end
196+
local scanned = buildListHelpers.ScanFolder(self.subPath, main.filterBuildList or "")
197+
for _, entry in ipairs(scanned) do
198+
t_insert(self.list, entry)
250199
end
251200
self:SortList()
252201
end
253202

254203
function listMode:SortList()
255204
local oldSelFileName = self.controls.buildList.selValue and self.controls.buildList.selValue.fileName
256-
table.sort(self.list, function(a, b)
257-
local a_is_folder = a.folderName ~= nil
258-
local b_is_folder = b.folderName ~= nil
259-
260-
if a_is_folder and not b_is_folder then return true end
261-
if not a_is_folder and b_is_folder then return false end
262-
263-
264-
if main.buildSortMode == "EDITED" then
265-
local modA = a.modified or 0 -- Use 0 as fallback if modified time is nil
266-
local modB = b.modified or 0
267-
if modA ~= modB then
268-
return modA > modB -- Newest first maybe allow for inverting of order?
269-
end
270-
-- If modified times are the same or both 0 fall back to name sort
271-
if a_is_folder then
272-
return naturalSortCompare(a.folderName, b.folderName)
273-
else
274-
return naturalSortCompare(a.fileName, b.fileName)
275-
end
276-
end
277-
278-
if a_is_folder then
279-
return naturalSortCompare(a.folderName, b.folderName)
280-
else
281-
if main.buildSortMode == "CLASS" then
282-
local a_has_class = a.className ~= nil
283-
local b_has_class = b.className ~= nil
284-
if not a_has_class and b_has_class then return true
285-
elseif a_has_class and not b_has_class then return false
286-
elseif a_has_class and b_has_class and a.className ~= b.className then
287-
return a.className < b.className
288-
end
289-
290-
local a_has_asc = a.ascendClassName ~= nil
291-
local b_has_asc = b.ascendClassName ~= nil
292-
if not a_has_asc and b_has_asc then return true
293-
elseif a_has_asc and not b_has_asc then return false
294-
elseif a_has_asc and b_has_asc and a.ascendClassName ~= b.ascendClassName then
295-
return a.ascendClassName < b.ascendClassName
296-
end
297-
return naturalSortCompare(a.fileName, b.fileName)
298-
elseif main.buildSortMode == "LEVEL" then
299-
if a.level and not b.level then return false
300-
elseif not a.level and b.level then return true
301-
elseif a.level and b.level then
302-
if a.level ~= b.level then return a.level < b.level end
303-
end
304-
return naturalSortCompare(a.fileName, b.fileName)
305-
else
306-
return naturalSortCompare(a.fileName, b.fileName)
307-
end
308-
end
309-
end)
205+
buildListHelpers.SortList(self.list, main.buildSortMode)
310206
if oldSelFileName then
311207
self.controls.buildList:SelByFileName(oldSelFileName)
312208
end

0 commit comments

Comments
 (0)