From 867df49074d1e680c536d9dbc361a9eb4fd3706a Mon Sep 17 00:00:00 2001 From: Openarl Date: Mon, 21 Nov 2016 02:54:19 +1000 Subject: [PATCH] Sneaking in a few more features - Sort button for 'All items' list - Improved keyboard interaction --- Classes/BuildListControl.lua | 15 +++++++++++ Classes/ButtonControl.lua | 6 +++++ Classes/ItemDBControl.lua | 18 +++++++++++++ Classes/ItemListControl.lua | 49 ++++++++++++++++++++++++++++++++++++ Classes/ItemSlotControl.lua | 1 + Classes/ItemsTab.lua | 18 ++++++++----- Classes/PopupDialog.lua | 11 +++++++- Classes/SkillListControl.lua | 21 +++++++++++----- Classes/TreeTab.lua | 10 +++----- Modules/Build.lua | 3 +-- Modules/Main.lua | 16 ++++++------ README.md | 5 ++++ changelog.txt | 5 ++++ manifest.xml | 24 +++++++++--------- 14 files changed, 161 insertions(+), 41 deletions(-) diff --git a/Classes/BuildListControl.lua b/Classes/BuildListControl.lua index e85ad21c..a8078be6 100644 --- a/Classes/BuildListControl.lua +++ b/Classes/BuildListControl.lua @@ -41,6 +41,13 @@ function BuildListClass:ScrollSelIntoView() end end +function BuildListClass:SelectIndex(index) + if self.listMode.list[index] then + self.listMode.sel = index + self:ScrollSelIntoView() + end +end + function BuildListClass:IsMouseOver() if not self:IsShown() then return @@ -134,6 +141,14 @@ function BuildListClass:OnKeyDown(key, doubleClick) end end end + elseif key == "UP" then + self:SelectIndex(((self.listMode.sel or 1) - 2) % #self.listMode.list + 1) + elseif key == "DOWN" then + self:SelectIndex((self.listMode.sel or #self.listMode.list) % #self.listMode.list + 1) + elseif key == "HOME" then + self:SelectIndex(1) + elseif key == "END" then + self:SelectIndex(#self.listMode.list) elseif self.listMode.sel then if key == "BACK" or key == "DELETE" then self.listMode:DeleteSel() diff --git a/Classes/ButtonControl.lua b/Classes/ButtonControl.lua index bdd66e71..5c3f4d05 100644 --- a/Classes/ButtonControl.lua +++ b/Classes/ButtonControl.lua @@ -11,6 +11,12 @@ local ButtonClass = common.NewClass("ButtonControl", "Control", function(self, a self.onClick = onClick end) +function ButtonClass:Click() + if self:IsShown() and self:IsEnabled() then + self.onClick() + end +end + function ButtonClass:IsMouseOver() if not self:IsShown() then return false diff --git a/Classes/ItemDBControl.lua b/Classes/ItemDBControl.lua index 2e1953d3..596fab58 100644 --- a/Classes/ItemDBControl.lua +++ b/Classes/ItemDBControl.lua @@ -160,6 +160,14 @@ function ItemDBClass:BuildOrderList() end) end +function ItemDBClass:SelectIndex(index) + self.selItem = self.orderList[index] + if self.selItem then + self.selIndex = index + self.controls.scrollBar:ScrollIntoView((index - 2) * 16, 48) + end +end + function ItemDBClass:IsMouseOver() if not self:IsShown() then return @@ -242,6 +250,7 @@ function ItemDBClass:OnKeyDown(key, doubleClick) end if key == "LEFTBUTTON" then self.selItem = nil + self.selIndex = nil local x, y = self:GetPos() local width, height = self:GetSize() local cursorX, cursorY = GetCursorPos() @@ -283,6 +292,14 @@ function ItemDBClass:OnKeyDown(key, doubleClick) self.selDragging = true self.selDragActive = false end + elseif key == "UP" then + self:SelectIndex(((self.selIndex or 1) - 2) % #self.orderList + 1) + elseif key == "DOWN" then + self:SelectIndex((self.selIndex or #self.orderList) % #self.orderList + 1) + elseif key == "HOME" then + self:SelectIndex(1) + elseif key == "END" then + self:SelectIndex(#self.orderList) elseif key == "c" and IsKeyDown("CTRL") then if self.selItem then Copy(self.selItem.raw:gsub("\n","\r\n")) @@ -325,6 +342,7 @@ function ItemDBClass:OnKeyUp(key) self.itemsTab.build.buildFlag = true end self.selItem = nil + self.selIndex = nil return end end diff --git a/Classes/ItemListControl.lua b/Classes/ItemListControl.lua index 47cad556..016e6b10 100644 --- a/Classes/ItemListControl.lua +++ b/Classes/ItemListControl.lua @@ -20,6 +20,33 @@ local ItemListClass = common.NewClass("ItemList", "Control", "ControlHost", func local width, height = self:GetSize() return height - 2 end + self.controls.sort = common.New("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, -64, -2, 60, 18, "Sort", function() + table.sort(itemsTab.orderList, function(a, b) + local itemA = itemsTab.list[a] + local itemB = itemsTab.list[b] + local primSlotA = itemLib.getPrimarySlotForItem(itemA) + local primSlotB = itemLib.getPrimarySlotForItem(itemB) + if primSlotA ~= primSlotB then + if not itemsTab.slotOrder[primSlotA] then + return false + elseif not itemsTab.slotOrder[primSlotB] then + return true + end + return itemsTab.slotOrder[primSlotA] < itemsTab.slotOrder[primSlotB] + end + local equipSlotA = itemsTab:GetEquippedSlotForItem(itemA) + local equipSlotB = itemsTab:GetEquippedSlotForItem(itemB) + if equipSlotA and equipSlotB then + return itemsTab.slotOrder[equipSlotA.slotName] < itemsTab.slotOrder[equipSlotB.slotName] + elseif not equipSlotA then + return false + elseif not equipSlotB then + return true + end + return itemA.name < itemB.name + end) + itemsTab:AddUndoState() + end) self.controls.delete = common.New("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, 0, -2, 60, 18, "Delete", function() self:OnKeyUp("DELETE") end) @@ -28,6 +55,15 @@ local ItemListClass = common.NewClass("ItemList", "Control", "ControlHost", func end end) +function ItemListClass:SelectIndex(index) + local selItemId = self.itemsTab.orderList[index] + if selItemId then + self.selItem = self.itemsTab.list[selItemId] + self.selIndex = index + self.controls.scrollBar:ScrollIntoView((index - 2) * 16, 48) + end +end + function ItemListClass:IsMouseOver() if not self:IsShown() then return @@ -134,6 +170,7 @@ function ItemListClass:OnKeyDown(key, doubleClick) end if key == "LEFTBUTTON" then self.selItem = nil + self.selIndex = nil local x, y = self:GetPos() local width, height = self:GetSize() local cursorX, cursorY = GetCursorPos() @@ -173,6 +210,14 @@ function ItemListClass:OnKeyDown(key, doubleClick) self.selDragging = true self.selDragActive = false end + elseif key == "UP" then + self:SelectIndex(((self.selIndex or 1) - 2) % #self.itemsTab.orderList + 1) + elseif key == "DOWN" then + self:SelectIndex((self.selIndex or #self.itemsTab.orderList) % #self.itemsTab.orderList + 1) + elseif key == "HOME" then + self:SelectIndex(1) + elseif key == "END" then + self:SelectIndex(#self.itemsTab.orderList) elseif key == "c" and IsKeyDown("CTRL") then if self.selItem then Copy(self.selItem.raw:gsub("\n","\r\n")) @@ -196,10 +241,12 @@ function ItemListClass:OnKeyUp(key) main:OpenConfirmPopup("Delete Item", self.selItem.name.." is currently equipped in "..equipSlot.label..".\nAre you sure you want to delete it?", "Delete", function() self.itemsTab:DeleteItem(self.selItem) self.selItem = nil + self.selIndex = nil end) else self.itemsTab:DeleteItem(self.selItem) self.selItem = nil + self.selIndex = nil end elseif key == "LEFTBUTTON" then self.selDragging = false @@ -214,6 +261,7 @@ function ItemListClass:OnKeyUp(key) t_insert(self.itemsTab.orderList, self.selDragIndex, self.selItem.id) self.itemsTab:AddUndoState() self.selItem = nil + self.selIndex = nil end else for slotName, slot in pairs(self.itemsTab.slots) do @@ -225,6 +273,7 @@ function ItemListClass:OnKeyUp(key) self.itemsTab.build.buildFlag = true end self.selItem = nil + self.selIndex = nil return end end diff --git a/Classes/ItemSlotControl.lua b/Classes/ItemSlotControl.lua index ca33f3f2..14ba6126 100644 --- a/Classes/ItemSlotControl.lua +++ b/Classes/ItemSlotControl.lua @@ -31,6 +31,7 @@ local ItemSlotClass = common.NewClass("ItemSlot", "DropDownControl", function(se self.label = slotLabel or slotName self.nodeId = nodeId itemsTab.slots[slotName] = self + t_insert(itemsTab.orderedSlots, self) end) function ItemSlotClass:Populate() diff --git a/Classes/ItemsTab.lua b/Classes/ItemsTab.lua index 06dfece5..106b30b2 100644 --- a/Classes/ItemsTab.lua +++ b/Classes/ItemsTab.lua @@ -27,8 +27,11 @@ local ItemsTabClass = common.NewClass("ItemsTab", "UndoHandler", "ControlHost", -- Item slots self.slots = { } - for index, slotName in pairs(baseSlots) do + self.orderedSlots = { } + self.slotOrder = { } + for index, slotName in ipairs(baseSlots) do t_insert(self.controls, common.New("ItemSlot", {"TOPLEFT",self,"TOPLEFT"}, 96, (index - 1) * 20 + 24, self, slotName)) + self.slotOrder[slotName] = index end self.sockets = { } for _, node in pairs(main.tree.nodes) do @@ -36,12 +39,16 @@ local ItemsTabClass = common.NewClass("ItemsTab", "UndoHandler", "ControlHost", local socketControl = common.New("ItemSlot", {"TOPLEFT",self,"TOPLEFT"}, 96, 0, self, "Jewel "..node.id, "Socket", node.id) self.controls["socket"..node.id] = socketControl self.sockets[node.id] = socketControl + self.slotOrder["Jewel "..node.id] = #baseSlots + 1 + node.id end end - self.controls.slotHeader = common.New("LabelControl", {"BOTTOMLEFT",self.slots[baseSlots[1]],"TOPLEFT"}, 0, -4, 0, 16, "^7Equipped items:") + table.sort(self.orderedSlots, function(a, b) + return self.slotOrder[a.slotName] < self.slotOrder[b.slotName] + end) + self.controls.slotHeader = common.New("LabelControl", {"BOTTOMLEFT",self.orderedSlots[1],"TOPLEFT"}, 0, -4, 0, 16, "^7Equipped items:") -- Build item list - self.controls.itemList = common.New("ItemList", {"TOPLEFT",self.slots[baseSlots[1]],"TOPRIGHT"}, 20, 0, 360, 308, self) + self.controls.itemList = common.New("ItemList", {"TOPLEFT",self.orderedSlots[1],"TOPRIGHT"}, 20, 0, 360, 308, self) -- Database selector self.controls.selectDBLabel = common.New("LabelControl", {"TOPLEFT",self.controls.itemList,"BOTTOMLEFT"}, 0, 14, 0, 16, "^7Import from:") @@ -335,10 +342,9 @@ function ItemsTabClass:DeleteItem(item) self:AddUndoState() end --- Returns a slot in which the given item is equipped, if one exists --- If the item is equipped in multiple slots, the return value may be any of those slots +-- Returns the first slot in which the given item is equipped function ItemsTabClass:GetEquippedSlotForItem(item) - for _, slot in pairs(self.slots) do + for _, slot in ipairs(self.orderedSlots) do if not slot.inactive and slot.selItemId == item.id then return slot end diff --git a/Classes/PopupDialog.lua b/Classes/PopupDialog.lua index 2f835daf..377501c6 100644 --- a/Classes/PopupDialog.lua +++ b/Classes/PopupDialog.lua @@ -7,7 +7,7 @@ local launch, main = ... local m_floor = math.floor -local PopupDialogClass = common.NewClass("PopupDialog", "ControlHost", "Control", function(self, width, height, title, controls) +local PopupDialogClass = common.NewClass("PopupDialog", "ControlHost", "Control", function(self, width, height, title, controls, enterControl, defaultControl) self.ControlHost() self.Control(nil, 0, 0, width, height) self.x = function() @@ -18,6 +18,7 @@ local PopupDialogClass = common.NewClass("PopupDialog", "ControlHost", "Control" end self.title = title self.controls = controls + self.enterControl = enterControl for id, control in pairs(self.controls) do if not control.anchor.point then control:SetAnchor("TOP", self, "TOP") @@ -27,6 +28,9 @@ local PopupDialogClass = common.NewClass("PopupDialog", "ControlHost", "Control" control.anchor.other = self.controls[control.anchor.other] end end + if defaultControl then + self:SelectControl(self.controls[defaultControl]) + end end) function PopupDialogClass:Draw(viewPort) @@ -57,6 +61,11 @@ function PopupDialogClass:ProcessInput(inputEvents, viewPort) if event.key == "ESCAPE" then main:ClosePopup() return + elseif event.key == "RETURN" then + if self.enterControl then + self.controls[self.enterControl]:Click() + return + end end end end diff --git a/Classes/SkillListControl.lua b/Classes/SkillListControl.lua index fa403c94..cb3bafb8 100644 --- a/Classes/SkillListControl.lua +++ b/Classes/SkillListControl.lua @@ -47,6 +47,15 @@ local SkillListClass = common.NewClass("SkillList", "Control", "ControlHost", fu end) end) +function SkillListClass:SelectIndex(index) + self.selGroup = self.skillsTab.socketGroupList[index] + if self.selGroup then + self.selIndex = index + self.skillsTab:SetDisplayGroup(self.selGroup) + self.controls.scrollBar:ScrollIntoView((index - 2) * 16, 48) + end +end + function SkillListClass:IsMouseOver() if not self:IsShown() then return @@ -229,13 +238,13 @@ function SkillListClass:OnKeyDown(key, doubleClick) end elseif #self.skillsTab.socketGroupList > 0 then if key == "UP" then - self.selIndex = ((self.selIndex or 1) - 2) % #self.skillsTab.socketGroupList + 1 - self.selGroup = self.skillsTab.socketGroupList[self.selIndex] - self.skillsTab:SetDisplayGroup(self.selGroup) + self:SelectIndex(((self.selIndex or 1) - 2) % #self.skillsTab.socketGroupList + 1) elseif key == "DOWN" then - self.selIndex = (self.selIndex or #self.skillsTab.socketGroupList) % #self.skillsTab.socketGroupList + 1 - self.selGroup = self.skillsTab.socketGroupList[self.selIndex] - self.skillsTab:SetDisplayGroup(self.selGroup) + self:SelectIndex((self.selIndex or #self.skillsTab.socketGroupList) % #self.skillsTab.socketGroupList + 1) + elseif key == "HOME" then + self:SelectIndex(1) + elseif key == "END" then + self:SelectIndex(#self.skillsTab.socketGroupList) end end return self diff --git a/Classes/TreeTab.lua b/Classes/TreeTab.lua index 3cb1e773..1fd3ead9 100644 --- a/Classes/TreeTab.lua +++ b/Classes/TreeTab.lua @@ -32,7 +32,7 @@ local TreeTabClass = common.NewClass("TreeTab", "ControlHost", function(self, bu showMsg = nil end), common.New("LabelControl", nil, 0, 58, 0, 16, function() return showMsg or "" end), - common.New("ButtonControl", nil, -45, 80, 80, 20, "Import", function() + import = common.New("ButtonControl", nil, -45, 80, 80, 20, "Import", function() if #treeLink > 0 then if treeLink:match("poeurl%.com/") then local curl = require("lcurl") @@ -63,8 +63,7 @@ local TreeTabClass = common.NewClass("TreeTab", "ControlHost", function(self, bu common.New("ButtonControl", nil, 45, 80, 80, 20, "Cancel", function() main:ClosePopup() end), - }) - popup:SelectControl(popup.controls.edit) + }, "import", "edit") end) self.controls.export = common.New("ButtonControl", {"LEFT",self.controls.import,"RIGHT"}, 8, 0, 90, 20, "Export Tree", function() local treeLink = self.build.spec:EncodeURL("https://www.pathofexile.com/passive-skill-tree/") @@ -89,11 +88,10 @@ local TreeTabClass = common.NewClass("TreeTab", "ControlHost", function(self, bu common.New("ButtonControl", nil, 30, 70, 80, 20, "Copy", function() Copy(treeLink) end), - common.New("ButtonControl", nil, 120, 70, 80, 20, "Done", function() + done = common.New("ButtonControl", nil, 120, 70, 80, 20, "Done", function() main:ClosePopup() end), - }) - popup:SelectControl(popup.controls.edit) + }, "done", "edit") end) self.controls.treeSearch = common.New("EditControl", {"LEFT",self.controls.export,"RIGHT"}, 8, 0, 400, 20, "", "Search", "[^%c%(%)]", 100, function(buf) self.viewer.searchStr = buf diff --git a/Modules/Build.lua b/Modules/Build.lua index df95f520..a995f47c 100644 --- a/Modules/Build.lua +++ b/Modules/Build.lua @@ -95,9 +95,8 @@ function buildMode:Init(dbFileName, buildName) common.New("ButtonControl", nil, 45, 70, 80, 20, "Cancel", function() main:ClosePopup() end), - }) + }, "save", "edit") popup.controls.save.enabled = false - popup:SelectControl(popup.controls.edit) end) -- Controls: top bar, right side diff --git a/Modules/Main.lua b/Modules/Main.lua index 584d6b97..ae69e066 100644 --- a/Modules/Main.lua +++ b/Modules/Main.lua @@ -369,8 +369,8 @@ function main:DrawCheckMark(x, y, size) DrawImageQuad(nil, x + size * 0.40, y + size * 0.90, x + size * 0.35, y + size * 0.75, x + size * 0.80, y + size * 0.10, x + size * 0.90, y + size * 0.20) end -function main:OpenPopup(width, height, title, controls) - local popup = common.New("PopupDialog", width, height, title, controls) +function main:OpenPopup(width, height, title, controls, enterControl, defaultControl) + local popup = common.New("PopupDialog", width, height, title, controls, enterControl, defaultControl) t_insert(self.popups, popup) return popup end @@ -386,10 +386,10 @@ function main:OpenMessagePopup(title, msg) t_insert(controls, common.New("LabelControl", nil, 0, 20 + numMsgLines * 16, 0, 16, line)) numMsgLines = numMsgLines + 1 end - t_insert(controls, common.New("ButtonControl", nil, 0, 40 + numMsgLines * 16, 80, 20, "Ok", function() + controls.close = common.New("ButtonControl", nil, 0, 40 + numMsgLines * 16, 80, 20, "Ok", function() main:ClosePopup() - end)) - return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls) + end) + return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "close") end function main:OpenConfirmPopup(title, msg, confirmLabel, onConfirm) @@ -399,14 +399,14 @@ function main:OpenConfirmPopup(title, msg, confirmLabel, onConfirm) t_insert(controls, common.New("LabelControl", nil, 0, 20 + numMsgLines * 16, 0, 16, line)) numMsgLines = numMsgLines + 1 end - t_insert(controls, common.New("ButtonControl", nil, -45, 40 + numMsgLines * 16, 80, 20, confirmLabel, function() + controls.confirm = common.New("ButtonControl", nil, -45, 40 + numMsgLines * 16, 80, 20, confirmLabel, function() onConfirm() main:ClosePopup() - end)) + end) t_insert(controls, common.New("ButtonControl", nil, 45, 40 + numMsgLines * 16, 80, 20, "Cancel", function() main:ClosePopup() end)) - return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls) + return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "confirm") end function main:AddTooltipLine(size, text) diff --git a/README.md b/README.md index 5ef110fe..d73a0b12 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,11 @@ Head over to the [Releases](https://github.com/Openarl/PathOfBuilding/releases) ## Changelog ### 1.2.10 - 2016/11/21 * Added support for Unholy Might; you can enable it in the Configuration tab in the Combat section + * Added a Sort button to the "All items" list in the Items tab + * Improved keyboard interaction throughout the program: + * Enabled keyboard navigation for all lists + * 'Enter' now accepts confirmation popups, and other popups such as "Save As" + * Dropdown lists can be cycled with Up/Down as well as the mousewheel * Fixed Elreon's -mana cost modifier increasing the mana cost instead of decreasing it ### 1.2.9 - 2016/11/20 diff --git a/changelog.txt b/changelog.txt index 23342d59..cc6b8cb4 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,10 @@ VERSION[1.2.10][2016/11/21] * Added support for Unholy Might; you can enable it in the Configuration tab in the Combat section + * Added a Sort button to the "All items" list in the Items tab + * Improved keyboard interaction throughout the program: + * Enabled keyboard navigation for all lists + * 'Enter' now accepts confirmation popups, and other popups such as "Save As" + * Dropdown lists can be cycled with Up/Down as well as the mousewheel * Fixed Elreon's -mana cost modifier increasing the mana cost instead of decreasing it VERSION[1.2.9][2016/11/20] * Blade Flurry now shows DPS instead of average damage diff --git a/manifest.xml b/manifest.xml index 46a5a07d..5559acc8 100644 --- a/manifest.xml +++ b/manifest.xml @@ -7,9 +7,9 @@ - - - + + + @@ -21,34 +21,34 @@ - - - - + + + + - + - + - + - + - +