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