You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
373 lines
12 KiB
373 lines
12 KiB
-- ------------------------------------------------------------------------------ -- |
|
-- TradeSkillMaster -- |
|
-- http://www.curse.com/addons/wow/tradeskill-master -- |
|
-- -- |
|
-- A TradeSkillMaster Addon (http://tradeskillmaster.com) -- |
|
-- All Rights Reserved* - Detailed license information included with addon. -- |
|
-- ------------------------------------------------------------------------------ -- |
|
|
|
local TSM = select(2, ...) |
|
local L = LibStub("AceLocale-3.0"):GetLocale("TradeSkillMaster") -- loads the localization table |
|
|
|
local COUNT = 1 |
|
local ROW_HEIGHT = 14 |
|
|
|
|
|
local function UpdateTree(self) |
|
self.statusText:SetText("") |
|
local rowData = {} |
|
local groupPathList, disabledGroupPaths = TSM:GetGroupPathList(self.module) |
|
|
|
for i, groupPath in ipairs(groupPathList) do |
|
if not disabledGroupPaths[groupPath] then |
|
local pathParts = { TSM.GROUP_SEP:split(groupPath) } |
|
local leader = "" |
|
for i = 1, #pathParts - 1 do |
|
leader = leader .. " " |
|
end |
|
local hasSubGroups = (groupPathList[i + 1] and (groupPathList[i + 1] == groupPath or strfind(groupPathList[i + 1], "^" .. TSMAPI:StrEscape(groupPath) .. TSM.GROUP_SEP))) |
|
local parent = #pathParts > 1 and table.concat(pathParts, TSM.GROUP_SEP, 1, #pathParts - 1) or nil |
|
local index = #rowData + 1 |
|
if self.selectedGroups[groupPath] == nil then |
|
-- select group by default |
|
self.selectedGroups[groupPath] = true |
|
end |
|
local groupNameText = pathParts[#pathParts] |
|
if TSM.db.profile.colorGroupName then |
|
groupNameText = TSMAPI:ColorGroupName(groupNameText, #pathParts) |
|
end |
|
rowData[index] = { |
|
value = leader .. format("%s %s%s|r", groupNameText, TSMAPI.Design:GetInlineColor("link"), hasSubGroups and (self.collapsed[groupPath] and "[+]" or "[-]") or ""), |
|
groupName = pathParts[#pathParts], |
|
parent = parent, |
|
groupPath = groupPath, |
|
hasSubGroups = hasSubGroups, |
|
index = index, |
|
isSelected = not self.isGroupBox and self.selectedGroups[groupPath], -- select all rows by default (unless it's for a GroupBox) |
|
} |
|
end |
|
end |
|
|
|
if #rowData == 0 then |
|
if #groupPathList == 0 then |
|
self.statusText:SetText(L["You currently don't have any groups setup. Type '/tsm' and click on the 'TradeSkillMaster Groups' button to setup TSM groups."]) |
|
else |
|
self.statusText:SetText(format(L["None of your groups have %s operations assigned. Type '/tsm' and click on the 'TradeSkillMaster Groups' button to assign operations to your TSM groups."], self.module)) |
|
end |
|
else |
|
self.statusText:SetText("") |
|
end |
|
|
|
self.rowData = rowData |
|
self:RefreshRows() |
|
end |
|
|
|
local function SelectAll(self) |
|
for i = 1, #self.st.rowData do |
|
self.st.selectedGroups[self.st.rowData[i].groupPath] = true |
|
self.st.rowData[i].isSelected = true |
|
end |
|
self.st:RefreshRows() |
|
for _, row in ipairs(self.st.rows) do |
|
row.highlight:Show() |
|
end |
|
end |
|
|
|
local function DeselectAll(self) |
|
for i = 1, #self.st.rowData do |
|
self.st.selectedGroups[self.st.rowData[i].groupPath] = false |
|
self.st.rowData[i].isSelected = nil |
|
end |
|
self.st:RefreshRows() |
|
for _, row in ipairs(self.st.rows) do |
|
row.highlight:Hide() |
|
end |
|
end |
|
|
|
local methods = { |
|
GetRowIndex = function(self, value) |
|
for i, v in pairs(self.rowData) do |
|
if v.groupPath == value then |
|
return i |
|
end |
|
end |
|
end, |
|
RefreshRows = function(self) |
|
local offset = FauxScrollFrame_GetOffset(self.scrollFrame) |
|
self.offset = offset |
|
|
|
for i = #self.rowData, 1, -1 do |
|
local data = self.rowData[i] |
|
if not self.isGroupBox and not data.isSelected and data.parent then |
|
local index = self:GetRowIndex(data.parent) |
|
if index then |
|
self.rowData[index].isSelected = self.selectedGroups[self.rowData[index].groupPath] |
|
end |
|
end |
|
end |
|
|
|
local displayRows = {} |
|
for i = 1, #self.rowData do |
|
local pathParts = { TSM.GROUP_SEP:split(self.rowData[i].groupPath) } |
|
local isCollapsed = false |
|
for i = 1, #pathParts - 1 do |
|
local path = table.concat(pathParts, TSM.GROUP_SEP, 1, i) |
|
if self.collapsed[path] then |
|
isCollapsed = true |
|
break |
|
end |
|
end |
|
if not isCollapsed then |
|
if self.collapsed[self.rowData[i].groupPath] then |
|
self.rowData[i].value = gsub(self.rowData[i].value, TSMAPI:StrEscape("[-]"), "[+]") |
|
else |
|
self.rowData[i].value = gsub(self.rowData[i].value, TSMAPI:StrEscape("[+]"), "[-]") |
|
end |
|
tinsert(displayRows, self.rowData[i]) |
|
end |
|
end |
|
FauxScrollFrame_Update(self.scrollFrame, #displayRows, self.NUM_ROWS, ROW_HEIGHT) |
|
|
|
for i = 1, self.NUM_ROWS do |
|
if i > #displayRows then |
|
self.rows[i]:Hide() |
|
self.rows[i].data = nil |
|
else |
|
self.rows[i]:Show() |
|
local data = displayRows[i + offset] |
|
if not data then return end |
|
self.rows[i].data = data |
|
|
|
if data.isSelected or self.rows[i]:IsMouseOver() then |
|
self.rows[i].highlight:Show() |
|
else |
|
self.rows[i].highlight:Hide() |
|
end |
|
self.rows[i]:SetText(data.value) |
|
end |
|
end |
|
end, |
|
SetSelection = function(self, rowNum, isSelected) |
|
self.selectedGroups[self.rowData[rowNum].groupPath] = isSelected or false |
|
self.rowData[rowNum].isSelected = isSelected |
|
self:RefreshRows() |
|
end, |
|
GetSelectedGroupInfo = function(self, rowNum) |
|
local groupInfo = {} |
|
for _, data in ipairs(self.rowData) do |
|
if data.isSelected then |
|
groupInfo[data.groupPath] = { operations = TSM:GetGroupOperations(data.groupPath, self.module), items = TSM:GetGroupItems(data.groupPath) } |
|
if self.module and not groupInfo[data.groupPath].operations then |
|
groupInfo[data.groupPath] = nil |
|
end |
|
end |
|
end |
|
return groupInfo |
|
end, |
|
ClearSelection = function(self) |
|
for i = 1, #self.rowData do |
|
self.selectedGroups[self.rowData[i].groupPath] = false |
|
self.rowData[i].isSelected = nil |
|
end |
|
self.groupBoxSelection = nil |
|
self:RefreshRows() |
|
end, |
|
SetGropBoxSelection = function(self, groupPath) |
|
if self.groupBoxSelection then |
|
self.groupBoxSelection.isSelected = nil |
|
self.groupBoxSelection = nil |
|
end |
|
for i = 1, #self.rowData do |
|
if self.rowData[i].groupPath == groupPath then |
|
self.rowData[i].isSelected = true |
|
self.groupBoxSelection = self.rowData[i] |
|
break |
|
end |
|
end |
|
end, |
|
GetGroupBoxSelection = function(self) |
|
return self.groupBoxSelection and self.groupBoxSelection.groupPath |
|
end, |
|
} |
|
|
|
local defaultColScripts = { |
|
OnEnter = function(self) |
|
local tooltipLines = {} |
|
tinsert(tooltipLines, format(L["%sLeft-Click|r to select / deselect this group."], TSMAPI.Design:GetInlineColor("link"))) |
|
if self.data.hasSubGroups then |
|
tinsert(tooltipLines, format(L["%sRight-Click|r to collapse / expand this group."], TSMAPI.Design:GetInlineColor("link"))) |
|
end |
|
|
|
local operations = TSM:GetGroupOperations(self.data.groupPath, self.st.module) |
|
local operationLine = operations and table.concat(operations, ", ") or L["<No Operation>"] |
|
tinsert(tooltipLines, "") |
|
tinsert(tooltipLines, format(L["Operations: %s"], operationLine)) |
|
|
|
GameTooltip:SetOwner(self, "ANCHOR_TOP") |
|
GameTooltip:AddLine(table.concat(tooltipLines, "\n"), 1, 1, 1) |
|
GameTooltip:Show() |
|
|
|
self.highlight:Show() |
|
end, |
|
OnLeave = function(self) |
|
GameTooltip:Hide() |
|
if not self.data.isSelected then |
|
self.highlight:Hide() |
|
end |
|
end, |
|
OnClick = function(self, button) |
|
if button == "RightButton" then |
|
self.st.collapsed[self.data.groupPath] = not self.st.collapsed[self.data.groupPath] |
|
self.st:RefreshRows() |
|
return |
|
end |
|
if self.st.isGroupBox then |
|
if self.data ~= self.st.groupBoxSelection then |
|
if self.st.groupBoxSelection then |
|
self.st.groupBoxSelection.isSelected = false |
|
end |
|
self.st.groupBoxSelection = self.data |
|
end |
|
self.data.isSelected = true |
|
else |
|
self.data.isSelected = not self.data.isSelected |
|
self.st.selectedGroups[self.data.groupPath] = self.data.isSelected or false |
|
if self.data.hasSubGroups then |
|
for i = 1, #self.st.rowData do |
|
if self.st.rowData[i].groupPath == self.data.groupPath or strfind(self.st.rowData[i].groupPath, "^" .. TSMAPI:StrEscape(self.data.groupPath) .. TSM.GROUP_SEP) then |
|
self.st.selectedGroups[self.st.rowData[i].groupPath] = self.data.isSelected or false |
|
self.st.rowData[i].isSelected = self.data.isSelected |
|
end |
|
end |
|
end |
|
end |
|
self.st:RefreshRows() |
|
if self.data.isSelected then |
|
self.highlight:Show() |
|
else |
|
self.highlight:Hide() |
|
end |
|
end, |
|
} |
|
|
|
function TSMAPI:CreateGroupTree(parent, module, label, isGroupBox) |
|
assert(type(parent) == "table", format(L["Invalid parent argument type. Expected table, got %s."], type(parent))) |
|
|
|
local name = "TSMGroupTree" .. COUNT |
|
COUNT = COUNT + 1 |
|
local st = CreateFrame("Frame", name, parent) |
|
st:SetAllPoints() |
|
st:SetScript("OnShow", UpdateTree) |
|
st.NUM_ROWS = floor((parent:GetHeight() - (isGroupBox and 0 or 20)) / ROW_HEIGHT) |
|
st.isGroupBox = isGroupBox |
|
st.groupBoxSelection = nil |
|
st.module = module |
|
if label or module then |
|
label = label or module |
|
if not TSM.db.profile.groupTreeSelectedGroupStatus[label] then |
|
TSMAPI:CreateTimeDelay(0, function() SelectAll({st=st}) end) |
|
end |
|
TSM.db.profile.groupTreeCollapsedStatus[label] = TSM.db.profile.groupTreeCollapsedStatus[label] or {} |
|
TSM.db.profile.groupTreeSelectedGroupStatus[label] = TSM.db.profile.groupTreeSelectedGroupStatus[label] or {} |
|
st.collapsed = TSM.db.profile.groupTreeCollapsedStatus[label] |
|
st.selectedGroups = TSM.db.profile.groupTreeSelectedGroupStatus[label] |
|
else |
|
st.collapsed = {} |
|
st.selectedGroups = {} |
|
end |
|
|
|
local contentFrame = CreateFrame("Frame", name .. "Content", st) |
|
contentFrame:SetPoint("TOPLEFT") |
|
contentFrame:SetPoint("BOTTOMRIGHT", -15, isGroupBox and 0 or 18) |
|
st.contentFrame = contentFrame |
|
|
|
if not isGroupBox then |
|
local btn = TSMAPI.GUI:CreateButton(st, 14) |
|
btn:SetPoint("BOTTOMLEFT", 0, 2) |
|
btn:SetPoint("BOTTOMRIGHT", st, "BOTTOM", -2, 2) |
|
btn:SetHeight(16) |
|
btn:SetText(L["Select All Groups"]) |
|
btn:SetScript("OnClick", SelectAll) |
|
btn.st = st |
|
|
|
local btn = TSMAPI.GUI:CreateButton(st, 14) |
|
btn:SetPoint("BOTTOMLEFT", st, "BOTTOM", 2, 2) |
|
btn:SetPoint("BOTTOMRIGHT", 0, 2) |
|
btn:SetHeight(16) |
|
btn:SetText(L["Deselect All Groups"]) |
|
btn:SetScript("OnClick", DeselectAll) |
|
btn.st = st |
|
end |
|
|
|
-- frame to hold the rows |
|
local scrollFrame = CreateFrame("ScrollFrame", name .. "ScrollFrame", st, "FauxScrollFrameTemplate") |
|
scrollFrame:SetScript("OnVerticalScroll", function(self, offset) |
|
FauxScrollFrame_OnVerticalScroll(self, offset, ROW_HEIGHT, function() st:RefreshRows() end) |
|
end) |
|
scrollFrame:SetAllPoints(contentFrame) |
|
st.scrollFrame = scrollFrame |
|
|
|
-- make the scroll bar consistent with the TSM theme |
|
local scrollBar = _G[scrollFrame:GetName() .. "ScrollBar"] |
|
scrollBar:ClearAllPoints() |
|
scrollBar:SetPoint("BOTTOMRIGHT", st, -1, isGroupBox and 1 or 19) |
|
scrollBar:SetPoint("TOPRIGHT", st, -1, -1) |
|
scrollBar:SetWidth(12) |
|
local thumbTex = scrollBar:GetThumbTexture() |
|
thumbTex:SetPoint("CENTER") |
|
TSMAPI.Design:SetContentColor(thumbTex) |
|
thumbTex:SetHeight(50) |
|
thumbTex:SetWidth(scrollBar:GetWidth()) |
|
_G[scrollBar:GetName() .. "ScrollUpButton"]:Hide() |
|
_G[scrollBar:GetName() .. "ScrollDownButton"]:Hide() |
|
|
|
local text = st:CreateFontString() |
|
text:SetFont(TSMAPI.Design:GetContentFont("normal")) |
|
text:SetJustifyH("CENTER") |
|
text:SetJustifyV("CENTER") |
|
text:SetPoint("LEFT", 5, 0) |
|
text:SetPoint("RIGHT", -5, 0) |
|
text:SetHeight(100) |
|
text:SetNonSpaceWrap(true) |
|
st.statusText = text |
|
|
|
-- create the rows |
|
st.rows = {} |
|
for i = 1, st.NUM_ROWS do |
|
local row = CreateFrame("Button", name .. "Row" .. i, st.contentFrame) |
|
row:SetHeight(ROW_HEIGHT) |
|
row:RegisterForClicks("AnyUp") |
|
if i == 1 then |
|
row:SetPoint("TOPLEFT") |
|
row:SetPoint("TOPRIGHT") |
|
else |
|
row:SetPoint("TOPLEFT", st.rows[i - 1], "BOTTOMLEFT") |
|
row:SetPoint("TOPRIGHT", st.rows[i - 1], "BOTTOMRIGHT") |
|
end |
|
local highlight = row:CreateTexture() |
|
highlight:SetAllPoints() |
|
highlight:SetTexture(1, .9, 0, .2) |
|
highlight:Hide() |
|
row.highlight = highlight |
|
local text = row:CreateFontString() |
|
text:SetFont(TSMAPI.Design:GetContentFont("medium")) |
|
text:SetJustifyH("LEFT") |
|
text:SetJustifyV("CENTER") |
|
text:SetPoint("TOPLEFT", 1, -1) |
|
text:SetPoint("BOTTOMRIGHT", -1, 1) |
|
row:SetFontString(text) |
|
for name, func in pairs(defaultColScripts) do |
|
row:SetScript(name, func) |
|
end |
|
row.st = st |
|
tinsert(st.rows, row) |
|
end |
|
|
|
for name, func in pairs(methods) do |
|
st[name] = func |
|
end |
|
|
|
UpdateTree(st) |
|
|
|
return st |
|
end |