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