Zerotorescue@0: --[[----------------------------------------------------------------------------- Zerotorescue@0: TreeGroup Container Zerotorescue@0: Container that uses a tree control to switch between groups. Zerotorescue@0: -------------------------------------------------------------------------------]] Zerotorescue@0: local Type, Version = "TreeGroup", 30 Zerotorescue@0: local AceGUI = LibStub and LibStub("AceGUI-3.0", true) Zerotorescue@0: if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end Zerotorescue@0: Zerotorescue@0: -- Lua APIs Zerotorescue@0: local next, pairs, ipairs, assert, type = next, pairs, ipairs, assert, type Zerotorescue@0: local math_min, math_max, floor = math.min, math.max, floor Zerotorescue@0: local select, tremove, unpack = select, table.remove, unpack Zerotorescue@0: Zerotorescue@0: -- WoW APIs Zerotorescue@0: local CreateFrame, UIParent = CreateFrame, UIParent Zerotorescue@0: Zerotorescue@0: -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded Zerotorescue@0: -- List them here for Mikk's FindGlobals script Zerotorescue@0: -- GLOBALS: GameTooltip, FONT_COLOR_CODE_CLOSE Zerotorescue@0: Zerotorescue@0: -- Recycling functions Zerotorescue@0: local new, del Zerotorescue@0: do Zerotorescue@0: local pool = setmetatable({},{__mode='k'}) Zerotorescue@0: function new() Zerotorescue@0: local t = next(pool) Zerotorescue@0: if t then Zerotorescue@0: pool[t] = nil Zerotorescue@0: return t Zerotorescue@0: else Zerotorescue@0: return {} Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: function del(t) Zerotorescue@0: for k in pairs(t) do Zerotorescue@0: t[k] = nil Zerotorescue@0: end Zerotorescue@0: pool[t] = true Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local DEFAULT_TREE_WIDTH = 175 Zerotorescue@0: local DEFAULT_TREE_SIZABLE = true Zerotorescue@0: Zerotorescue@0: --[[----------------------------------------------------------------------------- Zerotorescue@0: Support functions Zerotorescue@0: -------------------------------------------------------------------------------]] Zerotorescue@0: local function GetButtonUniqueValue(line) Zerotorescue@0: local parent = line.parent Zerotorescue@0: if parent and parent.value then Zerotorescue@0: return GetButtonUniqueValue(parent).."\001"..line.value Zerotorescue@0: else Zerotorescue@0: return line.value Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function UpdateButton(button, treeline, selected, canExpand, isExpanded) Zerotorescue@0: local self = button.obj Zerotorescue@0: local toggle = button.toggle Zerotorescue@0: local frame = self.frame Zerotorescue@0: local text = treeline.text or "" Zerotorescue@0: local icon = treeline.icon Zerotorescue@0: local iconCoords = treeline.iconCoords Zerotorescue@0: local level = treeline.level Zerotorescue@0: local value = treeline.value Zerotorescue@0: local uniquevalue = treeline.uniquevalue Zerotorescue@0: local disabled = treeline.disabled Zerotorescue@0: Zerotorescue@0: button.treeline = treeline Zerotorescue@0: button.value = value Zerotorescue@0: button.uniquevalue = uniquevalue Zerotorescue@0: if selected then Zerotorescue@0: button:LockHighlight() Zerotorescue@0: button.selected = true Zerotorescue@0: else Zerotorescue@0: button:UnlockHighlight() Zerotorescue@0: button.selected = false Zerotorescue@0: end Zerotorescue@0: local normalTexture = button:GetNormalTexture() Zerotorescue@0: local line = button.line Zerotorescue@0: button.level = level Zerotorescue@0: if ( level == 1 ) then Zerotorescue@0: button:SetNormalFontObject("GameFontNormal") Zerotorescue@0: button:SetHighlightFontObject("GameFontHighlight") Zerotorescue@0: button.text:SetPoint("LEFT", (icon and 16 or 0) + 8, 2) Zerotorescue@0: else Zerotorescue@0: button:SetNormalFontObject("GameFontHighlightSmall") Zerotorescue@0: button:SetHighlightFontObject("GameFontHighlightSmall") Zerotorescue@0: button.text:SetPoint("LEFT", (icon and 16 or 0) + 8 * level, 2) Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: if disabled then Zerotorescue@0: button:EnableMouse(false) Zerotorescue@0: button.text:SetText("|cff808080"..text..FONT_COLOR_CODE_CLOSE) Zerotorescue@0: else Zerotorescue@0: button.text:SetText(text) Zerotorescue@0: button:EnableMouse(true) Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: if icon then Zerotorescue@0: button.icon:SetTexture(icon) Zerotorescue@0: button.icon:SetPoint("LEFT", 8 * level, (level == 1) and 0 or 1) Zerotorescue@0: else Zerotorescue@0: button.icon:SetTexture(nil) Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: if iconCoords then Zerotorescue@0: button.icon:SetTexCoord(unpack(iconCoords)) Zerotorescue@0: else Zerotorescue@0: button.icon:SetTexCoord(0, 1, 0, 1) Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: if canExpand then Zerotorescue@0: if not isExpanded then Zerotorescue@0: toggle:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-UP") Zerotorescue@0: toggle:SetPushedTexture("Interface\\Buttons\\UI-PlusButton-DOWN") Zerotorescue@0: else Zerotorescue@0: toggle:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-UP") Zerotorescue@0: toggle:SetPushedTexture("Interface\\Buttons\\UI-MinusButton-DOWN") Zerotorescue@0: end Zerotorescue@0: toggle:Show() Zerotorescue@0: else Zerotorescue@0: toggle:Hide() Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function ShouldDisplayLevel(tree) Zerotorescue@0: local result = false Zerotorescue@0: for k, v in ipairs(tree) do Zerotorescue@0: if v.children == nil and v.visible ~= false then Zerotorescue@0: result = true Zerotorescue@0: elseif v.children then Zerotorescue@0: result = result or ShouldDisplayLevel(v.children) Zerotorescue@0: end Zerotorescue@0: if result then return result end Zerotorescue@0: end Zerotorescue@0: return false Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function addLine(self, v, tree, level, parent) Zerotorescue@0: local line = new() Zerotorescue@0: line.value = v.value Zerotorescue@0: line.text = v.text Zerotorescue@0: line.icon = v.icon Zerotorescue@0: line.iconCoords = v.iconCoords Zerotorescue@0: line.disabled = v.disabled Zerotorescue@0: line.tree = tree Zerotorescue@0: line.level = level Zerotorescue@0: line.parent = parent Zerotorescue@0: line.visible = v.visible Zerotorescue@0: line.uniquevalue = GetButtonUniqueValue(line) Zerotorescue@0: if v.children then Zerotorescue@0: line.hasChildren = true Zerotorescue@0: else Zerotorescue@0: line.hasChildren = nil Zerotorescue@0: end Zerotorescue@0: self.lines[#self.lines+1] = line Zerotorescue@0: return line Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: --fire an update after one frame to catch the treeframes height Zerotorescue@0: local function FirstFrameUpdate(frame) Zerotorescue@0: local self = frame.obj Zerotorescue@0: frame:SetScript("OnUpdate", nil) Zerotorescue@0: self:RefreshTree() Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function BuildUniqueValue(...) Zerotorescue@0: local n = select('#', ...) Zerotorescue@0: if n == 1 then Zerotorescue@0: return ... Zerotorescue@0: else Zerotorescue@0: return (...).."\001"..BuildUniqueValue(select(2,...)) Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: --[[----------------------------------------------------------------------------- Zerotorescue@0: Scripts Zerotorescue@0: -------------------------------------------------------------------------------]] Zerotorescue@0: local function Expand_OnClick(frame) Zerotorescue@0: local button = frame.button Zerotorescue@0: local self = button.obj Zerotorescue@0: local status = (self.status or self.localstatus).groups Zerotorescue@0: status[button.uniquevalue] = not status[button.uniquevalue] Zerotorescue@0: self:RefreshTree() Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function Button_OnClick(frame) Zerotorescue@0: local self = frame.obj Zerotorescue@0: self:Fire("OnClick", frame.uniquevalue, frame.selected) Zerotorescue@0: if not frame.selected then Zerotorescue@0: self:SetSelected(frame.uniquevalue) Zerotorescue@0: frame.selected = true Zerotorescue@0: frame:LockHighlight() Zerotorescue@0: self:RefreshTree() Zerotorescue@0: end Zerotorescue@0: AceGUI:ClearFocus() Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function Button_OnDoubleClick(button) Zerotorescue@0: local self = button.obj Zerotorescue@0: local status = self.status or self.localstatus Zerotorescue@0: local status = (self.status or self.localstatus).groups Zerotorescue@0: status[button.uniquevalue] = not status[button.uniquevalue] Zerotorescue@0: self:RefreshTree() Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function Button_OnEnter(frame) Zerotorescue@0: local self = frame.obj Zerotorescue@0: self:Fire("OnButtonEnter", frame.uniquevalue, frame) Zerotorescue@0: Zerotorescue@0: if self.enabletooltips then Zerotorescue@0: GameTooltip:SetOwner(frame, "ANCHOR_NONE") Zerotorescue@0: GameTooltip:SetPoint("LEFT",frame,"RIGHT") Zerotorescue@0: GameTooltip:SetText(frame.text:GetText() or "", 1, .82, 0, 1) Zerotorescue@0: Zerotorescue@0: GameTooltip:Show() Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function Button_OnLeave(frame) Zerotorescue@0: local self = frame.obj Zerotorescue@0: self:Fire("OnButtonLeave", frame.uniquevalue, frame) Zerotorescue@0: Zerotorescue@0: if self.enabletooltips then Zerotorescue@0: GameTooltip:Hide() Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function OnScrollValueChanged(frame, value) Zerotorescue@0: if frame.obj.noupdate then return end Zerotorescue@0: local self = frame.obj Zerotorescue@0: local status = self.status or self.localstatus Zerotorescue@0: status.scrollvalue = value Zerotorescue@0: self:RefreshTree() Zerotorescue@0: AceGUI:ClearFocus() Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function Tree_OnSizeChanged(frame) Zerotorescue@0: frame.obj:RefreshTree() Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function Tree_OnMouseWheel(frame, delta) Zerotorescue@0: local self = frame.obj Zerotorescue@0: if self.showscroll then Zerotorescue@0: local scrollbar = self.scrollbar Zerotorescue@0: local min, max = scrollbar:GetMinMaxValues() Zerotorescue@0: local value = scrollbar:GetValue() Zerotorescue@0: local newvalue = math_min(max,math_max(min,value - delta)) Zerotorescue@0: if value ~= newvalue then Zerotorescue@0: scrollbar:SetValue(newvalue) Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function Dragger_OnLeave(frame) Zerotorescue@0: frame:SetBackdropColor(1, 1, 1, 0) Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function Dragger_OnEnter(frame) Zerotorescue@0: frame:SetBackdropColor(1, 1, 1, 0.8) Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function Dragger_OnMouseDown(frame) Zerotorescue@0: local treeframe = frame:GetParent() Zerotorescue@0: treeframe:StartSizing("RIGHT") Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local function Dragger_OnMouseUp(frame) Zerotorescue@0: local treeframe = frame:GetParent() Zerotorescue@0: local self = treeframe.obj Zerotorescue@0: local frame = treeframe:GetParent() Zerotorescue@0: treeframe:StopMovingOrSizing() Zerotorescue@0: --treeframe:SetScript("OnUpdate", nil) Zerotorescue@0: treeframe:SetUserPlaced(false) Zerotorescue@0: --Without this :GetHeight will get stuck on the current height, causing the tree contents to not resize Zerotorescue@0: treeframe:SetHeight(0) Zerotorescue@0: treeframe:SetPoint("TOPLEFT", frame, "TOPLEFT",0,0) Zerotorescue@0: treeframe:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT",0,0) Zerotorescue@0: Zerotorescue@0: local status = self.status or self.localstatus Zerotorescue@0: status.treewidth = treeframe:GetWidth() Zerotorescue@0: Zerotorescue@0: treeframe.obj:Fire("OnTreeResize",treeframe:GetWidth()) Zerotorescue@0: -- recalculate the content width Zerotorescue@0: treeframe.obj:OnWidthSet(status.fullwidth) Zerotorescue@0: -- update the layout of the content Zerotorescue@0: treeframe.obj:DoLayout() Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: --[[----------------------------------------------------------------------------- Zerotorescue@0: Methods Zerotorescue@0: -------------------------------------------------------------------------------]] Zerotorescue@0: local methods = { Zerotorescue@0: ["OnAcquire"] = function(self) Zerotorescue@0: self:SetTreeWidth(DEFAULT_TREE_WIDTH, DEFAULT_TREE_SIZABLE) Zerotorescue@0: self:EnableButtonTooltips(true) Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["OnRelease"] = function(self) Zerotorescue@0: self.status = nil Zerotorescue@0: for k, v in pairs(self.localstatus) do Zerotorescue@0: if k == "groups" then Zerotorescue@0: for k2 in pairs(v) do Zerotorescue@0: v[k2] = nil Zerotorescue@0: end Zerotorescue@0: else Zerotorescue@0: self.localstatus[k] = nil Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: self.localstatus.scrollvalue = 0 Zerotorescue@0: self.localstatus.treewidth = DEFAULT_TREE_WIDTH Zerotorescue@0: self.localstatus.treesizable = DEFAULT_TREE_SIZABLE Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["EnableButtonTooltips"] = function(self, enable) Zerotorescue@0: self.enabletooltips = enable Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["CreateButton"] = function(self) Zerotorescue@0: local num = AceGUI:GetNextWidgetNum("TreeGroupButton") Zerotorescue@0: local button = CreateFrame("Button", ("AceGUI30TreeButton%d"):format(num), self.treeframe, "OptionsListButtonTemplate") Zerotorescue@0: button.obj = self Zerotorescue@0: Zerotorescue@0: local icon = button:CreateTexture(nil, "OVERLAY") Zerotorescue@0: icon:SetWidth(14) Zerotorescue@0: icon:SetHeight(14) Zerotorescue@0: button.icon = icon Zerotorescue@0: Zerotorescue@0: button:SetScript("OnClick",Button_OnClick) Zerotorescue@0: button:SetScript("OnDoubleClick", Button_OnDoubleClick) Zerotorescue@0: button:SetScript("OnEnter",Button_OnEnter) Zerotorescue@0: button:SetScript("OnLeave",Button_OnLeave) Zerotorescue@0: Zerotorescue@0: button.toggle.button = button Zerotorescue@0: button.toggle:SetScript("OnClick",Expand_OnClick) Zerotorescue@0: Zerotorescue@0: return button Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["SetStatusTable"] = function(self, status) Zerotorescue@0: assert(type(status) == "table") Zerotorescue@0: self.status = status Zerotorescue@0: if not status.groups then Zerotorescue@0: status.groups = {} Zerotorescue@0: end Zerotorescue@0: if not status.scrollvalue then Zerotorescue@0: status.scrollvalue = 0 Zerotorescue@0: end Zerotorescue@0: if not status.treewidth then Zerotorescue@0: status.treewidth = DEFAULT_TREE_WIDTH Zerotorescue@0: end Zerotorescue@0: if not status.treesizable then Zerotorescue@0: status.treesizable = DEFAULT_TREE_SIZABLE Zerotorescue@0: end Zerotorescue@0: self:SetTreeWidth(status.treewidth,status.treesizable) Zerotorescue@0: self:RefreshTree() Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: --sets the tree to be displayed Zerotorescue@0: ["SetTree"] = function(self, tree, filter) Zerotorescue@0: self.filter = filter Zerotorescue@0: if tree then Zerotorescue@0: assert(type(tree) == "table") Zerotorescue@0: end Zerotorescue@0: self.tree = tree Zerotorescue@0: self:RefreshTree() Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["BuildLevel"] = function(self, tree, level, parent) Zerotorescue@0: local groups = (self.status or self.localstatus).groups Zerotorescue@0: local hasChildren = self.hasChildren Zerotorescue@0: Zerotorescue@0: for i, v in ipairs(tree) do Zerotorescue@0: if v.children then Zerotorescue@0: if not self.filter or ShouldDisplayLevel(v.children) then Zerotorescue@0: local line = addLine(self, v, tree, level, parent) Zerotorescue@0: if groups[line.uniquevalue] then Zerotorescue@0: self:BuildLevel(v.children, level+1, line) Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: elseif v.visible ~= false or not self.filter then Zerotorescue@0: addLine(self, v, tree, level, parent) Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["RefreshTree"] = function(self) Zerotorescue@0: local buttons = self.buttons Zerotorescue@0: local lines = self.lines Zerotorescue@0: Zerotorescue@0: for i, v in ipairs(buttons) do Zerotorescue@0: v:Hide() Zerotorescue@0: end Zerotorescue@0: while lines[1] do Zerotorescue@0: local t = tremove(lines) Zerotorescue@0: for k in pairs(t) do Zerotorescue@0: t[k] = nil Zerotorescue@0: end Zerotorescue@0: del(t) Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: if not self.tree then return end Zerotorescue@0: --Build the list of visible entries from the tree and status tables Zerotorescue@0: local status = self.status or self.localstatus Zerotorescue@0: local groupstatus = status.groups Zerotorescue@0: local tree = self.tree Zerotorescue@0: Zerotorescue@0: local treeframe = self.treeframe Zerotorescue@0: Zerotorescue@0: self:BuildLevel(tree, 1) Zerotorescue@0: Zerotorescue@0: local numlines = #lines Zerotorescue@0: Zerotorescue@0: local maxlines = (floor(((self.treeframe:GetHeight()or 0) - 20 ) / 18)) Zerotorescue@0: Zerotorescue@0: local first, last Zerotorescue@0: Zerotorescue@0: if numlines <= maxlines then Zerotorescue@0: --the whole tree fits in the frame Zerotorescue@0: status.scrollvalue = 0 Zerotorescue@0: self:ShowScroll(false) Zerotorescue@0: first, last = 1, numlines Zerotorescue@0: else Zerotorescue@0: self:ShowScroll(true) Zerotorescue@0: --scrolling will be needed Zerotorescue@0: self.noupdate = true Zerotorescue@0: self.scrollbar:SetMinMaxValues(0, numlines - maxlines) Zerotorescue@0: --check if we are scrolled down too far Zerotorescue@0: if numlines - status.scrollvalue < maxlines then Zerotorescue@0: status.scrollvalue = numlines - maxlines Zerotorescue@0: self.scrollbar:SetValue(status.scrollvalue) Zerotorescue@0: end Zerotorescue@0: self.noupdate = nil Zerotorescue@0: first, last = status.scrollvalue+1, status.scrollvalue + maxlines Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: local buttonnum = 1 Zerotorescue@0: for i = first, last do Zerotorescue@0: local line = lines[i] Zerotorescue@0: local button = buttons[buttonnum] Zerotorescue@0: if not button then Zerotorescue@0: button = self:CreateButton() Zerotorescue@0: Zerotorescue@0: buttons[buttonnum] = button Zerotorescue@0: button:SetParent(treeframe) Zerotorescue@0: button:SetFrameLevel(treeframe:GetFrameLevel()+1) Zerotorescue@0: button:ClearAllPoints() Zerotorescue@0: if i == 1 then Zerotorescue@0: if self.showscroll then Zerotorescue@0: button:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",-22,-10) Zerotorescue@0: button:SetPoint("TOPLEFT", self.treeframe, "TOPLEFT", 0, -10) Zerotorescue@0: else Zerotorescue@0: button:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",0,-10) Zerotorescue@0: button:SetPoint("TOPLEFT", self.treeframe, "TOPLEFT", 0, -10) Zerotorescue@0: end Zerotorescue@0: else Zerotorescue@0: button:SetPoint("TOPRIGHT", buttons[buttonnum-1], "BOTTOMRIGHT",0,0) Zerotorescue@0: button:SetPoint("TOPLEFT", buttons[buttonnum-1], "BOTTOMLEFT",0,0) Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: UpdateButton(button, line, status.selected == line.uniquevalue, line.hasChildren, groupstatus[line.uniquevalue] ) Zerotorescue@0: button:Show() Zerotorescue@0: buttonnum = buttonnum + 1 Zerotorescue@0: end Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["SetSelected"] = function(self, value) Zerotorescue@0: local status = self.status or self.localstatus Zerotorescue@0: if status.selected ~= value then Zerotorescue@0: status.selected = value Zerotorescue@0: self:Fire("OnGroupSelected", value) Zerotorescue@0: end Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["Select"] = function(self, uniquevalue, ...) Zerotorescue@0: self.filter = false Zerotorescue@0: local status = self.status or self.localstatus Zerotorescue@0: local groups = status.groups Zerotorescue@0: for i = 1, select('#', ...) do Zerotorescue@0: groups[BuildUniqueValue(select(i, ...))] = true Zerotorescue@0: end Zerotorescue@0: status.selected = uniquevalue Zerotorescue@0: self:RefreshTree() Zerotorescue@0: self:Fire("OnGroupSelected", uniquevalue) Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["SelectByPath"] = function(self, ...) Zerotorescue@0: self:Select(BuildUniqueValue(...), ...) Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["SelectByValue"] = function(self, uniquevalue) Zerotorescue@0: self:Select(uniquevalue, ("\001"):split(uniquevalue)) Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["ShowScroll"] = function(self, show) Zerotorescue@0: self.showscroll = show Zerotorescue@0: if show then Zerotorescue@0: self.scrollbar:Show() Zerotorescue@0: if self.buttons[1] then Zerotorescue@0: self.buttons[1]:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",-22,-10) Zerotorescue@0: end Zerotorescue@0: else Zerotorescue@0: self.scrollbar:Hide() Zerotorescue@0: if self.buttons[1] then Zerotorescue@0: self.buttons[1]:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",0,-10) Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["OnWidthSet"] = function(self, width) Zerotorescue@0: local content = self.content Zerotorescue@0: local treeframe = self.treeframe Zerotorescue@0: local status = self.status or self.localstatus Zerotorescue@0: status.fullwidth = width Zerotorescue@0: Zerotorescue@0: local contentwidth = width - status.treewidth - 20 Zerotorescue@0: if contentwidth < 0 then Zerotorescue@0: contentwidth = 0 Zerotorescue@0: end Zerotorescue@0: content:SetWidth(contentwidth) Zerotorescue@0: content.width = contentwidth Zerotorescue@0: Zerotorescue@0: local maxtreewidth = math_min(400, width - 50) Zerotorescue@0: Zerotorescue@0: if maxtreewidth > 100 and status.treewidth > maxtreewidth then Zerotorescue@0: self:SetTreeWidth(maxtreewidth, status.treesizable) Zerotorescue@0: end Zerotorescue@0: treeframe:SetMaxResize(maxtreewidth, 1600) Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["OnHeightSet"] = function(self, height) Zerotorescue@0: local content = self.content Zerotorescue@0: local contentheight = height - 20 Zerotorescue@0: if contentheight < 0 then Zerotorescue@0: contentheight = 0 Zerotorescue@0: end Zerotorescue@0: content:SetHeight(contentheight) Zerotorescue@0: content.height = contentheight Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["SetTreeWidth"] = function(self, treewidth, resizable) Zerotorescue@0: if not resizable then Zerotorescue@0: if type(treewidth) == 'number' then Zerotorescue@0: resizable = false Zerotorescue@0: elseif type(treewidth) == 'boolean' then Zerotorescue@0: resizable = treewidth Zerotorescue@0: treewidth = DEFAULT_TREE_WIDTH Zerotorescue@0: else Zerotorescue@0: resizable = false Zerotorescue@0: treewidth = DEFAULT_TREE_WIDTH Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: self.treeframe:SetWidth(treewidth) Zerotorescue@0: self.dragger:EnableMouse(resizable) Zerotorescue@0: Zerotorescue@0: local status = self.status or self.localstatus Zerotorescue@0: status.treewidth = treewidth Zerotorescue@0: status.treesizable = resizable Zerotorescue@0: Zerotorescue@0: -- recalculate the content width Zerotorescue@0: if status.fullwidth then Zerotorescue@0: self:OnWidthSet(status.fullwidth) Zerotorescue@0: end Zerotorescue@0: end, Zerotorescue@0: Zerotorescue@0: ["LayoutFinished"] = function(self, width, height) Zerotorescue@0: if self.noAutoHeight then return end Zerotorescue@0: self:SetHeight((height or 0) + 20) Zerotorescue@0: end Zerotorescue@0: } Zerotorescue@0: Zerotorescue@0: --[[----------------------------------------------------------------------------- Zerotorescue@0: Constructor Zerotorescue@0: -------------------------------------------------------------------------------]] Zerotorescue@0: local PaneBackdrop = { Zerotorescue@0: bgFile = "Interface\\ChatFrame\\ChatFrameBackground", Zerotorescue@0: edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", Zerotorescue@0: tile = true, tileSize = 16, edgeSize = 16, Zerotorescue@0: insets = { left = 3, right = 3, top = 5, bottom = 3 } Zerotorescue@0: } Zerotorescue@0: Zerotorescue@0: local DraggerBackdrop = { Zerotorescue@0: bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", Zerotorescue@0: edgeFile = nil, Zerotorescue@0: tile = true, tileSize = 16, edgeSize = 0, Zerotorescue@0: insets = { left = 3, right = 3, top = 7, bottom = 7 } Zerotorescue@0: } Zerotorescue@0: Zerotorescue@0: local function Constructor() Zerotorescue@0: local num = AceGUI:GetNextWidgetNum(Type) Zerotorescue@0: local frame = CreateFrame("Frame", nil, UIParent) Zerotorescue@0: Zerotorescue@0: local treeframe = CreateFrame("Frame", nil, frame) Zerotorescue@0: treeframe:SetPoint("TOPLEFT") Zerotorescue@0: treeframe:SetPoint("BOTTOMLEFT") Zerotorescue@0: treeframe:SetWidth(DEFAULT_TREE_WIDTH) Zerotorescue@0: treeframe:EnableMouseWheel(true) Zerotorescue@0: treeframe:SetBackdrop(PaneBackdrop) Zerotorescue@0: treeframe:SetBackdropColor(0.1, 0.1, 0.1, 0.5) Zerotorescue@0: treeframe:SetBackdropBorderColor(0.4, 0.4, 0.4) Zerotorescue@0: treeframe:SetResizable(true) Zerotorescue@0: treeframe:SetMinResize(100, 1) Zerotorescue@0: treeframe:SetMaxResize(400, 1600) Zerotorescue@0: treeframe:SetScript("OnUpdate", FirstFrameUpdate) Zerotorescue@0: treeframe:SetScript("OnSizeChanged", Tree_OnSizeChanged) Zerotorescue@0: treeframe:SetScript("OnMouseWheel", Tree_OnMouseWheel) Zerotorescue@0: Zerotorescue@0: local dragger = CreateFrame("Frame", nil, treeframe) Zerotorescue@0: dragger:SetWidth(8) Zerotorescue@0: dragger:SetPoint("TOP", treeframe, "TOPRIGHT") Zerotorescue@0: dragger:SetPoint("BOTTOM", treeframe, "BOTTOMRIGHT") Zerotorescue@0: dragger:SetBackdrop(DraggerBackdrop) Zerotorescue@0: dragger:SetBackdropColor(1, 1, 1, 0) Zerotorescue@0: dragger:SetScript("OnEnter", Dragger_OnEnter) Zerotorescue@0: dragger:SetScript("OnLeave", Dragger_OnLeave) Zerotorescue@0: dragger:SetScript("OnMouseDown", Dragger_OnMouseDown) Zerotorescue@0: dragger:SetScript("OnMouseUp", Dragger_OnMouseUp) Zerotorescue@0: Zerotorescue@0: local scrollbar = CreateFrame("Slider", ("AceConfigDialogTreeGroup%dScrollBar"):format(num), treeframe, "UIPanelScrollBarTemplate") Zerotorescue@0: scrollbar:SetScript("OnValueChanged", nil) Zerotorescue@0: scrollbar:SetPoint("TOPRIGHT", -10, -26) Zerotorescue@0: scrollbar:SetPoint("BOTTOMRIGHT", -10, 26) Zerotorescue@0: scrollbar:SetMinMaxValues(0,0) Zerotorescue@0: scrollbar:SetValueStep(1) Zerotorescue@0: scrollbar:SetValue(0) Zerotorescue@0: scrollbar:SetWidth(16) Zerotorescue@0: scrollbar:SetScript("OnValueChanged", OnScrollValueChanged) Zerotorescue@0: Zerotorescue@0: local scrollbg = scrollbar:CreateTexture(nil, "BACKGROUND") Zerotorescue@0: scrollbg:SetAllPoints(scrollbar) Zerotorescue@0: scrollbg:SetTexture(0,0,0,0.4) Zerotorescue@0: Zerotorescue@0: local border = CreateFrame("Frame",nil,frame) Zerotorescue@0: border:SetPoint("TOPLEFT", treeframe, "TOPRIGHT") Zerotorescue@0: border:SetPoint("BOTTOMRIGHT") Zerotorescue@0: border:SetBackdrop(PaneBackdrop) Zerotorescue@0: border:SetBackdropColor(0.1, 0.1, 0.1, 0.5) Zerotorescue@0: border:SetBackdropBorderColor(0.4, 0.4, 0.4) Zerotorescue@0: Zerotorescue@0: --Container Support Zerotorescue@0: local content = CreateFrame("Frame", nil, border) Zerotorescue@0: content:SetPoint("TOPLEFT", 10, -10) Zerotorescue@0: content:SetPoint("BOTTOMRIGHT", -10, 10) Zerotorescue@0: Zerotorescue@0: local widget = { Zerotorescue@0: frame = frame, Zerotorescue@0: lines = {}, Zerotorescue@0: levels = {}, Zerotorescue@0: buttons = {}, Zerotorescue@0: hasChildren = {}, Zerotorescue@0: localstatus = { groups = {}, scrollvalue = 0 }, Zerotorescue@0: filter = false, Zerotorescue@0: treeframe = treeframe, Zerotorescue@0: dragger = dragger, Zerotorescue@0: scrollbar = scrollbar, Zerotorescue@0: border = border, Zerotorescue@0: content = content, Zerotorescue@0: type = Type Zerotorescue@0: } Zerotorescue@0: for method, func in pairs(methods) do Zerotorescue@0: widget[method] = func Zerotorescue@0: end Zerotorescue@0: treeframe.obj, dragger.obj, scrollbar.obj = widget, widget, widget Zerotorescue@0: Zerotorescue@0: return AceGUI:RegisterAsContainer(widget) Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: AceGUI:RegisterWidgetType(Type, Constructor, Version)