Mercurial > wow > inventory
changeset 132:8460855e3d90
Rewrote queueing module to insert a GUI.
Minor mover window changes.
author | Zerotorescue |
---|---|
date | Tue, 18 Jan 2011 00:30:15 +0100 |
parents | a27948591159 |
children | 2efe61ca718e |
files | Frames.lua Modules/Queue.lua Modules/Scanner.lua |
diffstat | 3 files changed, 726 insertions(+), 87 deletions(-) [+] |
line wrap: on
line diff
--- a/Frames.lua Tue Jan 18 00:28:24 2011 +0100 +++ b/Frames.lua Tue Jan 18 00:30:15 2011 +0100 @@ -4,7 +4,7 @@ -- If this function is called from a widget, self is the widget and self.frame the actual frame local this = self.frame or self; - if not this.tooltipTitle then return; end + if not this.tooltipTitle or addon.db.profile.defaults.hideHelp then return; end GameTooltip:SetOwner(this, "ANCHOR_NONE"); if this.tooltipLocation and this.tooltipLocation == "BOTTOM" then @@ -26,6 +26,10 @@ end function addon:CreateMoverFrame() + if InventoriumItemMover then + return; + end + local frameWidth = 400; -- Main window @@ -136,17 +140,16 @@ frame.lblDescription = lblDescription; -- Buttons - -- Move (proceed) - local btnMove = CreateFrame("Button", "$parentProceed", frame, "UIPanelButtonTemplate"); - btnMove:SetHeight(21); - btnMove:SetWidth(125); - btnMove:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 15, 11); - btnMove:SetText("Move Items"); - btnMove:SetScript("OnClick", function(this) this.OnClick(this); end); - btnMove:SetScript("OnEnter", ShowTooltip); - btnMove:SetScript("OnLeave", HideTooltip); + -- Proceed + local btnProceed = CreateFrame("Button", "$parentProceed", frame, "UIPanelButtonTemplate"); + btnProceed:SetHeight(21); + btnProceed:SetWidth(125); + btnProceed:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 15, 11); + btnProceed:SetScript("OnClick", function(this) this.OnClick(this); end); + btnProceed:SetScript("OnEnter", ShowTooltip); + btnProceed:SetScript("OnLeave", HideTooltip); - frame.btnMove = btnMove; + frame.btnProceed = btnProceed; -- Cancel local btnCancel = CreateFrame("Button", "$parentCancel", frame, "UIPanelButtonTemplate"); @@ -169,12 +172,12 @@ -- Scrolling table with a list of items to be moved local ScrollingTable = LibStub("ScrollingTable"); - local table = ScrollingTable:CreateST({}, 4, 15, nil, frame); -- inserting a dummy cols, real cols to be set in SetFrameSettings - table.frame:SetPoint("TOP", frame.lblDescription, "BOTTOM", 0, -18); - table.frame:SetPoint("LEFT", frame, "LEFT", 15, 0); - table.frame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -15, 35); + local scrollTable = ScrollingTable:CreateST({}, 4, 15, nil, frame); -- inserting a dummy cols, real cols to be set in SetFrameSettings + scrollTable.frame:SetPoint("TOP", frame.lblDescription, "BOTTOM", 0, -18); + scrollTable.frame:SetPoint("LEFT", frame, "LEFT", 15, 0); + scrollTable.frame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -15, 35); -- When moving over a row, provide a tooltip for the item - table:RegisterEvents({ + scrollTable:RegisterEvents({ ["OnEnter"] = function(rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...) if row and realrow then -- Data row @@ -205,7 +208,7 @@ end, }); - frame.scrollTable = table; + frame.scrollTable = scrollTable; -- Change the amount of displayed rows based on the size of the frame frame.AdjustScrollTableRows = function(this) @@ -223,7 +226,7 @@ InventoriumItemMover:Show(); end -function addon:SetFrameSettings(title, description, proceed, cancel, headers) +function addon:SetMoverFrameSettings(title, description, proceed, cancel, headers) local frame = InventoriumItemMover; frame.lblTitle:SetText(title); @@ -232,10 +235,10 @@ frame.lblDescription:SetText(description); - frame.btnMove:SetText(proceed.text); - frame.btnMove.tooltipTitle = proceed.tooltipTitle; - frame.btnMove.tooltip = proceed.tooltip; - frame.btnMove.OnClick = proceed.onClick; + frame.btnProceed:SetText(proceed.text); + frame.btnProceed.tooltipTitle = proceed.tooltipTitle; + frame.btnProceed.tooltip = proceed.tooltip; + frame.btnProceed.OnClick = proceed.onClick; frame.btnCancel:SetText(cancel.text); frame.btnCancel.tooltipTitle = cancel.tooltipTitle; @@ -244,3 +247,379 @@ frame.scrollTable:SetDisplayCols(headers); end + +function addon:CreateQueueFrame() + if InventoriumQueuer then + return; + end + + do + local frameWidth = 400; + + -- Main window + local frame = CreateFrame("Frame", "InventoriumQueuer", UIParent); + -- Hide by default + frame:Hide(); + -- Center the frame (will be adjusted later) + frame:SetPoint("CENTER", UIParent, "CENTER", 0, 0); + -- Put in front of other windows + frame:SetFrameStrata("FULLSCREEN_DIALOG"); + frame:SetToplevel(true); + -- Give it a size + frame:SetWidth(frameWidth); + frame:SetHeight(430); + -- Background + frame:SetBackdrop({ + bgFile = "Interface\\ChatFrame\\ChatFrameBackground", + edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", + edgeSize = 20, + insets = { + left = 5, + right = 5, + top = 5, + bottom = 5, + }, + }); + frame:SetBackdropColor(0, 0, 0, .8); + -- Mouse functions + frame:EnableMouse(); + frame:SetMovable(true); + -- Set event handlers + frame:SetScript("OnMouseUp", function(this) this:StopMovingOrSizing(); end); + frame:SetScript("OnShow", function(this) + this:AdjustScrollTableRows(); + end); + + -- Title (AceGUI frame-widget-title used as example) + local titleBackground = frame:CreateTexture(nil, "OVERLAY"); + titleBackground:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header"); + titleBackground:SetTexCoord(0.31, 0.67, 0, 0.63); + titleBackground:SetPoint("TOP", 0, 12); + titleBackground:SetWidth(150); + titleBackground:SetHeight(40); + + frame.titleBackground = titleBackground; + + local titleBackgroundLeft = frame:CreateTexture(nil, "OVERLAY"); + titleBackgroundLeft:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header"); + titleBackgroundLeft:SetTexCoord(0.21, 0.31, 0, 0.63); + titleBackgroundLeft:SetPoint("RIGHT", titleBackground, "LEFT"); + titleBackgroundLeft:SetWidth(30); + titleBackgroundLeft:SetHeight(40); + + local titleBackgroundRight = frame:CreateTexture(nil, "OVERLAY"); + titleBackgroundRight:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header"); + titleBackgroundRight:SetTexCoord(0.67, 0.77, 0, 0.63); + titleBackgroundRight:SetPoint("LEFT", titleBackground, "RIGHT"); + titleBackgroundRight:SetWidth(30); + titleBackgroundRight:SetHeight(40); + + local frmTitle = CreateFrame("Frame", nil, frame); + frmTitle:EnableMouse(true); + frmTitle:SetScript("OnMouseDown", function(this) this:GetParent():StartMoving(); end); + frmTitle:SetScript("OnMouseUp", function(this) this:GetParent():StopMovingOrSizing(); end); + frmTitle:SetAllPoints(titleBackground); + + local lblTitle = frmTitle:CreateFontString(nil, "OVERLAY", "GameFontNormal"); + lblTitle:SetPoint("TOP", titleBackground, "TOP", 0, -14); + + frame.lblTitle = lblTitle; + + -- Expand button + local btnExpander = CreateFrame("Button", "$parentExpander", frame); + btnExpander:SetWidth(32); + btnExpander:SetHeight(32); + btnExpander:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -10, -10); + btnExpander:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up"); + btnExpander:SetPushedTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Down"); + btnExpander:SetDisabledTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Disabled"); + btnExpander:SetHighlightTexture("Interface\\Buttons\\UI-Common-MouseHilight", "ADD"); + btnExpander.tooltipTitle = "Show unqueueables"; + btnExpander.tooltip = "Click to show a list of all unqueueable but tracked items."; + btnExpander:SetScript("OnEnter", ShowTooltip); + btnExpander:SetScript("OnLeave", HideTooltip); + btnExpander:SetScript("OnClick", function(this) + if this.Expanded then + -- Collapsing + this.Expanded = nil; + InventoriumQueuerUnqueueables:Hide(); + PlaySound("igCharacterInfoClose"); + + -- Next is an expand + this:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Up"); + this:SetPushedTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Down"); + this:SetDisabledTexture("Interface\\Buttons\\UI-SpellbookIcon-NextPage-Disabled"); + else + -- Expanding + this.Expanded = true; + + -- Position the frame against the queuer window + InventoriumQueuerUnqueueables:ClearAllPoints(); + InventoriumQueuerUnqueueables:SetPoint("TOPLEFT", this:GetParent(), "TOPRIGHT", 0, 0); + InventoriumQueuerUnqueueables:SetPoint("BOTTOMLEFT", this:GetParent(), "BOTTOMLEFT", 0, 0); + InventoriumQueuerUnqueueables:Show(); + PlaySound("igCharacterInfoOpen"); + + -- Next is a collapse + this:SetNormalTexture("Interface\\Buttons\\UI-SpellbookIcon-PrevPage-Up"); + this:SetPushedTexture("Interface\\Buttons\\UI-SpellbookIcon-PrevPage-Down"); + this:SetDisabledTexture("Interface\\Buttons\\UI-SpellbookIcon-PrevPage-Disabled"); + end + end); + + -- Description + local lblDescription = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal"); + lblDescription:SetPoint("TOPLEFT", frame, "TOPLEFT", 15, -27); + lblDescription:SetPoint("RIGHT", btnExpander, "LEFT", -15, 0); + lblDescription:SetJustifyH("LEFT"); + lblDescription:SetJustifyV("TOP"); + lblDescription:SetWidth(frameWidth - 70); + + frame.lblDescription = lblDescription; + + -- Buttons + -- Proceed + local btnProceed = CreateFrame("Button", "$parentProceed", frame, "UIPanelButtonTemplate"); + btnProceed:SetHeight(21); + btnProceed:SetWidth(125); + btnProceed:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 15, 11); + btnProceed:SetScript("OnClick", function(this) this.OnClick(this); end); + btnProceed:SetScript("OnEnter", ShowTooltip); + btnProceed:SetScript("OnLeave", HideTooltip); + + frame.btnProceed = btnProceed; + + -- Cancel + local btnCancel = CreateFrame("Button", "$parentCancel", frame, "UIPanelButtonTemplate"); + btnCancel:SetHeight(21); + btnCancel:SetWidth(125); + btnCancel:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -15, 11); + btnCancel:SetScript("OnClick", function(this) this.OnClick(this); end); + btnCancel:SetScript("OnEnter", ShowTooltip); + btnCancel:SetScript("OnLeave", HideTooltip); + + frame.btnCancel = btnCancel; + + -- Because the scrolling table code-behind will change the scrolltable element's height, we can't rely on that. Make a dummy frame which we can measure + local frmMeasureDummy = CreateFrame("Frame", nil, frame); + frmMeasureDummy:SetPoint("TOP", frame.lblDescription, "BOTTOM", 0, -18); + frmMeasureDummy:SetPoint("LEFT", frame, "LEFT", 15, 0); + frmMeasureDummy:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -15, 35); + + frame.frmMeasureDummy = frmMeasureDummy; + + -- Scrolling table with a list of items to be queued + local ScrollingTable = LibStub("ScrollingTable"); + local scrollTable = ScrollingTable:CreateST({}, 4, 15, nil, frame); -- inserting a dummy cols, real cols to be set in SetFrameSettings + scrollTable.frame:SetPoint("TOP", frame.lblDescription, "BOTTOM", 0, -18); + scrollTable.frame:SetPoint("LEFT", frame, "LEFT", 15, 0); + scrollTable.frame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -15, 35); + -- When moving over a row, provide a tooltip for the item + scrollTable:RegisterEvents({ + ["OnEnter"] = function(rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...) + if row and realrow then + -- Data row + + if data[realrow] and data[realrow].rowData and data[realrow].rowData.itemId then + GameTooltip:SetOwner(rowFrame, "ANCHOR_NONE"); + GameTooltip:SetPoint("TOPLEFT", rowFrame, "BOTTOMLEFT"); + GameTooltip:SetHyperlink(("item:%d"):format(data[realrow].rowData.itemId)); + GameTooltip:Show(); + end + else + -- Header row + + if cols[column].tooltipTitle and type(cols[column].tooltipTitle) == "string" then + cellFrame.tooltipTitle = cols[column].tooltipTitle; + if cols[column].tooltip then + cellFrame.tooltip = cols[column].tooltip; -- Optional + else + cellFrame.tooltip = nil; + end + + ShowTooltip(cellFrame); + end + end + end, + ["OnLeave"] = function(rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...) + HideTooltip(); + end, + }); + + frame.scrollTable = scrollTable; + + -- Change the amount of displayed rows based on the size of the frame + frame.AdjustScrollTableRows = function(this) + local newRows = math.floor(( this.frmMeasureDummy:GetHeight() - 5 ) / 15); + newRows = (newRows < 4 and 4) or newRows; + + this.scrollTable:SetDisplayRows(newRows, 15); + end; + frame:SetScript("OnSizeChanged", frame.AdjustScrollTableRows); + end + do + local frameWidth = 300; + + -- Main window + local frame = CreateFrame("Frame", "InventoriumQueuerUnqueueables", InventoriumQueuer); + -- Hide by default + frame:Hide(); + -- Position the frame against the queuer window + frame:SetPoint("TOPLEFT", InventoriumQueuer, "TOPRIGHT", 0, 0); + frame:SetPoint("BOTTOMLEFT", InventoriumQueuer, "BOTTOMLEFT", 0, 0); + -- Put in front of other windows + frame:SetFrameStrata("FULLSCREEN_DIALOG"); + frame:SetToplevel(true); + -- Give it a size + frame:SetWidth(frameWidth); + -- Background + frame:SetBackdrop({ + bgFile = "Interface\\ChatFrame\\ChatFrameBackground", + edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", + edgeSize = 20, + insets = { + left = 5, + right = 5, + top = 5, + bottom = 5, + }, + }); + frame:SetBackdropColor(0, 0, 0, .8); + -- Mouse functions + frame:EnableMouse(); + frame:SetMovable(true); + -- Set event handlers + frame:SetScript("OnMouseUp", function(this) this:StopMovingOrSizing(); end); + frame:SetScript("OnShow", function(this) + this:AdjustScrollTableRows(); + end); + + -- Title (AceGUI frame-widget-title used as example) + local titleBackground = frame:CreateTexture(nil, "OVERLAY"); + titleBackground:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header"); + titleBackground:SetTexCoord(0.31, 0.67, 0, 0.63); + titleBackground:SetPoint("TOP", 0, 12); + titleBackground:SetWidth(90); + titleBackground:SetHeight(40); + + frame.titleBackground = titleBackground; + + local titleBackgroundLeft = frame:CreateTexture(nil, "OVERLAY"); + titleBackgroundLeft:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header"); + titleBackgroundLeft:SetTexCoord(0.21, 0.31, 0, 0.63); + titleBackgroundLeft:SetPoint("RIGHT", titleBackground, "LEFT"); + titleBackgroundLeft:SetWidth(30); + titleBackgroundLeft:SetHeight(40); + + local titleBackgroundRight = frame:CreateTexture(nil, "OVERLAY"); + titleBackgroundRight:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header"); + titleBackgroundRight:SetTexCoord(0.67, 0.77, 0, 0.63); + titleBackgroundRight:SetPoint("LEFT", titleBackground, "RIGHT"); + titleBackgroundRight:SetWidth(30); + titleBackgroundRight:SetHeight(40); + + local frmTitle = CreateFrame("Frame", nil, frame); + frmTitle:EnableMouse(true); + frmTitle:SetScript("OnMouseDown", function(this) this:GetParent():StartMoving(); end); + frmTitle:SetScript("OnMouseUp", function(this) this:GetParent():StopMovingOrSizing(); end); + frmTitle:SetAllPoints(titleBackground); + + local lblTitle = frmTitle:CreateFontString(nil, "OVERLAY", "GameFontNormal"); + lblTitle:SetPoint("TOP", titleBackground, "TOP", 0, -14); + lblTitle:SetText("Unqueueables"); + + -- Because the scrolling table code-behind will change this element's height, we can't rely on that. Make a dummy frame which we can measure + local frmMeasureDummy = CreateFrame("Frame", nil, frame); + frmMeasureDummy:SetPoint("TOPLEFT", frame, "TOPLEFT", 15, -42); + frmMeasureDummy:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -15, 15); + + frame.frmMeasureDummy = frmMeasureDummy; + + -- Scrolling table with a list of items to be queued + local ScrollingTable = LibStub("ScrollingTable"); + local scrollTable = ScrollingTable:CreateST({}, 4, 15, nil, frame); -- inserting a dummy cols, real cols to be set in SetFrameSettings + scrollTable.frame:SetPoint("TOPLEFT", frame, "TOPLEFT", 15, -42); + scrollTable.frame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -15, 15); + -- When moving over a row, provide a tooltip for the item + scrollTable:RegisterEvents({ + ["OnEnter"] = function(rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...) + if row and realrow then + -- Data row + + if data[realrow] and data[realrow].rowData and data[realrow].rowData.itemId then + if column == 1 then + GameTooltip:SetOwner(rowFrame, "ANCHOR_NONE"); + GameTooltip:SetPoint("TOPLEFT", rowFrame, "BOTTOMLEFT"); + GameTooltip:SetHyperlink(("item:%d"):format(data[realrow].rowData.itemId)); + GameTooltip:Show(); + else + GameTooltip:SetOwner(cellFrame, "ANCHOR_NONE"); + GameTooltip:SetPoint("TOPLEFT", cellFrame, "BOTTOMLEFT"); + GameTooltip:SetText(data[realrow].rowData.reason[1]); + GameTooltip:AddLine(data[realrow].rowData.reason[2], 1, 1, 1, 1); + GameTooltip:Show(); + end + end + else + -- Header row + + if cols[column].tooltipTitle and type(cols[column].tooltipTitle) == "string" then + cellFrame.tooltipTitle = cols[column].tooltipTitle; + if cols[column].tooltip then + cellFrame.tooltip = cols[column].tooltip; -- Optional + else + cellFrame.tooltip = nil; + end + + ShowTooltip(cellFrame); + end + end + end, + ["OnLeave"] = function(rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...) + HideTooltip(); + end, + }); + + frame.scrollTable = scrollTable; + + -- Change the amount of displayed rows based on the size of the frame + frame.AdjustScrollTableRows = function(this) + local newRows = math.floor(( this.frmMeasureDummy:GetHeight() - 5 ) / 15); + newRows = (newRows < 4 and 4) or newRows; + + this.scrollTable:SetDisplayRows(newRows, 15); + end; + frame:SetScript("OnSizeChanged", frame.AdjustScrollTableRows); + end +end + +function addon:SetQueueFrameData(queueable, unqueueables) + InventoriumQueuer.scrollTable:SetData(queueable); + InventoriumQueuerUnqueueables.scrollTable:SetData(unqueueables); + + InventoriumQueuer:Show(); +end + +function addon:SetQueueFrameSettings(title, description, proceed, cancel, headers, unqueueablesHeaders) + local frame = InventoriumQueuer; + + frame.lblTitle:SetText(title); + -- Adjust size for the title background + frame.titleBackground:SetWidth((frame.lblTitle:GetWidth() or 0) + 10); -- 10 pixels margin + + frame.lblDescription:SetText(description); + + frame.btnProceed:SetText(proceed.text); + frame.btnProceed.tooltipTitle = proceed.tooltipTitle; + frame.btnProceed.tooltip = proceed.tooltip; + frame.btnProceed.OnClick = proceed.onClick; + + frame.btnCancel:SetText(cancel.text); + frame.btnCancel.tooltipTitle = cancel.tooltipTitle; + frame.btnCancel.tooltip = cancel.tooltip; + frame.btnCancel.OnClick = cancel.onClick; + + frame.scrollTable:SetDisplayCols(headers); + + InventoriumQueuerUnqueueables.scrollTable:SetDisplayCols(unqueueablesHeaders); +end
--- a/Modules/Queue.lua Tue Jan 18 00:28:24 2011 +0100 +++ b/Modules/Queue.lua Tue Jan 18 00:30:15 2011 +0100 @@ -1,7 +1,209 @@ local addon = select(2, ...); local mod = addon:NewModule("Queue", "AceEvent-3.0", "AceTimer-3.0"); -local pairs = pairs; +local _G = _G; +local tonumber, pairs, sformat, smatch, floor, ceil, tinsert, twipe = _G.tonumber, _G.pairs, _G.string.format, _G.string.match, _G.floor, _G.ceil, _G.table.insert, _G.table.wipe; + +local queue, skipped = {}, {}; + +-- strings are passed by reference, so it takes no additional memory if one string was used in a thousand tables compared to any other reference type +local skipReasons = { + ["LOW_VALUE"] = { "|cffff6633Underpriced|r", "The recorded auction value of this item is below your price threshold." }, + ["CAPPED"] = { "|cff66ff33Fully stocked|r", "The recorded item count is above or equal to your minimum global stock setting." }, + ["MIN_CRAFTING_QUEUE"] = { "|cffffff00Min crafting queue|r", "The amount of missing items is below or equal to your \"don't queue if I only miss\"-setting." }, + ["NO_ITEMCOUNT_ADDON"] = { "|cffff0000No itemcount addon|r", "No compatible item count could be found." }, + ["NOT_CRAFTABLE"] = { "|cff3d3d3dNot in profession|r", "This item is not part of this profession." }, +}; + +local function OnQueueCancel() + twipe(queue); + twipe(skipped); + + InventoriumQueuer:Hide(); +end + +local function OnQueueAccept() + -- Prepare a table with all possible tradeskill craftables + local craftables = mod:GetTradeskillCraftables(); + + for _, q in pairs(queue) do + if craftables[q.itemId] then + if mod:QueueWithAddon(craftables[q.itemId].no, ceil(q.amount / craftables[q.itemId].quantity), q.groupName) == -1 then + addon:Print("Couldn't queue, no supported crafting addon found.", addon.Colors.Red); + + OnQueueCancel(); + return; + end + else + addon:Debug("Lost %s", IdToItemLink(q.itemId)); + end + end + + twipe(queue); + twipe(skipped); + + InventoriumQueuer:Hide(); +end + +local function MakeQueueWindow() + do + local frame = InventoriumQueuer; -- both for speed as code-consistency + + -- Scrolling table with a list of items to be moved + local scrollTableWidth = ( frame.frmMeasureDummy:GetWidth() - 30 ); -- adjust width by the scrollbar size + local headers = { + { + ["name"] = "Item", + ["width"] = (scrollTableWidth * .60), + ["defaultsort"] = "asc", + ["comparesort"] = function(this, aRow, bRow, column) + local aName, _, aRarity = GetItemInfo(this:GetRow(aRow).rowData.itemId); + local bName, _, bRarity = GetItemInfo(this:GetRow(bRow).rowData.itemId); + local template = "%d%s"; + aName = template:format((10 - (aRarity or 10)), (aName or ""):lower()); + bName = template:format((10 - (bRarity or 10)), (bName or ""):lower()); + + if this.cols[column].sort == "dsc" then + return aName > bName; + else + return aName < bName; + end + end, + ["sort"] = "asc", -- when the data is set, use this column so sort the default data + ["tooltipTitle"] = (not addon.db.profile.defaults.hideHelp and "Item"), + ["tooltip"] = (not addon.db.profile.defaults.hideHelp and "Click to sort the list by item quality then item name."), + }, + { + ["name"] = "Amount", + ["width"] = (scrollTableWidth * .20), + ["align"] = "RIGHT", + ["defaultsort"] = "dsc", + ["sortnext"] = 1, + ["tooltipTitle"] = (not addon.db.profile.defaults.hideHelp and "Amount"), + ["tooltip"] = (not addon.db.profile.defaults.hideHelp and "Click to sort the list by the amount of items to be queued."), + }, + { + ["name"] = "Extra", + ["width"] = (scrollTableWidth * .20), + ["align"] = "RIGHT", + ["defaultsort"] = "dsc", + ["sortnext"] = 1, + ["tooltipTitle"] = (not addon.db.profile.defaults.hideHelp and "Extra"), + ["tooltip"] = (not addon.db.profile.defaults.hideHelp and "Click to sort the list by the amount of bonus items."), + }, + }; + + local scrollTableWidth = ( InventoriumQueuerUnqueueables.frmMeasureDummy:GetWidth() - 30 ); -- adjust width by the scrollbar size + local unqueueablesHeaders = { + { + ["name"] = "Item", + ["width"] = (scrollTableWidth * .6), + ["defaultsort"] = "asc", + ["comparesort"] = function(this, aRow, bRow, column) + local aName, _, aRarity = GetItemInfo(this:GetRow(aRow).rowData.itemId); + local bName, _, bRarity = GetItemInfo(this:GetRow(bRow).rowData.itemId); + local template = "%d%s"; + aName = template:format((10 - (aRarity or 10)), (aName or ""):lower()); + bName = template:format((10 - (bRarity or 10)), (bName or ""):lower()); + + if this.cols[column].sort == "dsc" then + return aName > bName; + else + return aName < bName; + end + end, + ["sort"] = "asc", -- when the data is set, use this column so sort the default data + ["tooltipTitle"] = (not addon.db.profile.defaults.hideHelp and "Item"), + ["tooltip"] = (not addon.db.profile.defaults.hideHelp and "Click to sort the list by item quality then item name."), + }, + { + ["name"] = "Reason", + ["width"] = (scrollTableWidth * .4), + ["defaultsort"] = "dsc", + ["sortnext"] = 1, + ["tooltipTitle"] = (not addon.db.profile.defaults.hideHelp and "Reason"), + ["tooltip"] = (not addon.db.profile.defaults.hideHelp and "Click to sort the list by the reason the items couldn't be queued."), + }, + }; + + local proceedButton = { + text = "Queue", + tooltipTitle = (not addon.db.profile.defaults.hideHelp and "Queue"), + tooltip = (not addon.db.profile.defaults.hideHelp and "Add these items to the queue of your crafting addon."), + onClick = OnQueueAccept, + }; + local cancelButton = { + text = "Cancel", + tooltipTitle = (not addon.db.profile.defaults.hideHelp and "Cancel"), + tooltip = (not addon.db.profile.defaults.hideHelp and "Do not queue anything and close the window."), + onClick = OnQueueCancel, + }; + + addon:SetQueueFrameSettings("Inventorium Queue", "The following items can be added to the queue of your crafting addon. Do you wish to proceed?", proceedButton, cancelButton, headers, unqueueablesHeaders); + end +end + +local function DisplayQueue() + MakeQueueWindow(); + + -- This table is never copied, just referenced. It is the same for every row. + local queueablesColumns = { + { + ["value"] = function(data, cols, realrow, column, table) + return IdToItemLink(data[realrow].rowData.itemId); + end, + }, -- item + { + ["value"] = function(data, cols, realrow, column, table) + return data[realrow].rowData.amount; + end, + }, -- amount + { + ["value"] = function(data, cols, realrow, column, table) + return (data[realrow].rowData.bonus == 0 and 0) or "+" .. data[realrow].rowData.bonus; + end, + ["color"] = function(data, cols, realrow, column, table) + return ((data[realrow].rowData.bonus == 0) and { r = 1, g = 1, b = 1, a = 0.5 }) or { r = 0, g = 1, b = 0, a = 1 }; + end, + }, -- extra + }; + + -- Store the list with rows in this + local queueables = {}; + + for _, q in pairs(queue) do + tinsert(queueables, { + ["rowData"] = q, -- this is not a key usually found in a row item and ignored by the library + ["cols"] = queueablesColumns, + }); + end + + -- This table is never copied, just referenced. It is the same for every row. + local unqueueablesColumns = { + { + ["value"] = function(data, cols, realrow, column, table) + return IdToItemLink(data[realrow].rowData.itemId); + end, + }, -- item + { + ["value"] = function(data, cols, realrow, column, table) + return data[realrow].rowData.reason[1]; + end, + }, -- reason + }; + + -- Store the list with rows in this + local unqueueables = {}; + + for _, s in pairs(skipped) do + tinsert(unqueueables, { + ["rowData"] = s, -- this is not a key usually found in a row item and ignored by the library + ["cols"] = unqueueablesColumns, + }); + end + + addon:SetQueueFrameData(queueables, unqueueables); +end function mod:OnEnable() -- Register our own slash commands @@ -12,6 +214,10 @@ self:RegisterMessage("IM_QUEUE_ALL"); self:RegisterMessage("IM_QUEUE_GROUP"); + + if not InventoriumQueuer then + addon:CreateQueueFrame(OnMoveAccept, OnMoveCancel); + end end function mod:IM_QUEUE_ALL() @@ -23,6 +229,13 @@ end function mod:QueueAll() + -- Prepare a table with all possible tradeskill craftables + local craftables = self:GetTradeskillCraftables(); + + -- Forget old queue + twipe(queue); + twipe(skipped); + local playerName = UnitName("player"); -- Go through all groups @@ -30,108 +243,108 @@ local trackAt = addon:GetOptionByKey(groupName, "trackAtCharacters"); if trackAt[playerName] then - self:QueueGroup(groupName); + self:QueueGroup(groupName, craftables); end end + + DisplayQueue(); end -function mod:QueueGroup(groupName) - if not addon.db.profile.groups[groupName] then - addon:Print(("Tried to queue items from a group named \"%s\", but no such group exists."):format(groupName), addon.Colors.Red); +function mod:QueueGroup(groupName, craftables) + -- Prepare a table with all possible tradeskill craftables + if not craftables then + craftables = self:GetTradeskillCraftables(); -- nil when no tradeskill window is open + end + + if not craftables then + addon:Print("No tradeskill window detected.", addon.Colors.Red); + return; + elseif not addon.db.profile.groups[groupName] then + addon:Print(sformat("Tried to queue items from a group named \"%s\", but no such group exists.", groupName), addon.Colors.Red); + return; + elseif not addon.db.profile.groups[groupName].items then + addon:Debug("This group (%s) has no items.", groupName); return; end - local temp = {}; + -- Retrieve group settings + local restockTarget = addon:GetOptionByKey(groupName, "restockTarget"); + local bonusQueue = addon:GetOptionByKey(groupName, "bonusQueue"); + local minCraftingQueue = floor( addon:GetOptionByKey(groupName, "minCraftingQueue") * restockTarget ); -- If the minCraftingQueue is 5% and restockTarget is 60, this will result in 3 + local priceThreshold = addon:GetOptionByKey(groupName, "priceThreshold"); - local tradeskillName, currentLevel, maxLevel = GetTradeSkillLine(); - - if tradeskillName ~= "UNKNOWN" then - -- Go through all trade skills for the profession - for i = 1, GetNumTradeSkills() do - -- Process every single tradeskill - self:ProcessTradeSkill(i, groupName, temp); - end - end - - if addon.db.profile.groups[groupName].items then - for itemId, _ in pairs(addon.db.profile.groups[groupName].items) do - if not temp[itemId] then - local itemLink = select(2, GetItemInfo(itemId)); - - addon:Print(("Couldn't queue %s (not part of this profession)"):format((itemLink or itemId or "???")), addon.Colors.Orange); - end - end - end -end - -function mod:ProcessTradeSkill(i, groupName, temp) - -- Try to retrieve the itemlink, this will be nil if current item is a group instead - local itemLink = GetTradeSkillItemLink(i); - - if itemLink then - local itemId = addon:GetItemId(itemLink); - if not itemId then - -- If this isn't an item, it can only be an enchant instead - itemId = tonumber(itemLink:match("|Henchant:([-0-9]+)|h")); - - itemId = addon.scrollIds[itemId]; -- change enchantIds into scrollIds - end - - if addon.db.profile.groups[groupName].items and addon.db.profile.groups[groupName].items[itemId] then - -- This item is in this group, queue it! - - if temp then - -- Remember which items have been processed - temp[itemId] = true; - end - + for itemId in pairs(addon.db.profile.groups[groupName].items) do + if craftables[itemId] then local currentStock = addon:GetItemCount(itemId, groupName); if currentStock >= 0 then -- Current stock will be -1 when no itemcount addon was found - -- Retrieve group settings - local restockTarget = addon:GetOptionByKey(groupName, "restockTarget"); - local bonusQueue = addon:GetOptionByKey(groupName, "bonusQueue"); - local minCraftingQueue = floor( addon:GetOptionByKey(groupName, "minCraftingQueue") * restockTarget ); -- If the minCraftingQueue is 5% and restockTarget is 60, this will result in 3 - -- Calculate the amount to be queued local amount = ( restockTarget - currentStock ); + local bonus = 0; if currentStock == 0 and bonusQueue > 0 then -- If we have none left and the bonus queue is enabled, modify the amount to be queued - amount = floor( ( amount * ( bonusQueue + 1 ) ) + .5 ); -- round + bonus = floor( ( amount * ( bonusQueue ) ) + .5 ); -- round + + -- Update amount + amount = (amount + bonus); end if amount > 0 and amount >= minCraftingQueue then -- If we are queueing at least one AND more than the minimum amount, then proceed -- Auction value settings - local priceThreshold = addon:GetOptionByKey(groupName, "priceThreshold"); local value = (priceThreshold ~= 0 and addon:GetAuctionValue(itemLink, groupName)); if priceThreshold == 0 or value == -1 or value >= priceThreshold then -- If no price threshold is set or the auction value is equal to or larger than the price threshold, then proceed - self:Queue(i, amount, groupName); - - addon:Print(("Queued %d of %s"):format(amount, itemLink)); + self:Queue(itemId, amount, bonus, groupName); + else + self:Skip(itemId, skipReasons.LOW_VALUE); + end + else + if amount <= 0 then + self:Skip(itemId, skipReasons.CAPPED); + else + self:Skip(itemId, skipReasons.MIN_CRAFTING_QUEUE); end end else + self:Skip(itemId, skipReasons.NO_ITEMCOUNT_ADDON); addon:Print("No usable itemcount addon found."); + return; end + else + self:Skip(itemId, skipReasons.NOT_CRAFTABLE); end end end -function mod:Queue(tradeSkillIndex, amount, group) +function mod:Queue(itemId, amount, bonus, groupName) + tinsert(queue, { + ["itemId"] = itemId, + ["amount"] = amount, + ["bonus"] = bonus, + ["groupName"] = groupName, + }); +end + +function mod:Skip(itemId, reason) + tinsert(skipped, { + ["itemId"] = itemId, + ["reason"] = reason, + }); +end + +function mod:QueueWithAddon(tradeSkillIndex, amount, group) + -- Sanity check tradeSkillIndex = tonumber(tradeSkillIndex); amount = tonumber(amount); - if not tradeSkillIndex or not amount then return; end - local selectedExternalAddon = addon:GetOptionByKey(group, "craftingAddon"); if addon.supportedAddons.crafting[selectedExternalAddon] and addon.supportedAddons.crafting[selectedExternalAddon].IsEnabled() then @@ -148,5 +361,52 @@ end end - return -2; + return -1; end + +-- Expand all categories +local function ExpandSubClasses() + for i = GetNumTradeSkills(), 1, -1 do + local _, skillType, _, isExpanded = GetTradeSkillInfo(i); + + if skillType == "header" and not isExpanded then + ExpandTradeSkillSubClass(i); + end + end +end + +function mod:GetTradeskillCraftables() + local craftables = {}; + + if GetTradeSkillLine() ~= "UNKNOWN" then + ExpandSubClasses(); + + -- Cache all craftable items + for i = 1, GetNumTradeSkills() do + local itemLink = GetTradeSkillItemLink(i); + + if itemLink then + local itemId = addon:GetItemId(itemLink); + if not itemId then + -- If this isn't an item, it can only be an enchant instead + itemId = tonumber(smatch(itemLink, "|Henchant:([-0-9]+)|h")); + + itemId = addon.scrollIds[itemId]; -- change enchantIds into scrollIds + end + + -- Remember the average amount of items created per craft (doesn't need to be a round number, since we multiply this by the amount of items to be queued we're better off rounding at that time) + local minMade, maxMade = GetTradeSkillNumMade(i); + local average = ((minMade == maxMade) and minMade) or ((minMade + maxMade) / 2); + + craftables[itemId] = { + ["no"] = i, + ["quantity"] = average, + }; + end + end + else + return; + end + + return craftables; +end
--- a/Modules/Scanner.lua Tue Jan 18 00:28:24 2011 +0100 +++ b/Modules/Scanner.lua Tue Jan 18 00:30:15 2011 +0100 @@ -105,7 +105,7 @@ onClick = OnMoveCancel, }; - addon:SetFrameSettings("Inventorium Storage Refill", "The items listed below can be refilled from this location, do you wish to move them to your bags?", proceedButton, cancelButton, headers); + addon:SetMoverFrameSettings("Inventorium Storage Refill", "The items listed below can be refilled from this location, do you wish to move them to your bags?", proceedButton, cancelButton, headers); end -- Merchant restock window: restock from a merchant by buying items needed @@ -169,7 +169,7 @@ onClick = OnMoveCancel, }; - addon:SetFrameSettings("Inventorium Merchant Restock", ("The following items can be restocked from this merchant for a total of %s. Do you wish to proceed?"):format(GetSmallCoinTextureString(totalCost)), proceedButton, cancelButton, headers); + addon:SetMoverFrameSettings("Inventorium Merchant Restock", ("The following items can be restocked from this merchant for a total of %s. Do you wish to proceed?"):format(GetSmallCoinTextureString(totalCost)), proceedButton, cancelButton, headers); end function mod:ClearCache() @@ -627,7 +627,7 @@ Mover = addon:GetModule("Mover"); if not InventoriumItemMover then - addon:CreateMoverFrame(OnMoveAccept, OnMoveCancel); + addon:CreateMoverFrame(); end end