annotate Libs/AceGUI-3.0/widgets/AceGUIContainer-TreeGroup.lua @ 57:01b63b8ed811 v21

total rewrite to version 21
author yellowfive
date Fri, 05 Jun 2015 11:05:15 -0700
parents
children e635cd648e01
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@57 5 local Type, Version = "TreeGroup", 37
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@57 298 end,
yellowfive@57 299
yellowfive@57 300 ["OnRelease"] = function(self)
yellowfive@57 301 self.status = nil
yellowfive@57 302 for k, v in pairs(self.localstatus) do
yellowfive@57 303 if k == "groups" then
yellowfive@57 304 for k2 in pairs(v) do
yellowfive@57 305 v[k2] = nil
yellowfive@57 306 end
yellowfive@57 307 else
yellowfive@57 308 self.localstatus[k] = nil
yellowfive@57 309 end
yellowfive@57 310 end
yellowfive@57 311 self.localstatus.scrollvalue = 0
yellowfive@57 312 self.localstatus.treewidth = DEFAULT_TREE_WIDTH
yellowfive@57 313 self.localstatus.treesizable = DEFAULT_TREE_SIZABLE
yellowfive@57 314 end,
yellowfive@57 315
yellowfive@57 316 ["EnableButtonTooltips"] = function(self, enable)
yellowfive@57 317 self.enabletooltips = enable
yellowfive@57 318 end,
yellowfive@57 319
yellowfive@57 320 ["CreateButton"] = function(self)
yellowfive@57 321 local num = AceGUI:GetNextWidgetNum("TreeGroupButton")
yellowfive@57 322 local button = CreateFrame("Button", ("AceGUI30TreeButton%d"):format(num), self.treeframe, "OptionsListButtonTemplate")
yellowfive@57 323 button.obj = self
yellowfive@57 324
yellowfive@57 325 local icon = button:CreateTexture(nil, "OVERLAY")
yellowfive@57 326 icon:SetWidth(14)
yellowfive@57 327 icon:SetHeight(14)
yellowfive@57 328 button.icon = icon
yellowfive@57 329
yellowfive@57 330 button:SetScript("OnClick",Button_OnClick)
yellowfive@57 331 button:SetScript("OnDoubleClick", Button_OnDoubleClick)
yellowfive@57 332 button:SetScript("OnEnter",Button_OnEnter)
yellowfive@57 333 button:SetScript("OnLeave",Button_OnLeave)
yellowfive@57 334
yellowfive@57 335 button.toggle.button = button
yellowfive@57 336 button.toggle:SetScript("OnClick",Expand_OnClick)
yellowfive@57 337
yellowfive@57 338 return button
yellowfive@57 339 end,
yellowfive@57 340
yellowfive@57 341 ["SetStatusTable"] = function(self, status)
yellowfive@57 342 assert(type(status) == "table")
yellowfive@57 343 self.status = status
yellowfive@57 344 if not status.groups then
yellowfive@57 345 status.groups = {}
yellowfive@57 346 end
yellowfive@57 347 if not status.scrollvalue then
yellowfive@57 348 status.scrollvalue = 0
yellowfive@57 349 end
yellowfive@57 350 if not status.treewidth then
yellowfive@57 351 status.treewidth = DEFAULT_TREE_WIDTH
yellowfive@57 352 end
yellowfive@57 353 if status.treesizable == nil then
yellowfive@57 354 status.treesizable = DEFAULT_TREE_SIZABLE
yellowfive@57 355 end
yellowfive@57 356 self:SetTreeWidth(status.treewidth,status.treesizable)
yellowfive@57 357 self:RefreshTree()
yellowfive@57 358 end,
yellowfive@57 359
yellowfive@57 360 --sets the tree to be displayed
yellowfive@57 361 ["SetTree"] = function(self, tree, filter)
yellowfive@57 362 self.filter = filter
yellowfive@57 363 if tree then
yellowfive@57 364 assert(type(tree) == "table")
yellowfive@57 365 end
yellowfive@57 366 self.tree = tree
yellowfive@57 367 self:RefreshTree()
yellowfive@57 368 end,
yellowfive@57 369
yellowfive@57 370 ["BuildLevel"] = function(self, tree, level, parent)
yellowfive@57 371 local groups = (self.status or self.localstatus).groups
yellowfive@57 372 local hasChildren = self.hasChildren
yellowfive@57 373
yellowfive@57 374 for i, v in ipairs(tree) do
yellowfive@57 375 if v.children then
yellowfive@57 376 if not self.filter or ShouldDisplayLevel(v.children) then
yellowfive@57 377 local line = addLine(self, v, tree, level, parent)
yellowfive@57 378 if groups[line.uniquevalue] then
yellowfive@57 379 self:BuildLevel(v.children, level+1, line)
yellowfive@57 380 end
yellowfive@57 381 end
yellowfive@57 382 elseif v.visible ~= false or not self.filter then
yellowfive@57 383 addLine(self, v, tree, level, parent)
yellowfive@57 384 end
yellowfive@57 385 end
yellowfive@57 386 end,
yellowfive@57 387
yellowfive@57 388 ["RefreshTree"] = function(self,scrollToSelection)
yellowfive@57 389 local buttons = self.buttons
yellowfive@57 390 local lines = self.lines
yellowfive@57 391
yellowfive@57 392 for i, v in ipairs(buttons) do
yellowfive@57 393 v:Hide()
yellowfive@57 394 end
yellowfive@57 395 while lines[1] do
yellowfive@57 396 local t = tremove(lines)
yellowfive@57 397 for k in pairs(t) do
yellowfive@57 398 t[k] = nil
yellowfive@57 399 end
yellowfive@57 400 del(t)
yellowfive@57 401 end
yellowfive@57 402
yellowfive@57 403 if not self.tree then return end
yellowfive@57 404 --Build the list of visible entries from the tree and status tables
yellowfive@57 405 local status = self.status or self.localstatus
yellowfive@57 406 local groupstatus = status.groups
yellowfive@57 407 local tree = self.tree
yellowfive@57 408
yellowfive@57 409 local treeframe = self.treeframe
yellowfive@57 410
yellowfive@57 411 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 412
yellowfive@57 413 self:BuildLevel(tree, 1)
yellowfive@57 414
yellowfive@57 415 local numlines = #lines
yellowfive@57 416
yellowfive@57 417 local maxlines = (floor(((self.treeframe:GetHeight()or 0) - 20 ) / 18))
yellowfive@57 418 if maxlines <= 0 then return end
yellowfive@57 419
yellowfive@57 420 local first, last
yellowfive@57 421
yellowfive@57 422 scrollToSelection = status.scrollToSelection
yellowfive@57 423 status.scrollToSelection = nil
yellowfive@57 424
yellowfive@57 425 if numlines <= maxlines then
yellowfive@57 426 --the whole tree fits in the frame
yellowfive@57 427 status.scrollvalue = 0
yellowfive@57 428 self:ShowScroll(false)
yellowfive@57 429 first, last = 1, numlines
yellowfive@57 430 else
yellowfive@57 431 self:ShowScroll(true)
yellowfive@57 432 --scrolling will be needed
yellowfive@57 433 self.noupdate = true
yellowfive@57 434 self.scrollbar:SetMinMaxValues(0, numlines - maxlines)
yellowfive@57 435 --check if we are scrolled down too far
yellowfive@57 436 if numlines - status.scrollvalue < maxlines then
yellowfive@57 437 status.scrollvalue = numlines - maxlines
yellowfive@57 438 end
yellowfive@57 439 self.noupdate = nil
yellowfive@57 440 first, last = status.scrollvalue+1, status.scrollvalue + maxlines
yellowfive@57 441 --show selection?
yellowfive@57 442 if scrollToSelection and status.selected then
yellowfive@57 443 local show
yellowfive@57 444 for i,line in ipairs(lines) do -- find the line number
yellowfive@57 445 if line.uniquevalue==status.selected then
yellowfive@57 446 show=i
yellowfive@57 447 end
yellowfive@57 448 end
yellowfive@57 449 if not show then
yellowfive@57 450 -- selection was deleted or something?
yellowfive@57 451 elseif show>=first and show<=last then
yellowfive@57 452 -- all good
yellowfive@57 453 else
yellowfive@57 454 -- scrolling needed!
yellowfive@57 455 if show<first then
yellowfive@57 456 status.scrollvalue = show-1
yellowfive@57 457 else
yellowfive@57 458 status.scrollvalue = show-maxlines
yellowfive@57 459 end
yellowfive@57 460 first, last = status.scrollvalue+1, status.scrollvalue + maxlines
yellowfive@57 461 end
yellowfive@57 462 end
yellowfive@57 463 if self.scrollbar:GetValue() ~= status.scrollvalue then
yellowfive@57 464 self.scrollbar:SetValue(status.scrollvalue)
yellowfive@57 465 end
yellowfive@57 466 end
yellowfive@57 467
yellowfive@57 468 local buttonnum = 1
yellowfive@57 469 for i = first, last do
yellowfive@57 470 local line = lines[i]
yellowfive@57 471 local button = buttons[buttonnum]
yellowfive@57 472 if not button then
yellowfive@57 473 button = self:CreateButton()
yellowfive@57 474
yellowfive@57 475 buttons[buttonnum] = button
yellowfive@57 476 button:SetParent(treeframe)
yellowfive@57 477 button:SetFrameLevel(treeframe:GetFrameLevel()+1)
yellowfive@57 478 button:ClearAllPoints()
yellowfive@57 479 if buttonnum == 1 then
yellowfive@57 480 if self.showscroll then
yellowfive@57 481 button:SetPoint("TOPRIGHT", -22, -10)
yellowfive@57 482 button:SetPoint("TOPLEFT", 0, -10)
yellowfive@57 483 else
yellowfive@57 484 button:SetPoint("TOPRIGHT", 0, -10)
yellowfive@57 485 button:SetPoint("TOPLEFT", 0, -10)
yellowfive@57 486 end
yellowfive@57 487 else
yellowfive@57 488 button:SetPoint("TOPRIGHT", buttons[buttonnum-1], "BOTTOMRIGHT",0,0)
yellowfive@57 489 button:SetPoint("TOPLEFT", buttons[buttonnum-1], "BOTTOMLEFT",0,0)
yellowfive@57 490 end
yellowfive@57 491 end
yellowfive@57 492
yellowfive@57 493 UpdateButton(button, line, status.selected == line.uniquevalue, line.hasChildren, groupstatus[line.uniquevalue] )
yellowfive@57 494 button:Show()
yellowfive@57 495 buttonnum = buttonnum + 1
yellowfive@57 496 end
yellowfive@57 497
yellowfive@57 498 end,
yellowfive@57 499
yellowfive@57 500 ["SetSelected"] = function(self, value)
yellowfive@57 501 local status = self.status or self.localstatus
yellowfive@57 502 if status.selected ~= value then
yellowfive@57 503 status.selected = value
yellowfive@57 504 self:Fire("OnGroupSelected", value)
yellowfive@57 505 end
yellowfive@57 506 end,
yellowfive@57 507
yellowfive@57 508 ["Select"] = function(self, uniquevalue, ...)
yellowfive@57 509 self.filter = false
yellowfive@57 510 local status = self.status or self.localstatus
yellowfive@57 511 local groups = status.groups
yellowfive@57 512 local path = {...}
yellowfive@57 513 for i = 1, #path do
yellowfive@57 514 groups[tconcat(path, "\001", 1, i)] = true
yellowfive@57 515 end
yellowfive@57 516 status.selected = uniquevalue
yellowfive@57 517 self:RefreshTree(true)
yellowfive@57 518 self:Fire("OnGroupSelected", uniquevalue)
yellowfive@57 519 end,
yellowfive@57 520
yellowfive@57 521 ["SelectByPath"] = function(self, ...)
yellowfive@57 522 self:Select(BuildUniqueValue(...), ...)
yellowfive@57 523 end,
yellowfive@57 524
yellowfive@57 525 ["SelectByValue"] = function(self, uniquevalue)
yellowfive@57 526 self:Select(uniquevalue, ("\001"):split(uniquevalue))
yellowfive@57 527 end,
yellowfive@57 528
yellowfive@57 529 ["ShowScroll"] = function(self, show)
yellowfive@57 530 self.showscroll = show
yellowfive@57 531 if show then
yellowfive@57 532 self.scrollbar:Show()
yellowfive@57 533 if self.buttons[1] then
yellowfive@57 534 self.buttons[1]:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",-22,-10)
yellowfive@57 535 end
yellowfive@57 536 else
yellowfive@57 537 self.scrollbar:Hide()
yellowfive@57 538 if self.buttons[1] then
yellowfive@57 539 self.buttons[1]:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",0,-10)
yellowfive@57 540 end
yellowfive@57 541 end
yellowfive@57 542 end,
yellowfive@57 543
yellowfive@57 544 ["OnWidthSet"] = function(self, width)
yellowfive@57 545 local content = self.content
yellowfive@57 546 local treeframe = self.treeframe
yellowfive@57 547 local status = self.status or self.localstatus
yellowfive@57 548 status.fullwidth = width
yellowfive@57 549
yellowfive@57 550 local contentwidth = width - status.treewidth - 20
yellowfive@57 551 if contentwidth < 0 then
yellowfive@57 552 contentwidth = 0
yellowfive@57 553 end
yellowfive@57 554 content:SetWidth(contentwidth)
yellowfive@57 555 content.width = contentwidth
yellowfive@57 556
yellowfive@57 557 local maxtreewidth = math_min(400, width - 50)
yellowfive@57 558
yellowfive@57 559 if maxtreewidth > 100 and status.treewidth > maxtreewidth then
yellowfive@57 560 self:SetTreeWidth(maxtreewidth, status.treesizable)
yellowfive@57 561 end
yellowfive@57 562 treeframe:SetMaxResize(maxtreewidth, 1600)
yellowfive@57 563 end,
yellowfive@57 564
yellowfive@57 565 ["OnHeightSet"] = function(self, height)
yellowfive@57 566 local content = self.content
yellowfive@57 567 local contentheight = height - 20
yellowfive@57 568 if contentheight < 0 then
yellowfive@57 569 contentheight = 0
yellowfive@57 570 end
yellowfive@57 571 content:SetHeight(contentheight)
yellowfive@57 572 content.height = contentheight
yellowfive@57 573 end,
yellowfive@57 574
yellowfive@57 575 ["SetTreeWidth"] = function(self, treewidth, resizable)
yellowfive@57 576 if not resizable then
yellowfive@57 577 if type(treewidth) == 'number' then
yellowfive@57 578 resizable = false
yellowfive@57 579 elseif type(treewidth) == 'boolean' then
yellowfive@57 580 resizable = treewidth
yellowfive@57 581 treewidth = DEFAULT_TREE_WIDTH
yellowfive@57 582 else
yellowfive@57 583 resizable = false
yellowfive@57 584 treewidth = DEFAULT_TREE_WIDTH
yellowfive@57 585 end
yellowfive@57 586 end
yellowfive@57 587 self.treeframe:SetWidth(treewidth)
yellowfive@57 588 self.dragger:EnableMouse(resizable)
yellowfive@57 589
yellowfive@57 590 local status = self.status or self.localstatus
yellowfive@57 591 status.treewidth = treewidth
yellowfive@57 592 status.treesizable = resizable
yellowfive@57 593
yellowfive@57 594 -- recalculate the content width
yellowfive@57 595 if status.fullwidth then
yellowfive@57 596 self:OnWidthSet(status.fullwidth)
yellowfive@57 597 end
yellowfive@57 598 end,
yellowfive@57 599
yellowfive@57 600 ["GetTreeWidth"] = function(self)
yellowfive@57 601 local status = self.status or self.localstatus
yellowfive@57 602 return status.treewidth or DEFAULT_TREE_WIDTH
yellowfive@57 603 end,
yellowfive@57 604
yellowfive@57 605 ["LayoutFinished"] = function(self, width, height)
yellowfive@57 606 if self.noAutoHeight then return end
yellowfive@57 607 self:SetHeight((height or 0) + 20)
yellowfive@57 608 end
yellowfive@57 609 }
yellowfive@57 610
yellowfive@57 611 --[[-----------------------------------------------------------------------------
yellowfive@57 612 Constructor
yellowfive@57 613 -------------------------------------------------------------------------------]]
yellowfive@57 614 local PaneBackdrop = {
yellowfive@57 615 bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
yellowfive@57 616 edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
yellowfive@57 617 tile = true, tileSize = 16, edgeSize = 16,
yellowfive@57 618 insets = { left = 3, right = 3, top = 5, bottom = 3 }
yellowfive@57 619 }
yellowfive@57 620
yellowfive@57 621 local DraggerBackdrop = {
yellowfive@57 622 bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
yellowfive@57 623 edgeFile = nil,
yellowfive@57 624 tile = true, tileSize = 16, edgeSize = 0,
yellowfive@57 625 insets = { left = 3, right = 3, top = 7, bottom = 7 }
yellowfive@57 626 }
yellowfive@57 627
yellowfive@57 628 local function Constructor()
yellowfive@57 629 local num = AceGUI:GetNextWidgetNum(Type)
yellowfive@57 630 local frame = CreateFrame("Frame", nil, UIParent)
yellowfive@57 631
yellowfive@57 632 local treeframe = CreateFrame("Frame", nil, frame)
yellowfive@57 633 treeframe:SetPoint("TOPLEFT")
yellowfive@57 634 treeframe:SetPoint("BOTTOMLEFT")
yellowfive@57 635 treeframe:SetWidth(DEFAULT_TREE_WIDTH)
yellowfive@57 636 treeframe:EnableMouseWheel(true)
yellowfive@57 637 treeframe:SetBackdrop(PaneBackdrop)
yellowfive@57 638 treeframe:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
yellowfive@57 639 treeframe:SetBackdropBorderColor(0.4, 0.4, 0.4)
yellowfive@57 640 treeframe:SetResizable(true)
yellowfive@57 641 treeframe:SetMinResize(100, 1)
yellowfive@57 642 treeframe:SetMaxResize(400, 1600)
yellowfive@57 643 treeframe:SetScript("OnUpdate", FirstFrameUpdate)
yellowfive@57 644 treeframe:SetScript("OnSizeChanged", Tree_OnSizeChanged)
yellowfive@57 645 treeframe:SetScript("OnMouseWheel", Tree_OnMouseWheel)
yellowfive@57 646
yellowfive@57 647 local dragger = CreateFrame("Frame", nil, treeframe)
yellowfive@57 648 dragger:SetWidth(8)
yellowfive@57 649 dragger:SetPoint("TOP", treeframe, "TOPRIGHT")
yellowfive@57 650 dragger:SetPoint("BOTTOM", treeframe, "BOTTOMRIGHT")
yellowfive@57 651 dragger:SetBackdrop(DraggerBackdrop)
yellowfive@57 652 dragger:SetBackdropColor(1, 1, 1, 0)
yellowfive@57 653 dragger:SetScript("OnEnter", Dragger_OnEnter)
yellowfive@57 654 dragger:SetScript("OnLeave", Dragger_OnLeave)
yellowfive@57 655 dragger:SetScript("OnMouseDown", Dragger_OnMouseDown)
yellowfive@57 656 dragger:SetScript("OnMouseUp", Dragger_OnMouseUp)
yellowfive@57 657
yellowfive@57 658 local scrollbar = CreateFrame("Slider", ("AceConfigDialogTreeGroup%dScrollBar"):format(num), treeframe, "UIPanelScrollBarTemplate")
yellowfive@57 659 scrollbar:SetScript("OnValueChanged", nil)
yellowfive@57 660 scrollbar:SetPoint("TOPRIGHT", -10, -26)
yellowfive@57 661 scrollbar:SetPoint("BOTTOMRIGHT", -10, 26)
yellowfive@57 662 scrollbar:SetMinMaxValues(0,0)
yellowfive@57 663 scrollbar:SetValueStep(1)
yellowfive@57 664 scrollbar:SetValue(0)
yellowfive@57 665 scrollbar:SetWidth(16)
yellowfive@57 666 scrollbar:SetScript("OnValueChanged", OnScrollValueChanged)
yellowfive@57 667
yellowfive@57 668 local scrollbg = scrollbar:CreateTexture(nil, "BACKGROUND")
yellowfive@57 669 scrollbg:SetAllPoints(scrollbar)
yellowfive@57 670 scrollbg:SetTexture(0,0,0,0.4)
yellowfive@57 671
yellowfive@57 672 local border = CreateFrame("Frame",nil,frame)
yellowfive@57 673 border:SetPoint("TOPLEFT", treeframe, "TOPRIGHT")
yellowfive@57 674 border:SetPoint("BOTTOMRIGHT")
yellowfive@57 675 border:SetBackdrop(PaneBackdrop)
yellowfive@57 676 border:SetBackdropColor(0.1, 0.1, 0.1, 0.5)
yellowfive@57 677 border:SetBackdropBorderColor(0.4, 0.4, 0.4)
yellowfive@57 678
yellowfive@57 679 --Container Support
yellowfive@57 680 local content = CreateFrame("Frame", nil, border)
yellowfive@57 681 content:SetPoint("TOPLEFT", 10, -10)
yellowfive@57 682 content:SetPoint("BOTTOMRIGHT", -10, 10)
yellowfive@57 683
yellowfive@57 684 local widget = {
yellowfive@57 685 frame = frame,
yellowfive@57 686 lines = {},
yellowfive@57 687 levels = {},
yellowfive@57 688 buttons = {},
yellowfive@57 689 hasChildren = {},
yellowfive@57 690 localstatus = { groups = {}, scrollvalue = 0 },
yellowfive@57 691 filter = false,
yellowfive@57 692 treeframe = treeframe,
yellowfive@57 693 dragger = dragger,
yellowfive@57 694 scrollbar = scrollbar,
yellowfive@57 695 border = border,
yellowfive@57 696 content = content,
yellowfive@57 697 type = Type
yellowfive@57 698 }
yellowfive@57 699 for method, func in pairs(methods) do
yellowfive@57 700 widget[method] = func
yellowfive@57 701 end
yellowfive@57 702 treeframe.obj, dragger.obj, scrollbar.obj = widget, widget, widget
yellowfive@57 703
yellowfive@57 704 return AceGUI:RegisterAsContainer(widget)
yellowfive@57 705 end
yellowfive@57 706
yellowfive@57 707 AceGUI:RegisterWidgetType(Type, Constructor, Version)