Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 39 additions & 14 deletions src/Classes/BuildListControl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,21 @@ local BuildListClass = newClass("BuildListControl", "ListControl", function(self
function self.controls.path:ReceiveDrag(type, build, source)
if type == "Build" then
for index, folder in ipairs(self.folderList) do
if index < #self.folderList and folder.button:IsMouseOver() then
if build.folderName then
main:MoveFolder(build.folderName, main.buildPath..build.subPath, main.buildPath..folder.path)
else
os.rename(build.fullFileName, listMode:GetDestName(folder.path, build.fileName))
if folder.button:IsMouseOver() then
if build.subPath ~= folder.path then
if build.folderName then
main:MoveFolder(build.folderName, main.buildPath..build.subPath, main.buildPath..folder.path)
else
local destPath = listMode:GetDestName(folder.path, build.fileName)
local res, msg = os.rename(build.fullFileName, destPath)
if not res then
main:OpenMessagePopup("Error", "Couldn't move '"..build.fullFileName.."' to '"..destPath.."': "..(msg or ""))
return
end
end
listMode:BuildList()
end
listMode:BuildList()
break
end
end
end
Expand All @@ -57,7 +65,7 @@ end

function BuildListClass:LoadBuild(build)
if build.folderName then
self.controls.path:SetSubPath(self.listMode.subPath .. build.folderName .. "/")
self.controls.path:SetSubPath(build.subPath .. build.folderName .. "/")
else
main:SetMode("BUILD", build.fullFileName, build.buildName)
end
Expand Down Expand Up @@ -171,10 +179,19 @@ end
function BuildListClass:GetRowValue(column, index, build)
if column == 1 then
local label
local subPathPrefix = ""
if build.subPath and self.listMode and self.listMode.subPath and build.subPath ~= self.listMode.subPath then
local baseSub = self.listMode.subPath
if build.subPath:sub(1, #baseSub) == baseSub then
subPathPrefix = build.subPath:sub(#baseSub + 1)
else
subPathPrefix = build.subPath
end
end
if build.folderName then
label = ">> " .. build.folderName
label = ">> " .. subPathPrefix .. build.folderName
else
label = build.buildName or "?"
label = subPathPrefix .. (build.buildName or "?")
end
if self.cutBuild and self.cutBuild.buildName == build.buildName and self.cutBuild.folderName == build.folderName then
return "^xC0B0B0"..label
Expand Down Expand Up @@ -205,12 +222,20 @@ end
function BuildListClass:ReceiveDrag(type, build, source)
if type == "Build" then
if self.hoverValue and self.hoverValue.folderName then
if build.folderName then
main:MoveFolder(build.folderName, main.buildPath..build.subPath, main.buildPath..self.hoverValue.subPath..self.hoverValue.folderName.."/")
else
os.rename(build.fullFileName, self.listMode:GetDestName(self.listMode.subPath..self.hoverValue.folderName.."/", build.fileName))
local targetSubPath = self.hoverValue.subPath .. self.hoverValue.folderName .. "/"
if build.subPath ~= targetSubPath then
if build.folderName then
main:MoveFolder(build.folderName, main.buildPath..build.subPath, main.buildPath..targetSubPath)
else
local destPath = self.listMode:GetDestName(targetSubPath, build.fileName)
local res, msg = os.rename(build.fullFileName, destPath)
if not res then
main:OpenMessagePopup("Error", "Couldn't move '"..build.fullFileName.."' to '"..destPath.."': "..(msg or ""))
return
end
end
self.listMode:BuildList()
end
self.listMode:BuildList()
end
end
end
Expand Down
3 changes: 2 additions & 1 deletion src/Classes/CompareTab.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,7 @@ function CompareTabClass:OpenImportFolderPopup()
searchText = buf
listHost:BuildList()
end, nil, nil, true)
controls.searchText:SetPlaceholder("(e.g. class:assassin myfilename)")
controls.sort = new("DropDownControl", {"TOPLEFT", nil, "TOPLEFT"}, {475, 25, 210, 20}, buildListHelpers.buildSortDropList, function(index, value)
sortMode = value.sortMode
main.buildSortMode = value.sortMode
Expand All @@ -1590,7 +1591,7 @@ function CompareTabClass:OpenImportFolderPopup()
-- navigate folders, import builds, and suppress rename/delete/drag behaviors.
function controls.buildList:LoadBuild(build)
if build.folderName then
self.controls.path:SetSubPath(self.listMode.subPath .. build.folderName .. "/")
self.controls.path:SetSubPath(build.subPath .. build.folderName .. "/")
else
importBuildEntry(build)
end
Expand Down
4 changes: 4 additions & 0 deletions src/Classes/EditControl.lua
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,10 @@ function EditClass:Draw(viewPort, noTooltip)
DrawImage(nil, caretX, textY, 1, textHeight)
end
else
if self.buf == '' and self.placeholder then
SetDrawColor(self.disableCol)
DrawString(textX, textY, "LEFT", textHeight, self.font, self.placeholder)
end
local pre = self.textCol .. self.buf:sub(1, self.caret - 1)
local post = self.buf:sub(self.caret)
if self.protected then
Expand Down
7 changes: 5 additions & 2 deletions src/Modules/BuildList.lua
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ function listMode:Init(selBuildName, subPath)
main.filterBuildList = buf
self:BuildList()
end, nil, nil, true)
self.controls.searchText:SetPlaceholder("(e.g. class:assassin myfilename)")
self.controls.searchText.width = buildListWidth
self.controls.searchText.x = buildListOffset

Expand Down Expand Up @@ -180,9 +181,11 @@ function listMode:GetDestName(subPath, fileName)
local i = 2
local destName = fileName
while true do
local test = io.open(destName, "r")
local test = io.open(main.buildPath..subPath..destName, "r")
if test then
destName = fileName .. "[" .. i .. "]"
test:close()
local baseName = fileName:gsub("%.xml$", "")
destName = baseName .. "[" .. i .. "].xml"
i = i + 1
else
break
Expand Down
170 changes: 123 additions & 47 deletions src/Modules/BuildListHelpers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,65 +14,141 @@ local buildSortDropList = {
{ label = "Sort by Level", sortMode = "LEVEL"},
}

local function ReadBuildHeader(fullFileName)
local fileHnd = io.open(fullFileName, "r")
if not fileHnd then return nil, nil, nil end
local headerText = fileHnd:read(2048)
fileHnd:close()
if not headerText then return nil, nil, nil end

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we keep using OpenCloudErrorPopup here? I believe we've mitigated many of the root causes, but I'd like to keep this error pop-up in case people run into Cloud syncing issues


local buildTag = headerText:match("<Build%s+[^>]->")
if not buildTag then return nil, nil, nil end

local level = tonumber(buildTag:match('level="([^"]+)"'))
local className = buildTag:match('className="([^"]+)"')
local ascendClassName = buildTag:match('ascendClassName="([^"]+)"')
return level, className, ascendClassName
end

local function MatchEntry(entry, terms)
for _, term in ipairs(terms) do
local val = term:match("^class:(.*)$")
if val then
val = val:lower()
if val ~= "" then
local match = (entry.className and entry.className:lower():find(val, 1, true)) or
(entry.ascendClassName and entry.ascendClassName:lower():find(val, 1, true)) or
(entry.folderName and entry.folderName:lower():find(val, 1, true))
if not match then return false end
end
else
local termLower = term:lower()
local match = (entry.buildName and entry.buildName:lower():find(termLower, 1, true)) or
(entry.folderName and entry.folderName:lower():find(termLower, 1, true)) or
(entry.className and entry.className:lower():find(termLower, 1, true)) or
(entry.ascendClassName and entry.ascendClassName:lower():find(termLower, 1, true)) or
(entry.subPath and entry.subPath:lower():find(termLower, 1, true))
if not match then return false end
end
end
return true
end

-- Scan main.buildPath..subPath for .xml builds and sub-folders.
-- filterText is an optional substring filter applied to build filenames.
-- Returns a freshly allocated list of entries in the shape used by BuildListControl.
-- On cloud-read failure opens main:OpenCloudErrorPopup and returns whatever has been
-- collected so far (matching the prior in-module behavior in Modules/BuildList).
-- filterText is an optional space-separated filter with class: prefix support.
-- Recursively searches subfolders when filterText is non-empty.
-- Returns a list of build and folder entries for BuildListControl.
local function ScanFolder(subPath, filterText)
subPath = subPath or ""
filterText = filterText or ""
local list = { }
local handle
if filterText ~= "" then
handle = NewFileSearch(main.buildPath..subPath.."*"..filterText.."*.xml")
else
handle = NewFileSearch(main.buildPath..subPath.."*.xml")

local terms = { }
if filterText:match("%S") then
for term in filterText:gmatch("%S+") do
t_insert(terms, term)
end
end
while handle do
local fileName = handle:GetFileName()
local build = { }
build.fileName = fileName
build.subPath = subPath
build.fullFileName = main.buildPath..subPath..fileName
build.modified = handle:GetFileModifiedTime()
build.buildName = fileName:gsub("%.xml$","")
local fileHnd = io.open(build.fullFileName, "r")
if fileHnd then
local fileText = fileHnd:read("*a")
fileHnd:close()
if not fileText then
main:OpenCloudErrorPopup(build.fullFileName)
return list
end
fileText = fileText:match("(<Build.->)")
if fileText then
local xml = common.xml.ParseXML(fileText.."</Build>")
if xml and xml[1] then
build.level = tonumber(xml[1].attrib.level)
build.className = xml[1].attrib.className
build.ascendClassName = xml[1].attrib.ascendClassName

local function scanDir(currentSubPath)
local handle = NewFileSearch(main.buildPath..currentSubPath.."*.xml")
while handle do
local fileName = handle:GetFileName()
local buildName = fileName:gsub("%.xml$","")
local fullFileName = main.buildPath..currentSubPath..fileName

if #terms == 0 then
if currentSubPath == subPath then
local level, className, ascendClassName = ReadBuildHeader(fullFileName)
t_insert(list, {
fileName = fileName,
subPath = currentSubPath,
fullFileName = fullFileName,
modified = handle:GetFileModifiedTime(),
buildName = buildName,
level = level,
className = className,
ascendClassName = ascendClassName,
})
end
else
local level, className, ascendClassName = ReadBuildHeader(fullFileName)
local entry = {
fileName = fileName,
subPath = currentSubPath,
fullFileName = fullFileName,
modified = handle:GetFileModifiedTime(),
buildName = buildName,
level = level,
className = className,
ascendClassName = ascendClassName,
}
if MatchEntry(entry, terms) then
t_insert(list, entry)
end
end

if not handle:NextFile() then break end
end
t_insert(list, build)
if not handle:NextFile() then
break

handle = NewFileSearch(main.buildPath..currentSubPath.."*", true)
local subFolders = { }
while handle do
local folderName = handle:GetFileName()
local modified = handle:GetFileModifiedTime()
t_insert(subFolders, { name = folderName, modified = modified })
if not handle:NextFile() then break end
end
end
handle = NewFileSearch(main.buildPath..subPath.."*", true)
while handle do
local folderName = handle:GetFileName()
t_insert(list, {
folderName = folderName,
subPath = subPath,
fullFileName = main.buildPath..subPath..folderName,
modified = handle:GetFileModifiedTime()
})
if not handle:NextFile() then
break

for _, folder in ipairs(subFolders) do
local folderName = folder.name
local nextSubPath = currentSubPath .. folderName .. "/"

if #terms == 0 then
if currentSubPath == subPath then
t_insert(list, {
folderName = folderName,
subPath = currentSubPath,
fullFileName = main.buildPath..currentSubPath..folderName,
modified = folder.modified
})
end
else
local folderEntry = {
folderName = folderName,
subPath = currentSubPath,
fullFileName = main.buildPath..currentSubPath..folderName,
modified = folder.modified
}
if MatchEntry(folderEntry, terms) then
t_insert(list, folderEntry)
end
scanDir(nextSubPath)
end
end
end

scanDir(subPath)
return list
end

Expand Down
Loading