From cf81e7531ab07149d1c14cd86919b8fa1a63e1b8 Mon Sep 17 00:00:00 2001 From: Openarl Date: Wed, 7 Jun 2017 18:08:31 +1000 Subject: [PATCH] Release 1.4.19 - Added folder support to build list --- Classes/BuildListControl.lua | 202 ++++++++++++++++++++++++++-------- Classes/FolderListControl.lua | 70 ++++++++++++ Classes/ImportTab.lua | 95 +++++++--------- Classes/ListControl.lua | 34 ++++-- Classes/PathControl.lua | 108 ++++++++++++++++++ Data/Uniques/shield.lua | 1 + Modules/Build.lua | 161 +++++++++++++++++---------- Modules/BuildList.lua | 117 +++++++++++++++++--- Modules/Common.lua | 14 +++ Modules/ItemTools.lua | 35 +++--- Modules/Main.lua | 111 ++++++++++++++++++- PathOfBuilding.sln | 2 + README.md | 5 + changelog.txt | 4 + manifest.xml | 24 ++-- 15 files changed, 768 insertions(+), 215 deletions(-) create mode 100644 Classes/FolderListControl.lua create mode 100644 Classes/PathControl.lua diff --git a/Classes/BuildListControl.lua b/Classes/BuildListControl.lua index b3b9c693..cfcc4260 100644 --- a/Classes/BuildListControl.lua +++ b/Classes/BuildListControl.lua @@ -5,12 +5,37 @@ -- local launch, main = ... +local ipairs = ipairs local s_format = string.format local BuildListClass = common.NewClass("BuildList", "ListControl", function(self, anchor, x, y, width, height, listMode) self.ListControl(anchor, x, y, width, height, 20, false, listMode.list) self.listMode = listMode self.showRowSeparators = true + self.controls.path = common.New("PathControl", {"BOTTOM",self,"TOP"}, 0, -2, width, 24, main.buildPath, listMode.subPath, function(subPath) + listMode.subPath = subPath + listMode:BuildList() + self.selIndex = nil + self.selValue = nil + end) + function self.controls.path:CanReceiveDrag(type, build) + return type == "Build" and #self.folderList > 1 + end + 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)) + end + listMode:BuildList() + end + end + end + end + self.dragTargetList = { self.controls.path, self } end) function BuildListClass:SelByFileName(selFileName) @@ -23,52 +48,74 @@ function BuildListClass:SelByFileName(selFileName) end function BuildListClass:LoadBuild(build) - main:SetMode("BUILD", main.buildPath..build.fileName, build.buildName) + if build.folderName then + self.controls.path:SetSubPath(self.listMode.subPath .. build.folderName .. "/") + else + main:SetMode("BUILD", build.fullFileName, build.buildName) + end +end + +function BuildListClass:NewFolder() + main:OpenNewFolderPopup(main.buildPath..self.listMode.subPath, function(newFolderName) + if newFolderName then + self.listMode:BuildList() + end + self.listMode:SelectControl(self) + end) end function BuildListClass:RenameBuild(build, copyOnName) local controls = { } - controls.label = common.New("LabelControl", nil, 0, 20, 0, 16, "^7Enter the new name for this build:") - controls.edit = common.New("EditControl", nil, 0, 40, 350, 20, build.buildName, nil, "\\/:%*%?\"<>|%c", 100, function(buf) + controls.label = common.New("LabelControl", nil, 0, 20, 0, 16, "^7Enter the new name for this "..(build.folderName and "folder:" or "build:")) + controls.edit = common.New("EditControl", nil, 0, 40, 350, 20, build.folderName or build.buildName, nil, "\\/:%*%?\"<>|%c", 100, function(buf) controls.save.enabled = false - if buf:match("%S") and buf:lower() ~= build.buildName:lower() then - local newName = buf..".xml" - local newFile = io.open(main.buildPath..newName, "r") - if newFile then - newFile:close() - else + if build.folderName then + if buf:match("%S") and buf:lower() ~= build.folderName:lower() then controls.save.enabled = true end + else + if buf:match("%S") and buf:lower() ~= build.buildName:lower() then + local newName = buf..".xml" + local newFile = io.open(main.buildPath..build.subPath..newName, "r") + if newFile then + newFile:close() + else + controls.save.enabled = true + end + end end end) controls.save = common.New("ButtonControl", nil, -45, 70, 80, 20, "Save", function() local newBuildName = controls.edit.buf - local newFileName = newBuildName..".xml" - if copyOnName then - local inFile, msg = io.open(main.buildPath..build.fileName, "r") - if not inFile then - main:OpenMessagePopup("Error", "Couldn't open '"..build.fileName.."': "..msg) - return + if build.folderName then + if copyOnName then + main:CopyFolder(build.fullFileName, main.buildPath..build.subPath..newBuildName) + else + local res, msg = os.rename(build.fullFileName, main.buildPath..build.subPath..newBuildName) + if not res then + main:OpenMessagePopup("Error", "Couldn't rename '"..build.fullFileName.."' to '"..newBuildName.."': "..msg) + return + end end - local outFile, msg = io.open(main.buildPath..newFileName, "w") - if not outFile then - main:OpenMessagePopup("Error", "Couldn't create '"..newFileName.."': "..msg) - return - end - outFile:write(inFile:read("*a")) - inFile:close() - outFile:close() + self.listMode:BuildList() else - local res, msg = os.rename(main.buildPath..build.fileName, main.buildPath..newFileName) - if not res then - main:OpenMessagePopup("Error", "Couldn't rename '"..build.fileName.."' to '"..newFileName.."': "..msg) - return + local newFileName = newBuildName..".xml" + if copyOnName then + local res, msg = copyFile(build.fullFileName, main.buildPath..build.subPath..newFileName) + if not res then + main:OpenMessagePopup("Error", "Couldn't copy build: "..msg) + return + end + else + local res, msg = os.rename(build.fullFileName, main.buildPath..build.subPath..newFileName) + if not res then + main:OpenMessagePopup("Error", "Couldn't rename '"..build.fullFileName.."' to '"..newFileName.."': "..msg) + return + end end - build.buildName = newBuildName - build.fileName = newFileName + self.listMode:BuildList() + self:SelByFileName(newFileName) end - self.listMode:BuildList() - self:SelByFileName(newFileName) main:ClosePopup() self.listMode:SelectControl(self) end) @@ -77,44 +124,109 @@ function BuildListClass:RenameBuild(build, copyOnName) main:ClosePopup() self.listMode:SelectControl(self) end) - main:OpenPopup(370, 100, copyOnName and "Copy Build" or "Rename Build", controls, "save", "edit") + main:OpenPopup(370, 100, (copyOnName and "Copy " or "Rename ")..(build.folderName and "Folder" or "Build"), controls, "save", "edit") end function BuildListClass:DeleteBuild(build) - main:OpenConfirmPopup("Confirm Delete", "Are you sure you want to delete build:\n"..build.buildName.."\nThis cannot be undone.", "Delete", function() - os.remove(main.buildPath..build.fileName) - self.listMode:BuildList() - self.selIndex = nil - self.selValue = nil - end) + if build.folderName then + if NewFileSearch(build.fullFileName.."/*") or NewFileSearch(build.fullFileName.."/*", true) then + main:OpenMessagePopup("Delete Folder", "The folder is not empty.") + else + local res, msg = RemoveDir(build.fullFileName) + if not res then + main:OpenMessagePopup("Error", "Couldn't delete '"..build.fullFileName.."': "..msg) + return + end + self.listMode:BuildList() + self.selIndex = nil + self.selValue = nil + end + else + main:OpenConfirmPopup("Confirm Delete", "Are you sure you want to delete build:\n"..build.buildName.."\nThis cannot be undone.", "Delete", function() + os.remove(build.fullFileName) + self.listMode:BuildList() + self.selIndex = nil + self.selValue = nil + end) + end end function BuildListClass:GetColumnOffset(column) if column == 1 then return 0 elseif column == 2 then - return self:GetProperty("width") - 164 + return self:GetProperty("width") - 172 end end function BuildListClass:GetRowValue(column, index, build) if column == 1 then - return build.buildName or "?" + local label + if build.folderName then + label = ">> " .. build.folderName + else + label = build.buildName or "?" + end + if self.cutBuild and self.cutBuild.buildName == build.buildName and self.cutBuild.folderName == build.folderName then + return "^xC0B0B0"..label + else + return label + end elseif column == 2 then - return s_format("%sLevel %d %s", - build.className and data.colorCodes[build.className:upper()] or "^7", - build.level or 1, - (build.ascendClassName ~= "None" and build.ascendClassName) or build.className or "?" - ) + if build.buildName then + return s_format("%sLevel %d %s", + build.className and data.colorCodes[build.className:upper()] or "^7", + build.level or 1, + (build.ascendClassName ~= "None" and build.ascendClassName) or build.className or "?" + ) + else + return "" + end end end +function BuildListClass:GetDragValue(index, build) + return "Build", build +end + +function BuildListClass:CanReceiveDrag(type, build) + return type == "Build" +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)) + end + self.listMode:BuildList() + end + end +end + +function BuildListClass:CanDragToValue(index, build, source) + return build.folderName +end + function BuildListClass:OnSelClick(index, build, doubleClick) if doubleClick then self:LoadBuild(build) + self.selDragging = false end end +function BuildListClass:OnSelCopy(index, build) + self.copyBuild = build + self.cutBuild = nil +end + +function BuildListClass:OnSelCut(index, build) + self.copyBuild = nil + self.cutBuild = build +end + function BuildListClass:OnSelDelete(index, build) self:DeleteBuild(build) end diff --git a/Classes/FolderListControl.lua b/Classes/FolderListControl.lua new file mode 100644 index 00000000..0c66ec05 --- /dev/null +++ b/Classes/FolderListControl.lua @@ -0,0 +1,70 @@ +-- Path of Building +-- +-- Class: Folder List +-- Folder list control. +-- +local launch, main = ... + +local ipairs = ipairs +local t_insert = table.insert + +local FolderListClass = common.NewClass("FolderList", "ListControl", function(self, anchor, x, y, width, height, subPath, onChange) + self.ListControl(anchor, x, y, width, height, 16, false, { }) + self.subPath = subPath or "" + self.controls.path = common.New("PathControl", {"BOTTOM",self,"TOP"}, 0, -2, width, 24, main.buildPath, self.subPath, function(subPath) + self.subPath = subPath + self:BuildList() + self.selIndex = nil + self.selValue = nil + if onChange then + onChange(subPath) + end + end) + self:BuildList() +end) + +function FolderListClass:BuildList() + wipeTable(self.list) + local handle = NewFileSearch(main.buildPath..self.subPath.."*", true) + while handle do + local fileName = handle:GetFileName() + t_insert(self.list, { + name = fileName, + fullFileName = main.buildPath..self.subPath..fileName, + }) + if not handle:NextFile() then + break + end + end +end + +function FolderListClass:OpenFolder(folderName) + self.controls.path:SetSubPath(self.subPath .. folderName .. "/") +end + +function FolderListClass:GetRowValue(column, index, folder) + if column == 1 then + return folder.name + end +end + +function FolderListClass:OnSelClick(index, folder, doubleClick) + if doubleClick then + self:OpenFolder(folder.name) + end +end + +function FolderListClass:OnSelDelete(index, folder) + if NewFileSearch(folder.fullFileName.."/*") or NewFileSearch(folder.fullFileName.."/*", true) then + main:OpenMessagePopup("Delete Folder", "The folder is not empty.") + else + local res, msg = RemoveDir(folder.fullFileName) + if not res then + main:OpenMessagePopup("Error", "Couldn't delete '"..folder.fullFileName.."': "..msg) + return + end + self:BuildList() + self.selIndex = nil + self.selValue = nil + end +end \ No newline at end of file diff --git a/Classes/ImportTab.lua b/Classes/ImportTab.lua index 50c7b0bf..b7fdc889 100644 --- a/Classes/ImportTab.lua +++ b/Classes/ImportTab.lua @@ -199,60 +199,27 @@ You can get this from your web browser's cookies while logged into the Path of E return (self.importCodeState == "VALID" and data.colorCodes.POSITIVE.."Code is valid") or (self.importCodeState == "INVALID" and data.colorCodes.NEGATIVE.."Invalid code") or "" end self.controls.importCodePastebin = common.New("ButtonControl", {"LEFT",self.controls.importCodeIn,"RIGHT"}, 90, 0, 160, 20, "Import from Pastebin...", function() - local controls = { } - controls.editLabel = common.New("LabelControl", nil, 0, 20, 0, 16, "Enter Pastebin.com link:") - controls.edit = common.New("EditControl", nil, 0, 40, 250, 18, "", nil, nil, nil, function(buf) - controls.msg.label = "" - end) - controls.msg = common.New("LabelControl", nil, 0, 58, 0, 16, "") - controls.import = common.New("ButtonControl", nil, -45, 80, 80, 20, "Import", function() - controls.import.enabled = false - controls.msg.label = "Retrieving paste..." - launch:DownloadPage(controls.edit.buf:gsub("pastebin%.com/(%w+)$","pastebin.com/raw/%1"), function(page, errMsg) - if errMsg then - controls.msg.label = "^1"..errMsg - controls.import.enabled = true - else - self.controls.importCodeIn:SetText(page, true) - main:ClosePopup() - end - end) - end) - controls.import.enabled = function() - return #controls.edit.buf > 0 and controls.edit.buf:match("pastebin%.com/%w+") - end - controls.cancel = common.New("ButtonControl", nil, 45, 80, 80, 20, "Cancel", function() - main:ClosePopup() - end) - main:OpenPopup(280, 110, "Import from Pastebin", controls, "import", "edit") + self:OpenPastebinImportPopup() end) - self.controls.importCodeMode = common.New("DropDownControl", {"TOPLEFT",self.controls.importCodeIn,"BOTTOMLEFT"}, 0, 4, 160, 20, { "Import to this build", "Import to a new build:" }) + self.controls.importCodeMode = common.New("DropDownControl", {"TOPLEFT",self.controls.importCodeIn,"BOTTOMLEFT"}, 0, 4, 160, 20, { "Import to this build", "Import to a new build" }) self.controls.importCodeMode.enabled = function() return self.importCodeState == "VALID" and self.build.dbFileName end - self.controls.importCodeBuildName = common.New("EditControl", {"LEFT",self.controls.importCodeMode,"RIGHT"}, 4, 0, 400, 20, "", "New build name", "\\/:%*%?\"<>|%c", 100) - self.controls.importCodeBuildName.enabled = function() - return self.importCodeState == "VALID" and self.controls.importCodeMode.selIndex == 2 - end self.controls.importCodeGo = common.New("ButtonControl", {"TOPLEFT",self.controls.importCodeMode,"BOTTOMLEFT"}, 0, 8, 60, 20, "Import", function() if self.controls.importCodeMode.selIndex == 1 then - main:OpenConfirmPopup("Build Import", "^xFF9922Warning:^7 Importing to the current build will erase ALL existing data for this build.\nThis cannot be undone.", "Import", function() - self:ImportToBuild(self.build.dbFileName, self.build.buildName) + main:OpenConfirmPopup("Build Import", "^xFF9922Warning:^7 Importing to the current build will erase ALL existing data for this build.", "Import", function() + self.build:Shutdown() + self.build:Init(self.build.dbFileName, self.build.buildName, self.importCodeXML) + self.build.viewMode = "TREE" end) else - local newBuildName = self.controls.importCodeBuildName.buf - local newFileName = main.buildPath .. newBuildName .. ".xml" - local file = io.open(newFileName, "r") - if file then - file:close() - main:OpenMessagePopup("Build Import", "A build with that name already exists.") - return - end - self:ImportToBuild(newFileName, newBuildName) + self.build:Shutdown() + self.build:Init(false, "Imported build", self.importCodeXML) + self.build.viewMode = "TREE" end end) self.controls.importCodeGo.enabled = function() - return self.importCodeState == "VALID" and (self.controls.importCodeMode.selIndex == 1 or self.controls.importCodeBuildName.buf:match("%S")) + return self.importCodeState == "VALID" end end) @@ -709,6 +676,35 @@ function ImportTabClass:ImportSocketedSkills(item, socketedItems, slotName) end end +function ImportTabClass:OpenPastebinImportPopup() + local controls = { } + controls.editLabel = common.New("LabelControl", nil, 0, 20, 0, 16, "Enter Pastebin.com link:") + controls.edit = common.New("EditControl", nil, 0, 40, 250, 18, "", nil, nil, nil, function(buf) + controls.msg.label = "" + end) + controls.msg = common.New("LabelControl", nil, 0, 58, 0, 16, "") + controls.import = common.New("ButtonControl", nil, -45, 80, 80, 20, "Import", function() + controls.import.enabled = false + controls.msg.label = "Retrieving paste..." + launch:DownloadPage(controls.edit.buf:gsub("pastebin%.com/(%w+)$","pastebin.com/raw/%1"), function(page, errMsg) + if errMsg then + controls.msg.label = "^1"..errMsg + controls.import.enabled = true + else + self.controls.importCodeIn:SetText(page, true) + main:ClosePopup() + end + end) + end) + controls.import.enabled = function() + return #controls.edit.buf > 0 and controls.edit.buf:match("pastebin%.com/%w+") + end + controls.cancel = common.New("ButtonControl", nil, 45, 80, 80, 20, "Cancel", function() + main:ClosePopup() + end) + main:OpenPopup(280, 110, "Import from Pastebin", controls, "import", "edit") +end + function ImportTabClass:ProcessJSON(json) local func, errMsg = loadstring("return "..jsonToLua(json)) if errMsg then @@ -721,16 +717,3 @@ function ImportTabClass:ProcessJSON(json) end return data end - -function ImportTabClass:ImportToBuild(buildFileName, buildName) - self.build:Shutdown() - local file = io.open(buildFileName, "w+") - if not file then - main:ShowMessagePopup("Build Import", "^xFF2222Error:^7 Couldn't create build file (invalid name?)") - return - end - file:write(self.importCodeXML) - file:close() - self.build:Init(buildFileName, buildName) - self.build.viewMode = "TREE" -end \ No newline at end of file diff --git a/Classes/ListControl.lua b/Classes/ListControl.lua index 9656f68b..dd04f6ea 100644 --- a/Classes/ListControl.lua +++ b/Classes/ListControl.lua @@ -112,7 +112,7 @@ function ListClass:Draw(viewPort) if label then DrawString(x, y - 20, "LEFT", 16, "VAR", label) end - if self.otherDragSource then + if self.otherDragSource and not self.CanDragToValue then SetDrawColor(0.2, 0.6, 0.2) elseif self.hasFocus then SetDrawColor(1, 1, 1) @@ -120,7 +120,7 @@ function ListClass:Draw(viewPort) SetDrawColor(0.5, 0.5, 0.5) end DrawImage(nil, x, y, width, height) - if self.otherDragSource then + if self.otherDragSource and not self.CanDragToValue then SetDrawColor(0, 0.05, 0) else SetDrawColor(0, 0, 0) @@ -151,7 +151,7 @@ function ListClass:Draw(viewPort) text = text:sub(1, clipIndex - 1) .. "..." textWidth = DrawStringWidth(textHeight, "VAR", text) end - if not scrollBar.dragging and not self.selDragActive then + if not scrollBar.dragging and (not self.selDragActive or (self.CanDragToValue and self:CanDragToValue(index, value, self.otherDragSource))) then local cursorX, cursorY = GetCursorPos() local relX = cursorX - (x + 2) local relY = cursorY - (y + 2) @@ -174,6 +174,8 @@ function ListClass:Draw(viewPort) DrawImage(nil, colOffset, lineY, colWidth, rowHeight) if (value == self.selValue or value == ttValue) then SetDrawColor(0.33, 0.33, 0.33) + elseif self.otherDragSource and self.CanDragToValue and self:CanDragToValue(index, value, self.otherDragSource) then + SetDrawColor(0, 0.2, 0) elseif index % 2 == 0 then SetDrawColor(0.05, 0.05, 0.05) else @@ -189,7 +191,11 @@ function ListClass:Draw(viewPort) SetDrawColor(0.5, 0.5, 0.5) end DrawImage(nil, colOffset, lineY, colWidth, rowHeight) - SetDrawColor(0.15, 0.15, 0.15) + if self.otherDragSource and self.CanDragToValue and self:CanDragToValue(index, value, self.otherDragSource) then + SetDrawColor(0, 0.2, 0) + else + SetDrawColor(0.15, 0.15, 0.15) + end DrawImage(nil, colOffset, lineY + 1, colWidth, rowHeight - 2) end SetDrawColor(1, 1, 1) @@ -219,6 +225,8 @@ function ListClass:Draw(viewPort) DrawString(cursorX + 1, cursorY - 7, "LEFT", 16, "VAR", text) SetDrawLayer(nil, 0) end + self.hoverIndex = ttIndex + self.hoverValue = ttValue if ttIndex and self.AddValueTooltip then local col, center = self:AddValueTooltip(ttIndex, ttValue) SetDrawLayer(nil, 100) @@ -249,21 +257,21 @@ function ListClass:OnKeyDown(key, doubleClick) self.selValue = self.list[index] if self.selValue then self.selIndex = index - if self.OnSelect then - self:OnSelect(self.selIndex, self.selValue) - end - if self.OnSelClick then - self:OnSelClick(self.selIndex, self.selValue, doubleClick) - end if (self.isMutable or self.dragTargetList) and self:IsShown() then self.selCX = cursorX self.selCY = cursorY self.selDragging = true self.selDragActive = false end + if self.OnSelect then + self:OnSelect(self.selIndex, self.selValue) + end + if self.OnSelClick then + self:OnSelClick(self.selIndex, self.selValue, doubleClick) + end end end - elseif #self.list > 0 then + elseif #self.list > 0 and not self.selDragActive then if key == "UP" then self:SelectIndex(((self.selIndex or 1) - 2) % #self.list + 1) elseif key == "DOWN" then @@ -277,6 +285,10 @@ function ListClass:OnKeyDown(key, doubleClick) if self.OnSelCopy then self:OnSelCopy(self.selIndex, self.selValue) end + elseif key == "x" and IsKeyDown("CTRL") then + if self.OnSelCut then + self:OnSelCut(self.selIndex, self.selValue) + end elseif key == "BACK" or key == "DELETE" then if self.OnSelDelete then self:OnSelDelete(self.selIndex, self.selValue) diff --git a/Classes/PathControl.lua b/Classes/PathControl.lua new file mode 100644 index 00000000..642e0ffe --- /dev/null +++ b/Classes/PathControl.lua @@ -0,0 +1,108 @@ +-- Path of Building +-- +-- Class: Path Control +-- Path control. +-- +local launch, main = ... + +local ipairs = ipairs +local t_insert = table.insert + +local PathClass = common.NewClass("PathControl", "Control", "ControlHost", "UndoHandler", function(self, anchor, x, y, width, height, basePath, subPath, onChange) + self.Control(anchor, x, y, width, height) + self.ControlHost() + self.UndoHandler() + self.basePath = basePath + self.baseName = basePath:match("([^/]+)/$") or "Base" + self:SetSubPath(subPath or "") + self:ResetUndo() + self.onChange = onChange +end) + +function PathClass:SetSubPath(subPath, noUndo) + if subPath == self.subPath then + return + end + self.subPath = subPath + self.folderList = { + { label = self.baseName, path = "" }, + } + for folder, endIndex in subPath:gmatch("([^/]+)()") do + t_insert(self.folderList, { label = folder, path = subPath:sub(1, endIndex) }) + end + local x = 2 + local i = 1 + for index, folder in ipairs(self.folderList) do + local button = self.controls["folder"..i] + if not button then + button = common.New("ButtonControl", {"LEFT",self,"LEFT"}, 0, 0, 0, self.height - 4) + self.controls["folder"..i] = button + end + button.shown = true + button.x = x + button.label = folder.label + button.width = DrawStringWidth(self.height - 8, "VAR", folder.label) + 10 + button.onClick = function() + self:SetSubPath(folder.path) + end + folder.button = button + x = x + button.width + 12 + i = i + 1 + end + while self.controls["folder"..i] do + self.controls["folder"..i].shown = false + i = i + 1 + end + if self.onChange then + self.onChange(subPath) + end + if not noUndo then + self:AddUndoState() + end +end + +function PathClass:IsMouseOver() + if not self:IsShown() then + return + end + return self:IsMouseInBounds() or self:GetMouseOverControl() +end + +function PathClass:Draw(viewPort) + local x, y = self:GetPos() + local width, height = self:GetSize() + SetDrawColor(0.5, 0.5, 0.5) + DrawImage(nil, x, y, width, height) + SetDrawColor(0, 0, 0) + DrawImage(nil, x + 1, y + 1, width - 2, height - 2) + self:DrawControls(viewPort) + for index, folder in ipairs(self.folderList) do + local buttonX, buttonY = folder.button:GetPos() + local buttonW, buttonH = folder.button:GetSize() + SetDrawColor(1, 1, 1) + main:DrawArrow(buttonX + buttonW + 6, y + height/2, 8, "RIGHT") + if self.otherDragSource and index < #self.folderList then + SetDrawColor(0, 1, 0, 0.25) + DrawImage(nil, buttonX, buttonY, buttonW, buttonH) + end + end +end + +function PathClass:OnKeyDown(key, doubleClick) + if not self:IsShown() or not self:IsEnabled() then + return + end + local mOverControl = self:GetMouseOverControl() + if mOverControl and mOverControl.OnKeyDown then + return mOverControl:OnKeyDown(key) + end +end + +function PathClass:CreateUndoState() + return self.subPath +end + +function PathClass:RestoreUndoState(state) + self:SetSubPath(state, true) +end + diff --git a/Data/Uniques/shield.lua b/Data/Uniques/shield.lua index 31c4855c..1f41b794 100644 --- a/Data/Uniques/shield.lua +++ b/Data/Uniques/shield.lua @@ -426,6 +426,7 @@ Variant: Pre 1.1.0 Variant: Pre 2.0.0 Variant: Current Requires Level 68, 85 Str, 85 Int +Implicits: 2 {variant:1}+24% to all Elemental Resistances {variant:2,3}+12% to all Elemental Resistances {variant:1,2}+1 to Level of Aura Gems in this item diff --git a/Modules/Build.lua b/Modules/Build.lua index 94127410..338114cc 100644 --- a/Modules/Build.lua +++ b/Modules/Build.lua @@ -35,7 +35,7 @@ local mercilessBanditDropList = { local buildMode = common.New("ControlHost") -function buildMode:Init(dbFileName, buildName) +function buildMode:Init(dbFileName, buildName, buildXML) self.abortSave = true self.tree = main.tree @@ -53,7 +53,7 @@ function buildMode:Init(dbFileName, buildName) if self.unsaved then self:OpenSavePopup("LIST") else - main:SetMode("LIST", self.dbFileName and self.buildName) + self:CloseBuild() end end) self.controls.buildName = common.New("Control", {"LEFT",self.controls.back,"RIGHT"}, 8, 0, 0, 20) @@ -75,9 +75,13 @@ function buildMode:Init(dbFileName, buildName) SetViewport(x, y + 2, self.strWidth + 94, 16) DrawString(0, 0, "LEFT", 16, "VAR", "Current build: "..self.buildName) SetViewport() - if control:IsMouseInBounds() and self.strLimited then + if control:IsMouseInBounds() then SetDrawLayer(nil, 10) - main:AddTooltipLine(16, self.buildName) + if self.dbFileSubPath and self.dbFileSubPath ~= "" then + main:AddTooltipLine(16, self.dbFileSubPath..self.buildName) + elseif self.strLimited then + main:AddTooltipLine(16, self.buildName) + end main:DrawTooltip(x, y, width, height, main.viewPort) SetDrawLayer(nil, 0) end @@ -377,6 +381,11 @@ function buildMode:Init(dbFileName, buildName) self.dbFileName = dbFileName self.buildName = buildName + if dbFileName then + self.dbFileSubPath = self.dbFileName:sub(#main.buildPath + 1, -#self.buildName - 5) + else + self.dbFileSubPath = main.modes.LIST.subPath or "" + end self.characterLevel = 1 self.controls.characterLevel:SetText(tostring(self.characterLevel)) @@ -401,9 +410,18 @@ function buildMode:Init(dbFileName, buildName) ["Spec"] = self.treeTab, } - if self:LoadDBFile() then - main:SetMode("LIST", buildName) - return + if buildXML then + if self:LoadDB(buildXML, "Imported build") then + self:CloseBuild() + return + end + self.modFlag = true + else + if self:LoadDBFile() then + self:CloseBuild() + return + end + self.modFlag = false end if next(self.configTab.input) == nil then @@ -457,6 +475,14 @@ function buildMode:Shutdown() self.savers = nil end +function buildMode:GetArgs() + return self.dbFileName, self.buildName +end + +function buildMode:CloseBuild() + main:SetMode("LIST", self.dbFileName and self.buildName, self.dbFileSubPath) +end + function buildMode:Load(xml, fileName) if xml.attrib.viewMode then self.viewMode = xml.attrib.viewMode @@ -496,12 +522,18 @@ end function buildMode:OnFrame(inputEvents) if self.abortSave and not launch.devMode then - main:SetMode("LIST", self.buildName) + self:CloseBuild() end for id, event in ipairs(inputEvents) do if event.type == "KeyDown" then - if IsKeyDown("CTRL") then + if event.key == "MOUSE4" then + if self.unsaved then + self:OpenSavePopup("LIST") + else + self:CloseBuild() + end + elseif IsKeyDown("CTRL") then if event.key == "s" then self:SaveDBFile() inputEvents[id] = nil @@ -509,7 +541,7 @@ function buildMode:OnFrame(inputEvents) if self.unsaved then self:OpenSavePopup("LIST") else - main:SetMode("LIST", self.dbFileName and self.buildName) + self:CloseBuild() end elseif event.key == "1" then self.viewMode = "TREE" @@ -604,65 +636,77 @@ function buildMode:OpenSavePopup(mode) ["EXIT"] = "before exiting?", ["UPDATE"] = "before updating?", } - main:OpenPopup(290, 100, "Save Changes", { - common.New("LabelControl", nil, 0, 20, 0, 16, "^7This build has unsaved changes.\nDo you want to save them "..modeDesc[mode]), - common.New("ButtonControl", nil, -90, 70, 80, 20, "Save", function() - main:ClosePopup() - self.actionOnSave = mode - self:SaveDBFile() - end), - common.New("ButtonControl", nil, 0, 70, 80, 20, "Don't Save", function() - main:ClosePopup() - if mode == "LIST" then - main:SetMode("LIST", self.dbFileName and self.buildName) - elseif mode == "EXIT" then - Exit() - elseif mode == "UPDATE" then - launch:ApplyUpdate(launch.updateAvailable) - end - end), - common.New("ButtonControl", nil, 90, 70, 80, 20, "Cancel", function() - main:ClosePopup() - end), - }) + local controls = { } + controls.label = common.New("LabelControl", nil, 0, 20, 0, 16, "^7This build has unsaved changes.\nDo you want to save them "..modeDesc[mode]) + controls.save = common.New("ButtonControl", nil, -90, 70, 80, 20, "Save", function() + main:ClosePopup() + self.actionOnSave = mode + self:SaveDBFile() + end) + controls.noSave = common.New("ButtonControl", nil, 0, 70, 80, 20, "Don't Save", function() + main:ClosePopup() + if mode == "LIST" then + self:CloseBuild() + elseif mode == "EXIT" then + Exit() + elseif mode == "UPDATE" then + launch:ApplyUpdate(launch.updateAvailable) + end + end) + controls.close = common.New("ButtonControl", nil, 90, 70, 80, 20, "Cancel", function() + main:ClosePopup() + end) + main:OpenPopup(290, 100, "Save Changes", controls) end function buildMode:OpenSaveAsPopup() local newFileName, newBuildName - local popup - popup = main:OpenPopup(370, 100, self.dbFileName and "Save As" or "Save", { - common.New("LabelControl", nil, 0, 20, 0, 16, "^7Enter new build name:"), - edit = common.New("EditControl", nil, 0, 40, 350, 20, self.dbFileName and self.buildName, nil, "\\/:%*%?\"<>|%c", 100, function(buf) - newFileName = main.buildPath..buf..".xml" - newBuildName = buf - popup.controls.save.enabled = false - if not buf:match("%S") then - return - end + local controls = { } + local function updateBuildName() + local buf = controls.edit.buf + newFileName = main.buildPath..controls.folder.subPath..buf..".xml" + newBuildName = buf + controls.save.enabled = false + if buf:match("%S") then local out = io.open(newFileName, "r") if out then out:close() - return + else + controls.save.enabled = true end - popup.controls.save.enabled = true - end), - save = common.New("ButtonControl", nil, -45, 70, 80, 20, "Save", function() - main:ClosePopup() - self.dbFileName = newFileName - self.buildName = newBuildName - main.modeArgs = { newFileName, newBuildName } - self:SaveDBFile() - end), - common.New("ButtonControl", nil, 45, 70, 80, 20, "Cancel", function() - main:ClosePopup() - end), - }, "save", "edit") - popup.controls.save.enabled = false + end + end + controls.label = common.New("LabelControl", nil, 0, 20, 0, 16, "^7Enter new build name:") + controls.edit = common.New("EditControl", nil, 0, 40, 450, 20, self.dbFileName and self.buildName, nil, "\\/:%*%?\"<>|%c", 100, function(buf) + updateBuildName() + end) + controls.folderLabel = common.New("LabelControl", {"TOPLEFT",nil,"TOPLEFT"}, 10, 70, 0, 16, "^7Folder:") + controls.newFolder = common.New("ButtonControl", {"TOPLEFT",nil,"TOPLEFT"}, 100, 67, 94, 20, "New Folder...", function() + main:OpenNewFolderPopup(main.buildPath..controls.folder.subPath, function(newFolderName) + if newFolderName then + controls.folder:OpenFolder(newFolderName) + end + end) + end) + controls.folder = common.New("FolderList", nil, 0, 115, 450, 100, self.dbFileSubPath, function(subPath) + updateBuildName() + end) + controls.save = common.New("ButtonControl", nil, -45, 225, 80, 20, "Save", function() + main:ClosePopup() + self.dbFileName = newFileName + self.buildName = newBuildName + self.dbFileSubPath = controls.folder.subPath + self:SaveDBFile() + end) + controls.save.enabled = false + controls.close = common.New("ButtonControl", nil, 45, 225, 80, 20, "Cancel", function() + main:ClosePopup() + end) + main:OpenPopup(470, 255, self.dbFileName and "Save As" or "Save", controls, "save", "edit") end -- Open the spectre library popup function buildMode:OpenSpectreLibrary() - local controls = { } local destList = copyTable(self.spectreList) local sourceList = { } for id in pairs(data.spectres) do @@ -675,6 +719,7 @@ function buildMode:OpenSpectreLibrary() return data.minions[a].name < data.minions[b].name end end) + local controls = { } controls.list = common.New("MinionList", nil, -100, 40, 190, 250, destList) controls.source = common.New("MinionList", nil, 100, 40, 190, 250, sourceList, controls.list) controls.save = common.New("ButtonControl", nil, -45, 300, 80, 20, "Save", function() @@ -950,7 +995,7 @@ function buildMode:SaveDBFile() file:write(xmlText) file:close() if self.actionOnSave == "LIST" then - main:SetMode("LIST", self.dbFileName and self.buildName) + self:CloseBuild() elseif self.actionOnSave == "EXIT" then Exit() elseif self.actionOnSave == "UPDATE" then diff --git a/Modules/BuildList.lua b/Modules/BuildList.lua index 97b869a1..a6523fd4 100644 --- a/Modules/BuildList.lua +++ b/Modules/BuildList.lua @@ -7,6 +7,7 @@ local launch, main = ... local pairs = pairs local ipairs = ipairs +local t_insert = table.insert local buildSortDropList = { { label = "Sort by Name", sortMode = "NAME" }, @@ -16,18 +17,31 @@ local buildSortDropList = { local listMode = common.New("ControlHost") -function listMode:Init(selBuildName) +function listMode:Init(selBuildName, subPath) + if self.initialised then + self.subPath = subPath or self.subPath + self.controls.buildList.controls.path:SetSubPath(self.subPath) + self.controls.buildList:SelByFileName(selBuildName and selBuildName..".xml") + self:BuildList() + self:SelectControl(self.controls.buildList) + return + end + self.anchor = common.New("Control", nil, 0, 4, 0, 0) self.anchor.x = function() return main.screenW / 2 end + self.subPath = subPath or "" self.list = { } - self.controls.new = common.New("ButtonControl", {"TOP",self.anchor,"TOP"}, -210, 0, 60, 20, "New", function() + self.controls.new = common.New("ButtonControl", {"TOP",self.anchor,"TOP"}, -259, 0, 60, 20, "New", function() main:SetMode("BUILD", false, "Unnamed build") end) - self.controls.open = common.New("ButtonControl", {"LEFT",self.controls.new,"RIGHT"}, 8, 0, 60, 20, "Open", function() + self.controls.newFolder = common.New("ButtonControl", {"LEFT",self.controls.new,"RIGHT"}, 8, 0, 90, 20, "New Folder", function() + self.controls.buildList:NewFolder() + end) + self.controls.open = common.New("ButtonControl", {"LEFT",self.controls.newFolder,"RIGHT"}, 8, 0, 60, 20, "Open", function() self.controls.buildList:LoadBuild(self.controls.buildList.selValue) end) self.controls.open.enabled = function() return self.controls.buildList.selValue ~= nil end @@ -48,21 +62,63 @@ function listMode:Init(selBuildName) self:SortList() end) self.controls.sort:SelByValue(main.buildSortMode, "sortMode") - - self.controls.buildList = common.New("BuildList", {"TOP",self.anchor,"TOP"}, 0, 24, 640, 0, self) + self.controls.buildList = common.New("BuildList", {"TOP",self.anchor,"TOP"}, 0, 50, 640, 0, self) self.controls.buildList.height = function() - return main.screenH - 32 + return main.screenH - 58 end self:BuildList() self.controls.buildList:SelByFileName(selBuildName and selBuildName..".xml") self:SelectControl(self.controls.buildList) + + self.initialised = true end function listMode:Shutdown() end +function listMode:GetArgs() + return self.controls.buildList.selValue and self.controls.buildList.selValue.buildName or false, self.subPath +end + function listMode:OnFrame(inputEvents) + for id, event in ipairs(inputEvents) do + if event.type == "KeyDown" then + if event.key == "v" and IsKeyDown("CTRL") then + if self.controls.buildList.copyBuild then + local build = self.controls.buildList.copyBuild + if build.subPath ~= self.subPath then + if build.folderName then + main:CopyFolder(build.folderName, main.buildPath..build.subPath, main.buildPath..self.subPath) + else + copyFile(build.fullFileName, self:GetDestName(self.subPath, build.fileName)) + end + self:BuildList() + else + self.controls.buildList:RenameBuild(build, true) + end + self.controls.buildList.copyBuild = nil + elseif self.controls.buildList.cutBuild then + local build = self.controls.buildList.cutBuild + if build.subPath ~= self.subPath then + if build.folderName then + main:MoveFolder(build.folderName, main.buildPath..build.subPath, main.buildPath..self.subPath) + else + os.rename(build.fullFileName, self:GetDestName(self.subPath, build.fileName)) + end + self:BuildList() + end + self.controls.buildList.cutBuild = nil + end + elseif event.key == "n" and IsKeyDown("CTRL") then + main:SetMode("BUILD", false, "Unnamed build") + elseif event.key == "MOUSE4" then + self.controls.buildList.controls.path:Undo() + elseif event.key == "MOUSE5" then + self.controls.buildList.controls.path:Redo() + end + end + end self:ProcessControlsInput(inputEvents, main.viewPort) main:DrawBackground(main.viewPort) @@ -70,19 +126,33 @@ function listMode:OnFrame(inputEvents) self:DrawControls(main.viewPort) end -function listMode:BuildList() - self.list = wipeTable(self.list) - local handle = NewFileSearch(main.buildPath.."*.xml") - if not handle then - return - end +function listMode:GetDestName(subPath, fileName) + local i = 2 + local destName = fileName while true do + local test = io.open(destName, "r") + if test then + destName = fileName .. "[" .. i .. "]" + i = i + 1 + else + break + end + end + return main.buildPath..subPath..destName +end + +function listMode:BuildList() + wipeTable(self.list) + local handle = NewFileSearch(main.buildPath..self.subPath.."*.xml") + while handle do local fileName = handle:GetFileName() local build = { } build.fileName = fileName + build.subPath = self.subPath + build.fullFileName = main.buildPath..self.subPath..fileName build.modified = handle:GetFileModifiedTime() build.buildName = fileName:gsub("%.xml$","") - local dbXML = common.xml.LoadXMLFile(main.buildPath..fileName) + local dbXML = common.xml.LoadXMLFile(build.fullFileName) if dbXML and dbXML[1].elem == "PathOfBuilding" then for _, node in ipairs(dbXML[1]) do if type(node) == "table" and node.elem == "Build" then @@ -92,7 +162,19 @@ function listMode:BuildList() end end end - table.insert(self.list, build) + t_insert(self.list, build) + if not handle:NextFile() then + break + end + end + handle = NewFileSearch(main.buildPath..self.subPath.."*", true) + while handle do + local folderName = handle:GetFileName() + t_insert(self.list, { + folderName = folderName, + subPath = self.subPath, + fullFileName = main.buildPath..self.subPath..folderName, + }) if not handle:NextFile() then break end @@ -103,6 +185,13 @@ end function listMode:SortList() local oldSelFileName = self.controls.buildList.selValue and self.controls.buildList.selValue.fileName table.sort(self.list, function(a, b) + if a.folderName and b.folderName then + return a.folderName:upper() < b.folderName:upper() + elseif a.folderName and not b.folderName then + return true + elseif not a.folderName and b.folderName then + return false + end if main.buildSortMode == "EDITED" then return a.modified > b.modified elseif main.buildSortMode == "CLASS" then diff --git a/Modules/Common.lua b/Modules/Common.lua index 1a9991ae..2114cd8e 100644 --- a/Modules/Common.lua +++ b/Modules/Common.lua @@ -294,3 +294,17 @@ function getFormatSec(dec) end end +function copyFile(srcName, dstName) + local inFile, msg = io.open(srcName, "r") + if not inFile then + return nil, "Couldn't open '"..srcName.."': "..msg + end + local outFile, msg = io.open(dstName, "w") + if not outFile then + return nil, "Couldn't create '"..dstName.."': "..msg + end + outFile:write(inFile:read("*a")) + inFile:close() + outFile:close() + return true +end \ No newline at end of file diff --git a/Modules/ItemTools.lua b/Modules/ItemTools.lua index a56ca0bb..efd1d88a 100644 --- a/Modules/ItemTools.lua +++ b/Modules/ItemTools.lua @@ -342,26 +342,30 @@ function itemLib.parseItemRaw(item) end item.affixLimit = 0 if item.crafted then - if item.rarity == "MAGIC" then + if not item.affixes then + item.crafted = false + elseif item.rarity == "MAGIC" then item.affixLimit = 2 elseif item.rarity == "RARE" then - item.affixLimit = (item.base.type == "Jewel" and 4 or 6) + item.affixLimit = (item.type == "Jewel" and 4 or 6) else item.crafted = false end - for _, list in ipairs({item.prefixes,item.suffixes}) do - for i = 1, item.affixLimit/2 do - if not list[i] then - list[i] = "None" - elseif list[i] ~= "None" and not item.affixes[list[i]] then - for modId, mod in pairs(item.affixes) do - if list[i] == mod.affix then - list[i] = modId - break - end - end - if not item.affixes[list[i]] then + if item.crafted then + for _, list in ipairs({item.prefixes,item.suffixes}) do + for i = 1, item.affixLimit/2 do + if not list[i] then list[i] = "None" + elseif list[i] ~= "None" and not item.affixes[list[i]] then + for modId, mod in pairs(item.affixes) do + if list[i] == mod.affix then + list[i] = modId + break + end + end + if not item.affixes[list[i]] then + list[i] = "None" + end end end end @@ -544,9 +548,6 @@ function itemLib.craftItem(item) for _, line in ipairs(custom) do t_insert(item.modLines, line) end - if item.rarity == "MAGIC" then - item.name = newName - end item.raw = itemLib.createItemRaw(item) itemLib.parseItemRaw(item) end diff --git a/Modules/Main.lua b/Modules/Main.lua index 956b1c7d..9338541c 100644 --- a/Modules/Main.lua +++ b/Modules/Main.lua @@ -39,10 +39,12 @@ local classList = { "SliderControl", "TextListControl", "ListControl", + "PathControl", -- Misc "PopupDialog", -- Mode: Build list "BuildListControl", + "FolderListControl", -- Mode: Build "ModList", "ModDB", @@ -230,9 +232,8 @@ function main:OnFrame() self:CallMode("Shutdown") end self.mode = self.newMode - self.modeArgs = self.newModeArgs self.newMode = nil - self:CallMode("Init", unpack(self.modeArgs)) + self:CallMode("Init", unpack(self.newModeArgs)) end self.viewPort = { x = 0, y = 0, width = self.screenW, height = self.screenH } @@ -411,7 +412,7 @@ end function main:SaveSettings() local setXML = { elem = "PathOfBuilding" } local mode = { elem = "Mode", attrib = { mode = self.mode } } - for _, val in ipairs(self.modeArgs) do + for _, val in ipairs({ self:CallMode("GetArgs") }) do local child = { elem = "Arg", attrib = { } } if type(val) == "number" then child.attrib.number = tostring(val) @@ -664,6 +665,82 @@ function main:StatColor(stat, base, limit) end end +function main:MoveFolder(name, srcPath, dstPath) + -- Create destination folder + local res, msg = MakeDir(dstPath..name) + if not res then + self:OpenMessagePopup("Error", "Couldn't move '"..name.."' to '"..dstPath.."' : "..msg) + return + end + + -- Move subfolders + local handle = NewFileSearch(srcPath..name.."/*", true) + while handle do + self:MoveFolder(handle:GetFileName(), srcPath..name.."/", dstPath..name.."/") + if not handle:NextFile() then + break + end + end + + -- Move files + handle = NewFileSearch(srcPath..name.."/*") + while handle do + local fileName = handle:GetFileName() + local srcName = srcPath..name.."/"..fileName + local dstName = dstPath..name.."/"..fileName + local res, msg = os.rename(srcName, dstName) + if not res then + self:OpenMessagePopup("Error", "Couldn't move '"..srcName.."' to '"..dstName.."': "..msg) + return + end + if not handle:NextFile() then + break + end + end + + -- Remove source folder + local res, msg = RemoveDir(srcPath..name) + if not res then + self:OpenMessagePopup("Error", "Couldn't delete '"..dstPath..name.."' : "..msg) + return + end +end + +function main:CopyFolder(srcName, dstName) + -- Create destination folder + local res, msg = MakeDir(dstName) + if not res then + self:OpenMessagePopup("Error", "Couldn't copy '"..srcName.."' to '"..dstName.."' : "..msg) + return + end + + -- Copy subfolders + local handle = NewFileSearch(srcName.."/*", true) + while handle do + local fileName = handle:GetFileName() + self:CopyFolder(srcName.."/"..fileName, dstName.."/"..fileName) + if not handle:NextFile() then + break + end + end + + -- Copy files + handle = NewFileSearch(srcName.."/*") + while handle do + local fileName = handle:GetFileName() + local srcName = srcName.."/"..fileName + local dstName = dstName.."/"..fileName + local res, msg = copyFile(srcName, dstName) + if not res then + self:OpenMessagePopup("Error", "Couldn't copy '"..srcName.."' to '"..dstName.."': "..msg) + return + end + if not handle:NextFile() then + break + end + end +end + function main:OpenPopup(width, height, title, controls, enterControl, defaultControl, escapeControl) local popup = common.New("PopupDialog", width, height, title, controls, enterControl, defaultControl, escapeControl) t_insert(self.popups, 1, popup) @@ -704,6 +781,34 @@ function main:OpenConfirmPopup(title, msg, confirmLabel, onConfirm) return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "confirm") end +function main:OpenNewFolderPopup(path, onClose) + local controls = { } + controls.label = common.New("LabelControl", nil, 0, 20, 0, 16, "^7Enter folder name:") + controls.edit = common.New("EditControl", nil, 0, 40, 350, 20, nil, nil, "\\/:%*%?\"<>|%c", 100, function(buf) + controls.create.enabled = buf:match("%S") + end) + controls.create = common.New("ButtonControl", nil, -45, 70, 80, 20, "Create", function() + local newFolderName = controls.edit.buf + local res, msg = MakeDir(path..newFolderName) + if not res then + main:OpenMessagePopup("Error", "Couldn't create '"..newFolderName.."': "..msg) + return + end + if onClose then + onClose(newFolderName) + end + main:ClosePopup() + end) + controls.create.enabled = false + controls.cancel = common.New("ButtonControl", nil, 45, 70, 80, 20, "Cancel", function() + if onClose then + onClose() + end + main:ClosePopup() + end) + main:OpenPopup(370, 100, "New Folder", controls, "create", "edit", "cancel") +end + do local wrapTable = { } function main:WrapString(str, height, width) diff --git a/PathOfBuilding.sln b/PathOfBuilding.sln index 285f5dfe..761c19de 100644 --- a/PathOfBuilding.sln +++ b/PathOfBuilding.sln @@ -69,6 +69,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Classes", "Classes", "{7EE4 Classes\ControlHost.lua = Classes\ControlHost.lua Classes\DropDownControl.lua = Classes\DropDownControl.lua Classes\EditControl.lua = Classes\EditControl.lua + Classes\FolderListControl.lua = Classes\FolderListControl.lua Classes\GemSelectControl.lua = Classes\GemSelectControl.lua Classes\ImportTab.lua = Classes\ImportTab.lua Classes\ItemDBControl.lua = Classes\ItemDBControl.lua @@ -85,6 +86,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Classes", "Classes", "{7EE4 Classes\PassiveSpecListControl.lua = Classes\PassiveSpecListControl.lua Classes\PassiveTree.lua = Classes\PassiveTree.lua Classes\PassiveTreeView.lua = Classes\PassiveTreeView.lua + Classes\PathControl.lua = Classes\PathControl.lua Classes\PopupDialog.lua = Classes\PopupDialog.lua Classes\ScrollBarControl.lua = Classes\ScrollBarControl.lua Classes\SectionControl.lua = Classes\SectionControl.lua diff --git a/README.md b/README.md index a7b8f9aa..ba021275 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,11 @@ If you'd like to help support the development of Path of Building, I have a [Pat ![ss3](https://cloud.githubusercontent.com/assets/19189971/18089780/f0ff234a-6f04-11e6-8c88-6193fe59a5c4.png) ## Changelog +### 1.4.19 - 2017/06/07 + * The build list now has support for folders + * Importing from a build code no longer requires you to name the build before importing + * Fixed an error that could appear while using the item text editor + ### 1.4.18 - 2017/06/03 * The "Craft item..." feature has been significantly enhanced: * Modifiers are now available for all item types, not just Flasks and Jewels diff --git a/changelog.txt b/changelog.txt index 77935167..0c0688a4 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,7 @@ +VERSION[1.4.19][2017/06/07] + * The build list now has support for folders + * Importing from a build code no longer requires you to name the build before importing + * Fixed an error that could appear while using the item text editor VERSION[1.4.18][2017/06/03] * The "Craft item..." feature has been significantly enhanced: * Modifiers are now available for all item types, not just Flasks and Jewels diff --git a/manifest.xml b/manifest.xml index 2586c57e..5ccff6fd 100644 --- a/manifest.xml +++ b/manifest.xml @@ -1,14 +1,14 @@ - + - - + + @@ -19,14 +19,15 @@ + - + - + @@ -35,6 +36,7 @@ + @@ -45,8 +47,8 @@ - - + + @@ -56,10 +58,10 @@ - + - - + + @@ -123,7 +125,7 @@ - +