annotate Libs/AceGUI-3.0/widgets/AceGUIContainer-TreeGroup.lua @ 106:e635cd648e01 v49

7.2 update
author yellowfive
date Tue, 28 Mar 2017 16:10:00 -0700
parents 01b63b8ed811
children e31b02b24488
rev   line source
yellowfive@57 1 --[[-----------------------------------------------------------------------------
yellowfive@57 2 TreeGroup Container
yellowfive@57 3 Container that uses a tree control to switch between groups.
yellowfive@57 4 -------------------------------------------------------------------------------]]
yellowfive@106 5 local Type, Version = "TreeGroup", 40
yellowfive@57 6 local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
yellowfive@57 7 if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
yellowfive@57 8
yellowfive@57 9 -- Lua APIs
yellowfive@57 10 local next, pairs, ipairs, assert, type = next, pairs, ipairs, assert, type
yellowfive@57 11 local math_min, math_max, floor = math.min, math.max, floor
yellowfive@57 12 local select, tremove, unpack, tconcat = select, table.remove, unpack, table.concat
yellowfive@57 13
yellowfive@57 14 -- WoW APIs
yellowfive@57 15 local CreateFrame, UIParent = CreateFrame, UIParent
yellowfive@57 16
yellowfive@57 17 -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
yellowfive@57 18 -- List them here for Mikk's FindGlobals script
yellowfive@57 19 -- GLOBALS: GameTooltip, FONT_COLOR_CODE_CLOSE
yellowfive@57 20
yellowfive@57 21 -- Recycling functions
yellowfive@57 22 local new, del
yellowfive@57 23 do
yellowfive@57 24 local pool = setmetatable({},{__mode='k'})
yellowfive@57 25 function new()
yellowfive@57 26 local t = next(pool)
yellowfive@57 27 if t then
yellowfive@57 28 pool[t] = nil
yellowfive@57 29 return t
yellowfive@57 30 else
yellowfive@57 31 return {}
yellowfive@57 32 end
yellowfive@57 33 end
yellowfive@57 34 function del(t)
yellowfive@57 35 for k in pairs(t) do
yellowfive@57 36 t[k] = nil
yellowfive@57 37 end
yellowfive@57 38 pool[t] = true
yellowfive@57 39 end
yellowfive@57 40 end
yellowfive@57 41
yellowfive@57 42 local DEFAULT_TREE_WIDTH = 175
yellowfive@57 43 local DEFAULT_TREE_SIZABLE = true
yellowfive@57 44
yellowfive@57 45 --[[-----------------------------------------------------------------------------
yellowfive@57 46 Support functions
yellowfive@57 47 -------------------------------------------------------------------------------]]
yellowfive@57 48 local function GetButtonUniqueValue(line)
yellowfive@57 49 local parent = line.parent
yellowfive@57 50 if parent and parent.value then
yellowfive@57 51 return GetButtonUniqueValue(parent).."\001"..line.value
yellowfive@57 52 else
yellowfive@57 53 return line.value
yellowfive@57 54 end
yellowfive@57 55 end
yellowfive@57 56
yellowfive@57 57 local function UpdateButton(button, treeline, selected, canExpand, isExpanded)
yellowfive@57 58 local self = button.obj
yellowfive@57 59 local toggle = button.toggle
yellowfive@57 60 local frame = self.frame
yellowfive@57 61 local text = treeline.text or ""
yellowfive@57 62 local icon = treeline.icon
yellowfive@57 63 local iconCoords = treeline.iconCoords
yellowfive@57 64 local level = treeline.level
yellowfive@57 65 local value = treeline.value
yellowfive@57 66 local uniquevalue = treeline.uniquevalue
yellowfive@57 67 local disabled = treeline.disabled
yellowfive@57 68
yellowfive@57 69 button.treeline = treeline
yellowfive@57 70 button.value = value
yellowfive@57 71 button.uniquevalue = uniquevalue
yellowfive@57 72 if selected then
yellowfive@57 73 button:LockHighlight()
yellowfive@57 74 button.selected = true
yellowfive@57 75 else
yellowfive@57 76 button:UnlockHighlight()
yellowfive@57 77 button.selected = false
yellowfive@57 78 end
yellowfive@57 79 local normalTexture = button:GetNormalTexture()
yellowfive@57 80 local line = button.line
yellowfive@57 81 button.level = level
yellowfive@57 82 if ( level == 1 ) then
yellowfive@57 83 button:SetNormalFontObject("GameFontNormal")
yellowfive@57 84 button:SetHighlightFontObject("GameFontHighlight")
yellowfive@57 85 button.text:SetPoint("LEFT", (icon and 16 or 0) + 8, 2)
yellowfive@57 86 else
yellowfive@57 87 button:SetNormalFontObject("GameFontHighlightSmall")
yellowfive@57 88 button:SetHighlightFontObject("GameFontHighlightSmall")
yellowfive@57 89 button.text:SetPoint("LEFT", (icon and 16 or 0) + 8 * level, 2)
yellowfive@57 90 end
yellowfive@57 91
yellowfive@57 92 if disabled then
yellowfive@57 93 button:EnableMouse(false)
yellowfive@57 94 button.text:SetText("|cff808080"..text..FONT_COLOR_CODE_CLOSE)
yellowfive@57 95 else
yellowfive@57 96 button.text:SetText(text)
yellowfive@57 97 button:EnableMouse(true)
yellowfive@57 98 end
yellowfive@57 99
yellowfive@57 100 if icon then
yellowfive@57 101 button.icon:SetTexture(icon)
yellowfive@57 102 button.icon:SetPoint("LEFT", 8 * level, (level == 1) and 0 or 1)
yellowfive@57 103 else
yellowfive@57 104 button.icon:SetTexture(nil)
yellowfive@57 105 end
yellowfive@57 106
yellowfive@57 107 if iconCoords then
yellowfive@57 108 button.icon:SetTexCoord(unpack(iconCoords))
yellowfive@57 109 else
yellowfive@57 110 button.icon:SetTexCoord(0, 1, 0, 1)
yellowfive@57 111 end
yellowfive@57 112
yellowfive@57 113 if canExpand then
yellowfive@57 114 if not isExpanded then
yellowfive@57 115 toggle:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-UP")
yellowfive@57 116 toggle:SetPushedTexture("Interface\\Buttons\\UI-PlusButton-DOWN")
yellowfive@57 117 else
yellowfive@57 118 toggle:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-UP")
yellowfive@57 119 toggle:SetPushedTexture("Interface\\Buttons\\UI-MinusButton-DOWN")
yellowfive@57 120 end
yellowfive@57 121 toggle:Show()
yellowfive@57 122 else
yellowfive@57 123 toggle:Hide()
yellowfive@57 124 end
yellowfive@57 125 end
yellowfive@57 126
yellowfive@57 127 local function ShouldDisplayLevel(tree)
yellowfive@57 128 local result = false
yellowfive@57 129 for k, v in ipairs(tree) do
yellowfive@57 130 if v.children == nil and v.visible ~= false then
yellowfive@57 131 result = true
yellowfive@57 132 elseif v.children then
yellowfive@57 133 result = result or ShouldDisplayLevel(v.children)
yellowfive@57 134 end
yellowfive@57 135 if result then return result end
yellowfive@57 136 end
yellowfive@57 137 return false
yellowfive@57 138 end
yellowfive@57 139
yellowfive@57 140 local function addLine(self, v, tree, level, parent)
yellowfive@57 141 local line = new()
yellowfive@57 142 line.value = v.value
yellowfive@57 143 line.text = v.text
yellowfive@57 144 line.icon = v.icon
yellowfive@57 145 line.iconCoords = v.iconCoords
yellowfive@57 146 line.disabled = v.disabled
yellowfive@57 147 line.tree = tree
yellowfive@57 148 line.level = level
yellowfive@57 149 line.parent = parent
yellowfive@57 150 line.visible = v.visible
yellowfive@57 151 line.uniquevalue = GetButtonUniqueValue(line)
yellowfive@57 152 if v.children then
yellowfive@57 153 line.hasChildren = true
yellowfive@57 154 else
yellowfive@57 155 line.hasChildren = nil
yellowfive@57 156 end
yellowfive@57 157 self.lines[#self.lines+1] = line
yellowfive@57 158 return line
yellowfive@57 159 end
yellowfive@57 160
yellowfive@57 161 --fire an update after one frame to catch the treeframes height
yellowfive@57 162 local function FirstFrameUpdate(frame)
yellowfive@57 163 local self = frame.obj
yellowfive@57 164 frame:SetScript("OnUpdate", nil)
yellowfive@57 165 self:RefreshTree()
yellowfive@57 166 end
yellowfive@57 167
yellowfive@57 168 local function BuildUniqueValue(...)
yellowfive@57 169 local n = select('#', ...)
yellowfive@57 170 if n == 1 then
yellowfive@57 171 return ...
yellowfive@57 172 else
yellowfive@57 173 return (...).."\001"..BuildUniqueValue(select(2,...))
yellowfive@57 174 end
yellowfive@57 175 end
yellowfive@57 176
yellowfive@57 177 --[[-----------------------------------------------------------------------------
yellowfive@57 178 Scripts
yellowfive@57 179 -------------------------------------------------------------------------------]]
yellowfive@57 180 local function Expand_OnClick(frame)
yellowfive@57 181 local button = frame.button
yellowfive@57 182 local self = button.obj
yellowfive@57 183 local status = (self.status or self.localstatus).groups
yellowfive@57 184 status[button.uniquevalue] = not status[button.uniquevalue]
yellowfive@57 185 self:RefreshTree()
yellowfive@57 186 end
yellowfive@57 187
yellowfive@57 188 local function Button_OnClick(frame)
yellowfive@57 189 local self = frame.obj
yellowfive@57 190 self:Fire("OnClick", frame.uniquevalue, frame.selected)
yellowfive@57 191 if not frame.selected then
yellowfive@57 192 self:SetSelected(frame.uniquevalue)
yellowfive@57 193 frame.selected = true
yellowfive@57 194 frame:LockHighlight()
yellowfive@57 195 self:RefreshTree()
yellowfive@57 196 end
yellowfive@57 197 AceGUI:ClearFocus()
yellowfive@57 198 end
yellowfive@57 199
yellowfive@57 200 local function Button_OnDoubleClick(button)
yellowfive@57 201 local self = button.obj
yellowfive@57 202 local status = self.status or self.localstatus
yellowfive@57 203 local status = (self.status or self.localstatus).groups
yellowfive@57 204 status[button.uniquevalue] = not status[button.uniquevalue]
yellowfive@57 205 self:RefreshTree()
yellowfive@57 206 end
yellowfive@57 207
yellowfive@57 208 local function Button_OnEnter(frame)
yellowfive@57 209 local self = frame.obj
yellowfive@57 210 self:Fire("OnButtonEnter", frame.uniquevalue, frame)
yellowfive@57 211
yellowfive@57 212 if self.enabletooltips then
yellowfive@57 213 GameTooltip:SetOwner(frame, "ANCHOR_NONE")
yellowfive@57 214 GameTooltip:SetPoint("LEFT",frame,"RIGHT")
yellowfive@57 215 GameTooltip:SetText(frame.text:GetText() or "", 1, .82, 0, true)
yellowfive@57 216
yellowfive@57 217 GameTooltip:Show()
yellowfive@57 218 end
yellowfive@57 219 end
yellowfive@57 220
yellowfive@57 221 local function Button_OnLeave(frame)
yellowfive@57 222 local self = frame.obj
yellowfive@57 223 self:Fire("OnButtonLeave", frame.uniquevalue, frame)
yellowfive@57 224
yellowfive@57 225 if self.enabletooltips then
yellowfive@57 226 GameTooltip:Hide()
yellowfive@57 227 end
yellowfive@57 228 end
yellowfive@57 229
yellowfive@57 230 local function OnScrollValueChanged(frame, value)
yellowfive@57 231 if frame.obj.noupdate then return end
yellowfive@57 232 local self = frame.obj
yellowfive@57 233 local status = self.status or self.localstatus
yellowfive@57 234 status.scrollvalue = floor(value + 0.5)
yellowfive@57 235 self:RefreshTree()
yellowfive@57 236 AceGUI:ClearFocus()
yellowfive@57 237 end
yellowfive@57 238
yellowfive@57 239 local function Tree_OnSizeChanged(frame)
yellowfive@57 240 frame.obj:RefreshTree()
yellowfive@57 241 end
yellowfive@57 242
yellowfive@57 243 local function Tree_OnMouseWheel(frame, delta)
yellowfive@57 244 local self = frame.obj
yellowfive@57 245 if self.showscroll then
yellowfive@57 246 local scrollbar = self.scrollbar
yellowfive@57 247 local min, max = scrollbar:GetMinMaxValues()
yellowfive@57 248 local value = scrollbar:GetValue()
yellowfive@57 249 local newvalue = math_min(max,math_max(min,value - delta))
yellowfive@57 250 if value ~= newvalue then
yellowfive@57 251 scrollbar:SetValue(newvalue)
yellowfive@57 252 end
yellowfive@57 253 end
yellowfive@57 254 end
yellowfive@57 255
yellowfive@57 256 local function Dragger_OnLeave(frame)
yellowfive@57 257 frame:SetBackdropColor(1, 1, 1, 0)
yellowfive@57 258 end
yellowfive@57 259
yellowfive@57 260 local function Dragger_OnEnter(frame)
yellowfive@57 261 frame:SetBackdropColor(1, 1, 1, 0.8)
yellowfive@57 262 end
yellowfive@57 263
yellowfive@57 264 local function Dragger_OnMouseDown(frame)
yellowfive@57 265 local treeframe = frame:GetParent()
yellowfive@57 266 treeframe:StartSizing("RIGHT")
yellowfive@57 267 end
yellowfive@57 268
yellowfive@57 269 local function Dragger_OnMouseUp(frame)
yellowfive@57 270 local treeframe = frame:GetParent()
yellowfive@57 271 local self = treeframe.obj
yellowfive@57 272 local frame = treeframe:GetParent()
yellowfive@57 273 treeframe:StopMovingOrSizing()
yellowfive@57 274 --treeframe:SetScript("OnUpdate", nil)
yellowfive@57 275 treeframe:SetUserPlaced(false)
yellowfive@57 276 --Without this :GetHeight will get stuck on the current height, causing the tree contents to not resize
yellowfive@57 277 treeframe:SetHeight(0)
yellowfive@57 278 treeframe:SetPoint("TOPLEFT", frame, "TOPLEFT",0,0)
yellowfive@57 279 treeframe:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT",0,0)
yellowfive@57 280
yellowfive@57 281 local status = self.status or self.localstatus
yellowfive@57 282 status.treewidth = treeframe:GetWidth()
yellowfive@57 283
yellowfive@57 284 treeframe.obj:Fire("OnTreeResize",treeframe:GetWidth())
yellowfive@57 285 -- recalculate the content width
yellowfive@57 286 treeframe.obj:OnWidthSet(status.fullwidth)
yellowfive@57 287 -- update the layout of the content
yellowfive@57 288 treeframe.obj:DoLayout()
yellowfive@57 289 end
yellowfive@57 290
yellowfive@57 291 --[[-----------------------------------------------------------------------------
yellowfive@57 292 Methods
yellowfive@57 293 -------------------------------------------------------------------------------]]
yellowfive@57 294 local methods = {
yellowfive@57 295 ["OnAcquire"] = function(self)
yellowfive@57 296 self:SetTreeWidth(DEFAULT_TREE_WIDTH, DEFAULT_TREE_SIZABLE)
yellowfive@57 297 self:EnableButtonTooltips(true)
yellowfive@106 298 self.frame:SetScript("OnUpdate", FirstFrameUpdate)
yellowfive@57 299 end,
yellowfive@57 300
yellowfive@57 301 ["OnRelease"] = function(self)
yellowfive@57 302 self.status = nil
yellowfive@57 303 for k, v in pairs(self.localstatus) do
yellowfive@57 304 if k == "groups" then
yellowfive@57 305 for k2 in pairs(v) do
yellowfive@57 306 v[k2] = nil
yellowfive@57 307 end
yellowfive@57 308 else
yellowfive@57 309 self.localstatus[k] = nil
yellowfive@57 310 end
yellowfive@57 311 end
yellowfive@57 312 self.localstatus.scrollvalue = 0
yellowfive@57 313 self.localstatus.treewidth = DEFAULT_TREE_WIDTH
yellowfive@57 314 self.localstatus.treesizable = DEFAULT_TREE_SIZABLE
yellowfive@57 315 end,
yellowfive@57 316
yellowfive@57 317 ["EnableButtonTooltips"] = function(self, enable)
yellowfive@57 318 self.enabletooltips = enable
yellowfive@57 319 end,
yellowfive@57 320
yellowfive@57 321 ["CreateButton"] = function(self)
yellowfive@57 322 local num = AceGUI:GetNextWidgetNum("TreeGroupButton")
yellowfive@57 323 local button = CreateFrame("Button", ("AceGUI30TreeButton%d"):format(num), self.treeframe, "OptionsListButtonTemplate")
yellowfive@57 324 button.obj = self
yellowfive@57 325
yellowfive@57 326 local icon = button:CreateTexture(nil, "OVERLAY")
yellowfive@57 327 icon:SetWidth(14)
yellowfive@57 328 icon:SetHeight(14)
yellowfive@57 329 button.icon = icon
yellowfive@57 330
yellowfive@57 331 button:SetScript("OnClick",Button_OnClick)
yellowfive@57 332 button:SetScript("OnDoubleClick", Button_OnDoubleClick)
yellowfive@57 333 button:SetScript("OnEnter",Button_OnEnter)
yellowfive@57 334 button:SetScript("OnLeave",Button_OnLeave)
yellowfive@57 335
yellowfive@57 336 button.toggle.button = button
yellowfive@57 337 button.toggle:SetScript("OnClick",Expand_OnClick)
yellowfive@57 338
yellowfive@106 339 button.text:SetHeight(14) -- Prevents text wrapping
yellowfive@106 340
yellowfive@57 341 return button
yellowfive@57 342 end,
yellowfive@57 343
yellowfive@57 344 ["SetStatusTable"] = function(self, status)
yellowfive@57 345 assert(type(status) == "table")
yellowfive@57 346 self.status = status
yellowfive@57 347 if not status.groups then
yellowfive@57 348 status.groups = {}
yellowfive@57 349 end
yellowfive@57 350 if not status.scrollvalue then
yellowfive@57 351 status.scrollvalue = 0
yellowfive@57 352 end
yellowfive@57 353 if not status.treewidth then
yellowfive@57 354 status.treewidth = DEFAULT_TREE_WIDTH
yellowfive@57 355 end
yellowfive@57 356 if status.treesizable == nil then
yellowfive@57 357 status.treesizable = DEFAULT_TREE_SIZABLE
yellowfive@57 358 end
yellowfive@57 359 self:SetTreeWidth(status.treewidth,status.treesizable)
yellowfive@57 360 self:RefreshTree()
yellowfive@57 361 end,
yellowfive@57 362
yellowfive@57 363 --sets the tree to be displayed
yellowfive@57 364 ["SetTree"] = function(self, tree, filter)
yellowfive@57 365 self.filter = filter
yellowfive@57 366 if tree then
yellowfive@57 367 assert(type(tree) == "table")
yellowfive@57 368 end
yellowfive@57 369 self.tree = tree
yellowfive@57 370 self:RefreshTree()
yellowfive@57 371 end,
yellowfive@57 372
yellowfive@57 373 ["BuildLevel"] = function(self, tree, level, parent)
yellowfive@57 374 local groups = (self.status or self.localstatus).groups
yellowfive@57 375 local hasChildren = self.hasChildren
yellowfive@57 376
yellowfive@57 377 for i, v in ipairs(tree) do
yellowfive@57 378 if v.children then
yellowfive@57 379 if not self.filter or ShouldDisplayLevel(v.children) then
yellowfive@57 380 local line = addLine(self, v, tree, level, parent)
yellowfive@57 381 if groups[line.uniquevalue] then
yellowfive@57 382 self:BuildLevel(v.children, level+1, line)
yellowfive@57 383 end
yellowfive@57 384 end
yellowfive@57 385 elseif v.visible ~= false or not self.filter then
yellowfive@57 386 addLine(self, v, tree, level, parent)
yellowfive@57 387 end
yellowfive@57 388 end
yellowfive@57 389 end,
yellowfive@57 390
yellowfive@57 391 ["RefreshTree"] = function(self,scrollToSelection)
yellowfive@57 392 local buttons = self.buttons
yellowfive@57 393 local lines = self.lines
yellowfive@57 394
yellowfive@57 395 for i, v in ipairs(buttons) do
yellowfive@57 396 v:Hide()
yellowfive@57 397 end
yellowfive@57 398 while lines[1] do
yellowfive@57 399 local t = tremove(lines)
yellowfive@57 400 for k in pairs(t) do
yellowfive@57 401 t[k] = nil
yellowfive@57 402 end
yellowfive@57 403 del(t)
yellowfive@57 404 end
yellowfive@57 405
yellowfive@57 406 if not self.tree then return end
yellowfive@57 407 --Build the list of visible entries from the tree and status tables
yellowfive@57 408 local status = self.status or self.localstatus
yellowfive@57 409 local groupstatus = status.groups
yellowfive@57 410 local tree = self.tree
yellowfive@57 411
yellowfive@57 412 local treeframe = self.treeframe
yellowfive@57 413
yellowfive@57 414 status.scrollToSelection = status.scrollToSelection or scrollToSelection -- needs to be cached in case the control hasn't been drawn yet (code bails out below)
yellowfive@57 415
yellowfive@57 416 self:BuildLevel(tree, 1)
yellowfive@57 417
yellowfive@57 418 local numlines = #lines
yellowfive@57 419
yellowfive@57 420 local maxlines = (floor(((self.treeframe:GetHeight()or 0) - 20 ) / 18))
yellowfive@57 421 if maxlines <= 0 then return end
yellowfive@57 422
yellowfive@57 423 local first, last
yellowfive@57 424
yellowfive@57 425 scrollToSelection = status.scrollToSelection
yellowfive@57 426 status.scrollToSelection = nil
yellowfive@57 427
yellowfive@57 428 if numlines <= maxlines then
yellowfive@57 429 --the whole tree fits in the frame
yellowfive@57 430 status.scrollvalue = 0
yellowfive@57 431 self:ShowScroll(false)
yellowfive@57 432 first, last = 1, numlines
yellowfive@57 433 else
yellowfive@57 434 self:ShowScroll(true)
yellowfive@57 435 --scrolling will be needed
yellowfive@57 436 self.noupdate = true
yellowfive@57 437 self.scrollbar:SetMinMaxValues(0, numlines - maxlines)
yellowfive@57 438 --check if we are scrolled down too far
yellowfive@57 439 if numlines - status.scrollvalue < maxlines then
yellowfive@57 440 status.scrollvalue = numlines - maxlines
yellowfive@57 441 end
yellowfive@57 442 self.noupdate = nil
yellowfive@57 443 first, last = status.scrollvalue+1, status.scrollvalue + maxlines
yellowfive@57 444 --show selection?
yellowfive@57 445 if scrollToSelection and status.selected then
yellowfive@57 446 local show
yellowfive@57 447 for i,line in ipairs(lines) do -- find the line number
yellowfive@57 448 if line.uniquevalue==status.selected then
yellowfive@57 449 show=i
yellowfive@57 450 end
yellowfive@57 451 end
yellowfive@57 452 if not show then
yellowfive@57 453 -- selection was deleted or something?
yellowfive@57 454 elseif show>=first and show<=last then
yellowfive@57 455 -- all good
yellowfive@57 456 else
yellowfive@57 457 -- scrolling needed!
yellowfive@57 458 if show<first then
yellowfive@57 459 status.scrollvalue = show-1
yellowfive@57 460 else
yellowfive@57 461 status.scrollvalue = show-maxlines
yellowfive@57 462 end
yellowfive@57 463 first, last = status.scrollvalue+1, status.scrollvalue + maxlines
yellowfive@57 464 end
yellowfive@57 465 end
yellowfive@57 466 if self.scrollbar:GetValue() ~= status.scrollvalue then
yellowfive@57 467 self.scrollbar:SetValue(status.scrollvalue)
yellowfive@57 468 end
yellowfive@57 469 end
yellowfive@57 470
yellowfive@57 471 local buttonnum = 1
yellowfive@57 472 for i = first, last do
yellowfive@57 473 local line = lines[i]
yellowfive@57 474 local button = buttons[buttonnum]
yellowfive@57 475 if not button then
yellowfive@57 476 button = self:CreateButton()
yellowfive@57 477
yellowfive@57 478 buttons[buttonnum] = button
yellowfive@57 479 button:SetParent(treeframe)
yellowfive@57 480 button:SetFrameLevel(treeframe:GetFrameLevel()+1)
yellowfive@57 481 button:ClearAllPoints()
yellowfive@57 482 if buttonnum == 1 then
yellowfive@57 483 if self.showscroll then
yellowfive@57 484 button:SetPoint("TOPRIGHT", -22, -10)
yellowfive@57 485 button:SetPoint("TOPLEFT", 0, -10)
yellowfive@57 486 else
yellowfive@57 487 button:SetPoint("TOPRIGHT", 0, -10)
yellowfive@57 488 button:SetPoint("TOPLEFT", 0, -10)
yellowfive@57 489 end
yellowfive@57 490 else
yellowfive@57 491 button:SetPoint("TOPRIGHT", buttons[buttonnum-1], "BOTTOMRIGHT",0,0)
yellowfive@57 492 button:SetPoint("TOPLEFT", buttons[buttonnum-1], "BOTTOMLEFT",0,0)
yellowfive@57 493 end
yellowfive@57 494 end
yellowfive@57 495
yellowfive@57 496 UpdateButton(button, line, status.selected == line.uniquevalue, line.hasChildren, groupstatus[line.uniquevalue] )
yellowfive@57 497 button:Show()
yellowfive@57 498 buttonnum = buttonnum + 1
yellowfive@57 499 end
yellowfive@57 500
yellowfive@57 501 end,
yellowfive@57 502
yellowfive@57 503 ["SetSelected"] = function(self, value)
yellowfive@57 504 local status = self.status or self.localstatus
yellowfive@57 505 if status.selected ~= value then
yellowfive@57 506 status.selected = value
yellowfive@57 507 self:Fire("OnGroupSelected", value)
yellowfive@57 508 end
yellowfive@57 509 end,
yellowfive@57 510
yellowfive@57 511 ["Select"] = function(self, uniquevalue, ...)
yellowfive@57 512 self.filter = false
yellowfive@57 513 local status = self.status or self.localstatus
yellowfive@57 514 local groups = status.groups
yellowfive@57 515 local path = {...}
yellowfive@57 516 for i = 1, #path do
yellowfive@57 517 groups[tconcat(path, "\001", 1, i)] = true
yellowfive@57 518 end
yellowfive@57 519 status.selected = uniquevalue
yellowfive@57 520 self:RefreshTree(true)
yellowfive@57 521 self:Fire("OnGroupSelected", uniquevalue)
yellowfive@57 522 end,
yellowfive@57 523
yellowfive@57 524 ["SelectByPath"] = function(self, ...)
yellowfive@57 525 self:Select(BuildUniqueValue(...), ...)
yellowfive@57 526 end,
yellowfive@57 527
yellowfive@57 528 ["SelectByValue"] = function(self, uniquevalue)
yellowfive@57 529 self:Select(uniquevalue, ("\001"):split(uniquevalue))
yellowfive@57 530 end,
yellowfive@57 531
yellowfive@57 532 ["ShowScroll"] = function(self, show)
yellowfive@57 533 self.showscroll = show
yellowfive@57 534 if show then
yellowfive@57 535 self.scrollbar:Show()
yellowfive@57 536 if self.buttons[1] then
yellowfive@57 537 self.buttons[1]:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",-22,-10)
yellowfive@57 538 end
yellowfive@57 539 else
yellowfive@57 540 self.scrollbar:Hide()
yellowfive@57 541 if self.buttons[1] then
yellowfive@57 542 self.buttons[1]:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",0,-10)
yellowfive@57 543 end
yellowfive@57 544 end
yellowfive@57 545 end,
yellowfive@57 546
yellowfive@57 547 ["OnWidthSet"] = function(self, width)
yellowfive@57 548 local content = self.content
yellowfive@57 549 local treeframe = self.treeframe
yellowfive@57 550 local status = self.status or self.localstatus
yellowfive@57 551 status.fullwidth = width
yellowfive@57 552
yellowfive@57 553 local contentwidth = width - status.treewidth - 20
yellowfive@57 554 if contentwidth < 0 then
yellowfive@57 555 contentwidth = 0
yellowfive@57 556 end
yellowfive@57 557 content:SetWidth(contentwidth)
yellowfive@57 558 content.width = contentwidth
yellowfive@57 559
yellowfive@57 560 local maxtreewidth = math_min(400, width - 50)
yellowfive@57 561
yellowfive@57 562 if maxtreewidth > 100 and status.treewidth > maxtreewidth then
yellowfive@57 563 self:SetTreeWidth(maxtreewidth, status.treesizable)
yellowfive@57 564 end
yellowfive@57 565 treeframe:SetMaxResize(maxtreewidth, 1600)
yellowfive@57 566 end,
yellowfive@57 567
yellowfive@57 568 ["OnHeightSet"] = function(self, height)
yellowfive@57 569 local content = self.content
yellowfive@57 570 local contentheight = height - 20
yellowfive@57 571 if contentheight < 0 then
yellowfive@57 572 contentheight = 0
yellowfive@57 573 end
yellowfive@57 574 content:SetHeight(contentheight)
yellowfive@57 575 content.height = contentheight
yellowfive@57 576 end,
yellowfive@57 577
yellowfive@57 578 ["SetTreeWidth"] = function(self, treewidth, resizable)
yellowfive@57 579 if not resizable then
yellowfive@57 580 if type(treewidth) == 'number' then
yellowfive@57 581 resizable = false
yellowfive@57 582 elseif type(treewidth) == 'boolean' then
yellowfive@57 583 resizable = treewidth
yellowfive@57 584 treewidth = DEFAULT_TREE_WIDTH
yellowfive@57 585 else
yellowfive@57 586 resizable = false
yellowfive@57 587 treewidth = DEFAULT_TREE_WIDTH
yellowfive@57 588 end
yellowfive@57 589 end
yellowfive@57 590 self.treeframe:SetWidth(treewidth)
yellowfive@57 591 self.dragger:EnableMouse(resizable)
yellowfive@57 592
yellowfive@57 593 local status = self.status or self.localstatus
yellowfive@57 594 status.treewidth = treewidth
yellowfive@57 595 status.treesizable = resizable
yellowfive@57 596
yellowfive@57 597 -- recalculate the content width
yellowfive@57 598 if status.fullwidth then
yellowfive@57 599 self:OnWidthSet(status.fullwidth)
yellowfive@57 600 end
yellowfive@57 601 end,
yellowfive@57 602
yellowfive@57 603 ["GetTreeWidth"] = function(self)
yellowfive@57 604 local status = self.status or self.localstatus
yellowfive@57 605 return status.treewidth or DEFAULT_TREE_WIDTH
yellowfive@57 606 end,
yellowfive@57 607
yellowfive@57 608 ["LayoutFinished"] = function(self, width, height)
yellowfive@57 609 if self.noAutoHeight then return end
yellowfive@57 610 self:SetHeight((height or 0) + 20)
yellowfive@57 611 end
yellowfive@57 612 }
yellowfive@57 613
yellowfive@57 614 --[[-----------------------------------------------------------------------------
yellowfive@57 615 Constructor
yellowfive@57 616 -------------------------------------------------------------------------------]]
yellowfive@57 617 local PaneBackdrop = {
yellowfive@57 618 bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
yellowfive@57 619 edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
yellowfive@57 620 tile = true, tileSize = 16, edgeSize = 16,
yellowfive@57 621 insets = { left = 3, right = 3, top = 5, bottom = 3 }
yellowfive@57 622 }
yellowfive@57 623
yellowfive@57 624 local DraggerBackdrop = {
yellowfive@57 625 bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
yellowfive@57 626 edgeFile = nil,
yellowfive@57 627 tile = true, tileSize = 16, edgeSize = 0,
yellowfive@57 628 insets = { left = 3, right = 3, top = 7, bottom = 7 }
yellowfive@57 629 }
yellowfive@57 630
yellowfive@57 631 local function Constructor()
yellowfive@57 632 local num = AceGUI:GetNextWidgetNum(Type)
yellowfive@57 633 local frame = CreateFrame("Frame", nil, UIParent)
yellowfive@57 634
yellowfive@57 635 local treeframe = CreateFrame("Frame", nil, frame)
yellowfive@57 636 treeframe:SetPoint("TOPLEFT")
yellowfive@57 637 treeframe:SetPoint("BOTTOMLEFT")
yellowfive@57 638 treeframe:SetWidth(DEFAULT_TREE_WIDTH)
yellowfive@57 639 treeframe:EnableMouseWheel(true)
yellowfive@57 640 treeframe:SetBackdrop(PaneBackdrop)
yellowfive@57 641 treeframe:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
yellowfive@57 642 treeframe:SetBackdropBorderColor(0.4, 0.4, 0.4)
yellowfive@57 643 treeframe:SetResizable(true)
yellowfive@57 644 treeframe:SetMinResize(100, 1)
yellowfive@57 645 treeframe:SetMaxResize(400, 1600)
yellowfive@57 646 treeframe:SetScript("OnUpdate", FirstFrameUpdate)
yellowfive@57 647 treeframe:SetScript("OnSizeChanged", Tree_OnSizeChanged)
yellowfive@57 648 treeframe:SetScript("OnMouseWheel", Tree_OnMouseWheel)
yellowfive@57 649
yellowfive@57 650 local dragger = CreateFrame("Frame", nil, treeframe)
yellowfive@57 651 dragger:SetWidth(8)
yellowfive@57 652 dragger:SetPoint("TOP", treeframe, "TOPRIGHT")
yellowfive@57 653 dragger:SetPoint("BOTTOM", treeframe, "BOTTOMRIGHT")
yellowfive@57 654 dragger:SetBackdrop(DraggerBackdrop)
yellowfive@57 655 dragger:SetBackdropColor(1, 1, 1, 0)
yellowfive@57 656 dragger:SetScript("OnEnter", Dragger_OnEnter)
yellowfive@57 657 dragger:SetScript("OnLeave", Dragger_OnLeave)
yellowfive@57 658 dragger:SetScript("OnMouseDown", Dragger_OnMouseDown)
yellowfive@57 659 dragger:SetScript("OnMouseUp", Dragger_OnMouseUp)
yellowfive@57 660
yellowfive@57 661 local scrollbar = CreateFrame("Slider", ("AceConfigDialogTreeGroup%dScrollBar"):format(num), treeframe, "UIPanelScrollBarTemplate")
yellowfive@57 662 scrollbar:SetScript("OnValueChanged", nil)
yellowfive@57 663 scrollbar:SetPoint("TOPRIGHT", -10, -26)
yellowfive@57 664 scrollbar:SetPoint("BOTTOMRIGHT", -10, 26)
yellowfive@57 665 scrollbar:SetMinMaxValues(0,0)
yellowfive@57 666 scrollbar:SetValueStep(1)
yellowfive@57 667 scrollbar:SetValue(0)
yellowfive@57 668 scrollbar:SetWidth(16)
yellowfive@57 669 scrollbar:SetScript("OnValueChanged", OnScrollValueChanged)
yellowfive@57 670
yellowfive@57 671 local scrollbg = scrollbar:CreateTexture(nil, "BACKGROUND")
yellowfive@57 672 scrollbg:SetAllPoints(scrollbar)
yellowfive@106 673 scrollbg:SetColorTexture(0,0,0,0.4)
yellowfive@57 674
yellowfive@57 675 local border = CreateFrame("Frame",nil,frame)
yellowfive@57 676 border:SetPoint("TOPLEFT", treeframe, "TOPRIGHT")
yellowfive@57 677 border:SetPoint("BOTTOMRIGHT")
yellowfive@57 678 border:SetBackdrop(PaneBackdrop)
yellowfive@57 679 border:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
yellowfive@57 680 border:SetBackdropBorderColor(0.4, 0.4, 0.4)
yellowfive@57 681
yellowfive@57 682 --Container Support
yellowfive@57 683 local content = CreateFrame("Frame", nil, border)
yellowfive@57 684 content:SetPoint("TOPLEFT", 10, -10)
yellowfive@57 685 content:SetPoint("BOTTOMRIGHT", -10, 10)
yellowfive@57 686
yellowfive@57 687 local widget = {
yellowfive@57 688 frame = frame,
yellowfive@57 689 lines = {},
yellowfive@57 690 levels = {},
yellowfive@57 691 buttons = {},
yellowfive@57 692 hasChildren = {},
yellowfive@57 693 localstatus = { groups = {}, scrollvalue = 0 },
yellowfive@57 694 filter = false,
yellowfive@57 695 treeframe = treeframe,
yellowfive@57 696 dragger = dragger,
yellowfive@57 697 scrollbar = scrollbar,
yellowfive@57 698 border = border,
yellowfive@57 699 content = content,
yellowfive@57 700 type = Type
yellowfive@57 701 }
yellowfive@57 702 for method, func in pairs(methods) do
yellowfive@57 703 widget[method] = func
yellowfive@57 704 end
yellowfive@57 705 treeframe.obj, dragger.obj, scrollbar.obj = widget, widget, widget
yellowfive@57 706
yellowfive@57 707 return AceGUI:RegisterAsContainer(widget)
yellowfive@57 708 end
yellowfive@57 709
yellowfive@57 710 AceGUI:RegisterWidgetType(Type, Constructor, Version)