Files
coa-tsm/TradeSkillMaster/GUI/TSMWidgets/TSMGroupItemList.lua
T
Andrew6810 f3e579cb57 init
2022-11-05 21:19:42 -07:00

515 lines
17 KiB
Lua

-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- http://www.curse.com/addons/wow/tradeskill-master --
-- --
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) --
-- All Rights Reserved* - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
--[[-----------------------------------------------------------------------------
Group Item List Widget
Provides two scroll lists with buttons to move selected items from one list to the other.
-------------------------------------------------------------------------------]]
local TSM = select(2, ...)
local Type, Version = "TSMGroupItemList", 1
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster") -- loads the localization table
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
local ROW_HEIGHT = 16
--[[-----------------------------------------------------------------------------
Scripts
-------------------------------------------------------------------------------]]
local function ShowIcon(row)
row.iconFrame:Show()
row.label:SetPoint("TOPLEFT", 20, 0)
row.label:SetPoint("BOTTOMRIGHT")
end
local function HideIcon(row)
row.iconFrame:Hide()
row.label:SetPoint("TOPLEFT", 0, 0)
row.label:SetPoint("BOTTOMRIGHT")
end
local function UpdateScrollFrame(self)
local parent = self:GetParent()
if not parent.obj.GetListCallback then return end
parent.items = parent.obj.GetListCallback(parent == parent.obj.leftFrame and "left" or "right")
if not parent.list then
parent.list = {}
local usedItems = {}
for _, itemLink in ipairs(parent.items) do
local itemString = TSMAPI:GetItemString(itemLink)
local name, link, _, _, _, _, _, _, _, texture = TSMAPI:GetSafeItemInfo(itemString)
if itemString and name and texture and not usedItems[itemString] then
usedItems[itemString] = true
tinsert(parent.list, {value=itemString, link=link, icon=texture, sortText=strlower(name)})
end
end
sort(parent.list, function(a, b) return a.sortText < b.sortText end)
end
local rows = self.rows
-- clear all the rows
for _, v in pairs(rows) do
v.value = nil
v.label:SetText("")
v.iconFrame.icon:SetTexture("")
v:Hide()
end
local rowData = {}
for _, data in ipairs(self:GetParent().list) do
if not data.filtered then
tinsert(rowData, data)
end
end
local maxRows = floor((self.height-5)/(ROW_HEIGHT+2))
FauxScrollFrame_Update(self, #(rowData), maxRows-1, ROW_HEIGHT)
local offset = FauxScrollFrame_GetOffset(self)
local displayIndex = 0
-- make the rows bigger if the scroller isn't showing
if self:IsVisible() then
rows[1]:SetPoint("TOPRIGHT", self:GetParent(), -26, 0)
else
rows[1]:SetPoint("TOPRIGHT", self:GetParent(), -10, 0)
end
for index, data in ipairs(rowData) do
if index >= offset and displayIndex < maxRows then
displayIndex = displayIndex + 1
local row = rows[displayIndex]
row.label:SetText(data.link)
row.value = data.value
row.data = data
if data.selected then
row:LockHighlight()
else
row:UnlockHighlight()
end
if data.icon then
row.iconFrame.icon:SetTexture(data.icon)
ShowIcon(row)
else
HideIcon(row)
end
row:Show()
end
end
end
local function UpdateRows(parent)
local numRows = floor((parent.height-5)/(ROW_HEIGHT+2))
parent.rows = parent.rows or {}
for i=1, numRows do
if not parent.rows[i] then
local row = CreateFrame("Button", parent:GetName().."Row"..i, parent:GetParent())
row:SetHeight(ROW_HEIGHT)
row:SetScript("OnClick", function(self)
self.data.selected = not self.data.selected
if self.data.selected then
self:LockHighlight()
else
self:UnlockHighlight()
end
end)
row:SetScript("OnEnter", function(self)
GameTooltip:SetOwner(self, "ANCHOR_NONE")
GameTooltip:SetPoint("LEFT", parent:GetParent():GetParent(), "RIGHT")
TSMAPI:SafeTooltipLink(self.data.link)
GameTooltip:Show()
end)
-- row:SetScript("OnLeave", function() GameTooltip:Hide() BattlePetTooltip:Hide() end)
row:SetScript("OnLeave", function() GameTooltip:Hide() end)
if i > 1 then
row:SetPoint("TOPLEFT", parent.rows[i-1], "BOTTOMLEFT", 0, -2)
row:SetPoint("TOPRIGHT", parent.rows[i-1], "BOTTOMRIGHT", 0, -2)
else
row:SetPoint("TOPLEFT", parent, "TOPLEFT", 0, 0)
row:SetPoint("TOPRIGHT", parent, "TOPRIGHT", 4, 0)
end
-- highlight / selection texture for the row
local highlightTex = row:CreateTexture()
highlightTex:SetTexture("Interface\\Buttons\\UI-Listbox-Highlight")
highlightTex:SetPoint("TOPRIGHT", row, "TOPRIGHT", 0, 0)
highlightTex:SetPoint("BOTTOMLEFT")
highlightTex:SetAlpha(0.7)
row:SetHighlightTexture(highlightTex)
-- icon that goes to the left of the text
local iconFrame = CreateFrame("Frame", nil, row)
iconFrame:SetHeight(ROW_HEIGHT-2)
iconFrame:SetWidth(ROW_HEIGHT-2)
iconFrame:SetPoint("TOPLEFT")
row.iconFrame = iconFrame
-- texture that goes inside the iconFrame
local iconTexture = iconFrame:CreateTexture(nil, "BACKGROUND")
iconTexture:SetAllPoints(iconFrame)
iconTexture:SetVertexColor(1, 1, 1)
iconFrame.icon = iconTexture
local label = row:CreateFontString(nil, "OVERLAY")
label:SetFont(TSMAPI.Design:GetContentFont("normal"))
label:SetJustifyH("LEFT")
label:SetJustifyV("CENTER")
label:SetPoint("TOPLEFT", 20, 0)
label:SetPoint("BOTTOMRIGHT", 10, 0)
TSMAPI.Design:SetWidgetTextColor(label)
row.label = label
parent.rows[i] = row
end
end
UpdateScrollFrame(parent)
end
local function OnButtonClick(self)
local selected = {}
local rows, rowData
if self.type == "Add" then
rows = self.obj.leftFrame.scrollFrame.rows
rowData = self.obj.leftFrame.list
elseif self.type == "Remove" then
rows = self.obj.rightFrame.scrollFrame.rows
rowData = self.obj.rightFrame.list
end
if not rows then error("Invalid type") end
local temp = {}
for _, row in pairs(rows) do
if row.data and row.data.selected and row.value then
row.data.selected = false
row:UnlockHighlight()
temp[row.value] = true
tinsert(selected, row.value)
end
end
for _, data in pairs(rowData) do
if data.selected and data.value and not temp[data.value] then
data.selected = false
tinsert(selected, data.value)
end
end
self.obj:Fire("On"..self.type.."Clicked", selected)
end
local function OnFilterSet(self)
self:ClearFocus()
local text = strlower(TSMAPI:StrEscape(self:GetText():trim()))
local filterStr, minLevel, maxLevel, minILevel, maxILevel
for _, part in ipairs({("/"):split(text)}) do
part = part:trim()
if part ~= "" then
local lvl = tonumber(part)
local ilvl = gsub(part, "^i", "")
ilvl = tonumber(ilvl)
if lvl then
if not minLevel then
minLevel = lvl
elseif not maxLevel then
maxLevel = lvl
else
return TSM:Print(L["Invalid filter."])
end
elseif ilvl then
if not minILevel then
minILevel = ilvl
elseif not maxILevel then
maxILevel = ilvl
else
return TSM:Print(L["Invalid filter."])
end
else
if filterStr then
return TSM:Print(L["Invalid filter."])
end
filterStr = part
end
end
end
filterStr = filterStr or ""
minLevel = minLevel or 0
maxLevel = maxLevel or math.huge
minILevel = minILevel or 0
maxILevel = maxILevel or math.huge
for _, info in ipairs(self.obj.leftFrame.list) do
local name, _, _, ilvl, lvl = TSMAPI:GetSafeItemInfo(info.link)
local selected = (strfind(strlower(name), filterStr) and ilvl >= minILevel and ilvl <= maxILevel and lvl >= minLevel and lvl <= maxLevel)
info.selected = selected
info.filtered = not selected
end
for _, info in ipairs(self.obj.rightFrame.list) do
local name, _, _, ilvl, lvl = TSMAPI:GetSafeItemInfo(info.link)
local selected = (strfind(strlower(name), filterStr) and ilvl >= minILevel and ilvl <= maxILevel and lvl >= minLevel and lvl <= maxLevel)
info.selected = selected
info.filtered = not selected
end
FauxScrollFrame_SetOffset(self.obj.leftFrame.scrollFrame, 0)
FauxScrollFrame_SetOffset(self.obj.rightFrame.scrollFrame, 0)
UpdateScrollFrame(self.obj.leftFrame.scrollFrame)
UpdateScrollFrame(self.obj.rightFrame.scrollFrame)
end
local function OnClearButtonClicked(self)
for _, info in ipairs(self.obj.leftFrame.list) do
info.selected = false
end
for _, info in ipairs(self.obj.rightFrame.list) do
info.selected = false
end
UpdateScrollFrame(self.obj.leftFrame.scrollFrame)
UpdateScrollFrame(self.obj.rightFrame.scrollFrame)
end
local function OnIgnoreChanged(self, _, value)
TSM.db.global.ignoreRandomEnchants = value
self.obj.leftFrame.list = nil
UpdateScrollFrame(self.obj.leftFrame.scrollFrame)
end
--[[-----------------------------------------------------------------------------
Methods
-------------------------------------------------------------------------------]]
local methods = {
["OnAcquire"] = function(self)
-- restore default values
self:SetHeight(550)
TSMAPI:CreateTimeDelay(0.05, function() self.parent:DoLayout() end)
self.filter:SetText("")
self.ignoreCheckBox:SetValue(TSM.db.global.ignoreRandomEnchants)
end,
["OnRelease"] = function(self)
-- clear any points / other values
wipe(self.leftFrame.list)
wipe(self.rightFrame.list)
self.frame.leftTitle:SetText("")
self.frame.rightTitle:SetText("")
end,
["OnHeightSet"] = function(self, height)
if height == 100 then return end
self.leftScrollFrame.height = self.frame:GetHeight() - 85
self.rightScrollFrame.height = self.frame:GetHeight() - 85
UpdateRows(self.leftScrollFrame)
UpdateRows(self.rightScrollFrame)
end,
["SetListCallback"] = function(self, callback)
self.GetListCallback = callback
self.leftFrame.list = nil
self.rightFrame.list = nil
UpdateScrollFrame(self.leftScrollFrame)
UpdateScrollFrame(self.rightScrollFrame)
end,
["SetTitle"] = function(self, side, title)
if strlower(side) == "left" then
self.frame.leftTitle:SetText(title)
elseif strlower(side) == "right" then
self.frame.rightTitle:SetText(title)
elseif title then
error("Invalid side passed. Expected 'left' or 'right'")
end
end,
["SetIgnoreVisible"] = function(self, shown)
if shown then
self.ignoreCheckBox.frame:Show()
else
self.ignoreCheckBox.frame:Hide()
end
end,
}
--[[-----------------------------------------------------------------------------
Constructor
-------------------------------------------------------------------------------]]
local function Constructor()
local borderColor = TSM.db.profile.frameBackdropColor
local name = "TSMGroupItemList" .. AceGUI:GetNextWidgetNum(Type)
local frame = CreateFrame("Frame", name, UIParent)
frame:Hide()
local leftFrame = CreateFrame("Frame", name.."LeftFrame", frame)
leftFrame:SetPoint("TOPLEFT", 0, -80)
leftFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOM", -7, 0)
TSMAPI.Design:SetContentColor(leftFrame)
leftFrame.list = {}
frame.leftFrame = leftFrame
local leftTitle = frame:CreateFontString(nil, "OVERLAY")
leftTitle:SetFont(TSMAPI.Design:GetContentFont("normal"))
TSMAPI.Design:SetTitleTextColor(leftTitle)
leftTitle:SetJustifyH("LEFT")
leftTitle:SetJustifyV("BOTTOM")
leftTitle:SetHeight(15)
leftTitle:SetPoint("BOTTOMLEFT", leftFrame, "TOPLEFT", 8, 0)
leftTitle:SetPoint("BOTTOMRIGHT", leftFrame, "TOPRIGHT", -8, 0)
frame.leftTitle = leftTitle
local leftSF = CreateFrame("ScrollFrame", name.."LeftFrameScrollFrame", leftFrame, "FauxScrollFrameTemplate")
leftSF:SetPoint("TOPLEFT", 5, -5)
leftSF:SetPoint("BOTTOMRIGHT", -5, 5)
leftSF:SetScript("OnVerticalScroll", function(self, offset)
FauxScrollFrame_OnVerticalScroll(self, offset, ROW_HEIGHT, function() UpdateScrollFrame(self) end)
end)
leftFrame.scrollFrame = leftSF
local leftScrollBar = _G[leftSF:GetName().."ScrollBar"]
leftScrollBar:ClearAllPoints()
leftScrollBar:SetPoint("BOTTOMRIGHT")
leftScrollBar:SetPoint("TOPRIGHT")
leftScrollBar:SetWidth(12)
local thumbTex = leftScrollBar:GetThumbTexture()
thumbTex:SetPoint("CENTER")
TSMAPI.Design:SetFrameColor(thumbTex)
thumbTex:SetHeight(150)
thumbTex:SetWidth(leftScrollBar:GetWidth())
_G[leftScrollBar:GetName().."ScrollUpButton"]:Hide()
_G[leftScrollBar:GetName().."ScrollDownButton"]:Hide()
local rightFrame = CreateFrame("Frame", name.."RightFrame", frame)
rightFrame:SetPoint("TOPLEFT", frame, "TOP", 7, -80)
rightFrame:SetPoint("BOTTOMRIGHT", 0, 0)
TSMAPI.Design:SetContentColor(rightFrame)
rightFrame.list = {}
frame.rightFrame = rightFrame
local rightTitle = frame:CreateFontString(nil, "OVERLAY")
rightTitle:SetFont(TSMAPI.Design:GetContentFont("normal"))
TSMAPI.Design:SetTitleTextColor(rightTitle)
rightTitle:SetJustifyH("LEFT")
rightTitle:SetJustifyV("BOTTOM")
rightTitle:SetHeight(15)
rightTitle:SetPoint("BOTTOMLEFT", rightFrame, "TOPLEFT", 8, 0)
rightTitle:SetPoint("BOTTOMRIGHT", rightFrame, "TOPRIGHT", -8, 0)
frame.rightTitle = rightTitle
local rightSF = CreateFrame("ScrollFrame", name.."RightFrameScrollFrame", rightFrame, "FauxScrollFrameTemplate")
rightSF:SetPoint("TOPLEFT", 5, -5)
rightSF:SetPoint("BOTTOMRIGHT", -5, 5)
rightSF:SetScript("OnVerticalScroll", function(self, offset)
FauxScrollFrame_OnVerticalScroll(self, offset, ROW_HEIGHT, function() UpdateScrollFrame(self) end)
end)
rightFrame.scrollFrame = rightSF
local rightScrollBar = _G[rightSF:GetName().."ScrollBar"]
rightScrollBar:ClearAllPoints()
rightScrollBar:SetPoint("BOTTOMRIGHT")
rightScrollBar:SetPoint("TOPRIGHT")
rightScrollBar:SetWidth(12)
local thumbTex = rightScrollBar:GetThumbTexture()
thumbTex:SetPoint("CENTER")
TSMAPI.Design:SetFrameColor(thumbTex)
thumbTex:SetHeight(150)
thumbTex:SetWidth(rightScrollBar:GetWidth())
_G[rightScrollBar:GetName().."ScrollUpButton"]:Hide()
_G[rightScrollBar:GetName().."ScrollDownButton"]:Hide()
local label = TSMAPI.GUI:CreateLabel(frame, "normal")
label:SetText("Filter:")
label:SetPoint("TOPLEFT", 0, -5)
label:SetHeight(20)
label:SetJustifyV("CENTER")
local filter = TSMAPI.GUI:CreateInputBox(frame)
filter:SetPoint("BOTTOMLEFT", label, "BOTTOMRIGHT", 2, 0)
filter:SetHeight(20)
filter:SetWidth(150)
filter:SetScript("OnEnterPressed", OnFilterSet)
filter.tooltip = L["All items with names containing the specified filter will be selected. This makes it easier to add/remove multiple items at a time."]
local line = TSMAPI.GUI:CreateHorizontalLine(frame, 0)
line:SetPoint("TOPLEFT", 0, -58)
line:SetPoint("TOPRIGHT", 0, -58)
local line = TSMAPI.GUI:CreateVerticalLine(frame, 0)
line:ClearAllPoints()
line:SetPoint("TOP", 0, -60)
line:SetPoint("BOTTOM")
local ignoreCheckBox = TSMAPI.GUI:CreateCheckBox(frame, L["When checked, random enchants will be ignored for ungrouped items.\n\nNB: This will not affect parent group items that were already added with random enchants\n\nIf you have this checked when adding an ungrouped randomly enchanted item, it will act as all possible random enchants of that item."])
ignoreCheckBox:SetLabel(L["Ignore Random Enchants on Ungrouped Items"])
ignoreCheckBox:SetPoint("BOTTOMLEFT", filter, "BOTTOMRIGHT", 20, 5)
ignoreCheckBox:SetPoint("TOPRIGHT", 0, -2)
ignoreCheckBox:SetCallback("OnValueChanged", OnIgnoreChanged)
local addBtn = TSMAPI.GUI:CreateButton(frame, 18)
addBtn:SetPoint("TOPLEFT", 0, -33)
addBtn:SetWidth(170)
addBtn:SetHeight(20)
addBtn:SetText(L["Add >>>"])
addBtn.type = "Add"
addBtn:SetScript("OnClick", OnButtonClick)
local removeBtn = TSMAPI.GUI:CreateButton(frame, 18)
removeBtn:SetPoint("TOPRIGHT", 0, -33)
removeBtn:SetWidth(170)
removeBtn:SetHeight(20)
removeBtn:SetText(L["<<< Remove"])
removeBtn.type = "Remove"
removeBtn:SetScript("OnClick", OnButtonClick)
removeBtn.tooltip = L["You can hold shift while clicking this button to remove the items from ALL groups rather than keeping them in the parent group (if one exists)."]
local clearBtn = TSMAPI.GUI:CreateButton(frame, 16)
clearBtn:SetPoint("BOTTOMLEFT", addBtn, "BOTTOMRIGHT", 15, 0)
clearBtn:SetPoint("BOTTOMRIGHT", removeBtn, "BOTTOMLEFT", -15, 0)
clearBtn:SetHeight(20)
clearBtn:SetText(L["Clear Selection"])
clearBtn:SetScript("OnClick", OnClearButtonClicked)
clearBtn.tooltip = L["Deselects all items in both columns."]
local widget = {
leftFrame = leftFrame,
leftScrollFrame = leftSF,
rightFrame = rightFrame,
rightScrollFrame = rightSF,
ignoreCheckBox = ignoreCheckBox,
filter = filter,
clearBtn = clearBtn,
frame = frame,
type = Type
}
for method, func in pairs(methods) do
widget[method] = func
end
addBtn.obj = widget
removeBtn.obj = widget
widget.ignoreCheckBox.obj = widget
widget.filter.obj = widget
widget.clearBtn.obj = widget
widget.leftFrame.obj = widget
widget.rightFrame.obj = widget
widget.frame.obj = widget
return AceGUI:RegisterAsWidget(widget)
end
AceGUI:RegisterWidgetType(Type, Constructor, Version)