yellowfive@57
|
1 --- **AceGUI-3.0** provides access to numerous widgets which can be used to create GUIs.
|
yellowfive@57
|
2 -- AceGUI is used by AceConfigDialog to create the option GUIs, but you can use it by itself
|
yellowfive@57
|
3 -- to create any custom GUI. There are more extensive examples in the test suite in the Ace3
|
yellowfive@57
|
4 -- stand-alone distribution.
|
yellowfive@57
|
5 --
|
yellowfive@57
|
6 -- **Note**: When using AceGUI-3.0 directly, please do not modify the frames of the widgets directly,
|
yellowfive@57
|
7 -- as any "unknown" change to the widgets will cause addons that get your widget out of the widget pool
|
yellowfive@57
|
8 -- to misbehave. If you think some part of a widget should be modifiable, please open a ticket, and we"ll
|
yellowfive@57
|
9 -- implement a proper API to modify it.
|
yellowfive@57
|
10 -- @usage
|
yellowfive@57
|
11 -- local AceGUI = LibStub("AceGUI-3.0")
|
yellowfive@57
|
12 -- -- Create a container frame
|
yellowfive@57
|
13 -- local f = AceGUI:Create("Frame")
|
yellowfive@57
|
14 -- f:SetCallback("OnClose",function(widget) AceGUI:Release(widget) end)
|
yellowfive@57
|
15 -- f:SetTitle("AceGUI-3.0 Example")
|
yellowfive@57
|
16 -- f:SetStatusText("Status Bar")
|
yellowfive@57
|
17 -- f:SetLayout("Flow")
|
yellowfive@57
|
18 -- -- Create a button
|
yellowfive@57
|
19 -- local btn = AceGUI:Create("Button")
|
yellowfive@57
|
20 -- btn:SetWidth(170)
|
yellowfive@57
|
21 -- btn:SetText("Button !")
|
yellowfive@57
|
22 -- btn:SetCallback("OnClick", function() print("Click!") end)
|
yellowfive@57
|
23 -- -- Add the button to the container
|
yellowfive@57
|
24 -- f:AddChild(btn)
|
yellowfive@57
|
25 -- @class file
|
yellowfive@57
|
26 -- @name AceGUI-3.0
|
yellowfive@57
|
27 -- @release $Id: AceGUI-3.0.lua 1102 2013-10-25 14:15:23Z nevcairiel $
|
yellowfive@57
|
28 local ACEGUI_MAJOR, ACEGUI_MINOR = "AceGUI-3.0", 34
|
yellowfive@57
|
29 local AceGUI, oldminor = LibStub:NewLibrary(ACEGUI_MAJOR, ACEGUI_MINOR)
|
yellowfive@57
|
30
|
yellowfive@57
|
31 if not AceGUI then return end -- No upgrade needed
|
yellowfive@57
|
32
|
yellowfive@57
|
33 -- Lua APIs
|
yellowfive@57
|
34 local tconcat, tremove, tinsert = table.concat, table.remove, table.insert
|
yellowfive@57
|
35 local select, pairs, next, type = select, pairs, next, type
|
yellowfive@57
|
36 local error, assert, loadstring = error, assert, loadstring
|
yellowfive@57
|
37 local setmetatable, rawget, rawset = setmetatable, rawget, rawset
|
yellowfive@57
|
38 local math_max = math.max
|
yellowfive@57
|
39
|
yellowfive@57
|
40 -- WoW APIs
|
yellowfive@57
|
41 local UIParent = UIParent
|
yellowfive@57
|
42
|
yellowfive@57
|
43 -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
yellowfive@57
|
44 -- List them here for Mikk's FindGlobals script
|
yellowfive@57
|
45 -- GLOBALS: geterrorhandler, LibStub
|
yellowfive@57
|
46
|
yellowfive@57
|
47 --local con = LibStub("AceConsole-3.0",true)
|
yellowfive@57
|
48
|
yellowfive@57
|
49 AceGUI.WidgetRegistry = AceGUI.WidgetRegistry or {}
|
yellowfive@57
|
50 AceGUI.LayoutRegistry = AceGUI.LayoutRegistry or {}
|
yellowfive@57
|
51 AceGUI.WidgetBase = AceGUI.WidgetBase or {}
|
yellowfive@57
|
52 AceGUI.WidgetContainerBase = AceGUI.WidgetContainerBase or {}
|
yellowfive@57
|
53 AceGUI.WidgetVersions = AceGUI.WidgetVersions or {}
|
yellowfive@57
|
54
|
yellowfive@57
|
55 -- local upvalues
|
yellowfive@57
|
56 local WidgetRegistry = AceGUI.WidgetRegistry
|
yellowfive@57
|
57 local LayoutRegistry = AceGUI.LayoutRegistry
|
yellowfive@57
|
58 local WidgetVersions = AceGUI.WidgetVersions
|
yellowfive@57
|
59
|
yellowfive@57
|
60 --[[
|
yellowfive@57
|
61 xpcall safecall implementation
|
yellowfive@57
|
62 ]]
|
yellowfive@57
|
63 local xpcall = xpcall
|
yellowfive@57
|
64
|
yellowfive@57
|
65 local function errorhandler(err)
|
yellowfive@57
|
66 return geterrorhandler()(err)
|
yellowfive@57
|
67 end
|
yellowfive@57
|
68
|
yellowfive@57
|
69 local function CreateDispatcher(argCount)
|
yellowfive@57
|
70 local code = [[
|
yellowfive@57
|
71 local xpcall, eh = ...
|
yellowfive@57
|
72 local method, ARGS
|
yellowfive@57
|
73 local function call() return method(ARGS) end
|
yellowfive@57
|
74
|
yellowfive@57
|
75 local function dispatch(func, ...)
|
yellowfive@57
|
76 method = func
|
yellowfive@57
|
77 if not method then return end
|
yellowfive@57
|
78 ARGS = ...
|
yellowfive@57
|
79 return xpcall(call, eh)
|
yellowfive@57
|
80 end
|
yellowfive@57
|
81
|
yellowfive@57
|
82 return dispatch
|
yellowfive@57
|
83 ]]
|
yellowfive@57
|
84
|
yellowfive@57
|
85 local ARGS = {}
|
yellowfive@57
|
86 for i = 1, argCount do ARGS[i] = "arg"..i end
|
yellowfive@57
|
87 code = code:gsub("ARGS", tconcat(ARGS, ", "))
|
yellowfive@57
|
88 return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
|
yellowfive@57
|
89 end
|
yellowfive@57
|
90
|
yellowfive@57
|
91 local Dispatchers = setmetatable({}, {__index=function(self, argCount)
|
yellowfive@57
|
92 local dispatcher = CreateDispatcher(argCount)
|
yellowfive@57
|
93 rawset(self, argCount, dispatcher)
|
yellowfive@57
|
94 return dispatcher
|
yellowfive@57
|
95 end})
|
yellowfive@57
|
96 Dispatchers[0] = function(func)
|
yellowfive@57
|
97 return xpcall(func, errorhandler)
|
yellowfive@57
|
98 end
|
yellowfive@57
|
99
|
yellowfive@57
|
100 local function safecall(func, ...)
|
yellowfive@57
|
101 return Dispatchers[select("#", ...)](func, ...)
|
yellowfive@57
|
102 end
|
yellowfive@57
|
103
|
yellowfive@57
|
104 -- Recycling functions
|
yellowfive@57
|
105 local newWidget, delWidget
|
yellowfive@57
|
106 do
|
yellowfive@57
|
107 -- Version Upgrade in Minor 29
|
yellowfive@57
|
108 -- Internal Storage of the objects changed, from an array table
|
yellowfive@57
|
109 -- to a hash table, and additionally we introduced versioning on
|
yellowfive@57
|
110 -- the widgets which would discard all widgets from a pre-29 version
|
yellowfive@57
|
111 -- anyway, so we just clear the storage now, and don't try to
|
yellowfive@57
|
112 -- convert the storage tables to the new format.
|
yellowfive@57
|
113 -- This should generally not cause *many* widgets to end up in trash,
|
yellowfive@57
|
114 -- since once dialogs are opened, all addons should be loaded already
|
yellowfive@57
|
115 -- and AceGUI should be on the latest version available on the users
|
yellowfive@57
|
116 -- setup.
|
yellowfive@57
|
117 -- -- nevcairiel - Nov 2nd, 2009
|
yellowfive@57
|
118 if oldminor and oldminor < 29 and AceGUI.objPools then
|
yellowfive@57
|
119 AceGUI.objPools = nil
|
yellowfive@57
|
120 end
|
yellowfive@57
|
121
|
yellowfive@57
|
122 AceGUI.objPools = AceGUI.objPools or {}
|
yellowfive@57
|
123 local objPools = AceGUI.objPools
|
yellowfive@57
|
124 --Returns a new instance, if none are available either returns a new table or calls the given contructor
|
yellowfive@57
|
125 function newWidget(type)
|
yellowfive@57
|
126 if not WidgetRegistry[type] then
|
yellowfive@57
|
127 error("Attempt to instantiate unknown widget type", 2)
|
yellowfive@57
|
128 end
|
yellowfive@57
|
129
|
yellowfive@57
|
130 if not objPools[type] then
|
yellowfive@57
|
131 objPools[type] = {}
|
yellowfive@57
|
132 end
|
yellowfive@57
|
133
|
yellowfive@57
|
134 local newObj = next(objPools[type])
|
yellowfive@57
|
135 if not newObj then
|
yellowfive@57
|
136 newObj = WidgetRegistry[type]()
|
yellowfive@57
|
137 newObj.AceGUIWidgetVersion = WidgetVersions[type]
|
yellowfive@57
|
138 else
|
yellowfive@57
|
139 objPools[type][newObj] = nil
|
yellowfive@57
|
140 -- if the widget is older then the latest, don't even try to reuse it
|
yellowfive@57
|
141 -- just forget about it, and grab a new one.
|
yellowfive@57
|
142 if not newObj.AceGUIWidgetVersion or newObj.AceGUIWidgetVersion < WidgetVersions[type] then
|
yellowfive@57
|
143 return newWidget(type)
|
yellowfive@57
|
144 end
|
yellowfive@57
|
145 end
|
yellowfive@57
|
146 return newObj
|
yellowfive@57
|
147 end
|
yellowfive@57
|
148 -- Releases an instance to the Pool
|
yellowfive@57
|
149 function delWidget(obj,type)
|
yellowfive@57
|
150 if not objPools[type] then
|
yellowfive@57
|
151 objPools[type] = {}
|
yellowfive@57
|
152 end
|
yellowfive@57
|
153 if objPools[type][obj] then
|
yellowfive@57
|
154 error("Attempt to Release Widget that is already released", 2)
|
yellowfive@57
|
155 end
|
yellowfive@57
|
156 objPools[type][obj] = true
|
yellowfive@57
|
157 end
|
yellowfive@57
|
158 end
|
yellowfive@57
|
159
|
yellowfive@57
|
160
|
yellowfive@57
|
161 -------------------
|
yellowfive@57
|
162 -- API Functions --
|
yellowfive@57
|
163 -------------------
|
yellowfive@57
|
164
|
yellowfive@57
|
165 -- Gets a widget Object
|
yellowfive@57
|
166
|
yellowfive@57
|
167 --- Create a new Widget of the given type.
|
yellowfive@57
|
168 -- This function will instantiate a new widget (or use one from the widget pool), and call the
|
yellowfive@57
|
169 -- OnAcquire function on it, before returning.
|
yellowfive@57
|
170 -- @param type The type of the widget.
|
yellowfive@57
|
171 -- @return The newly created widget.
|
yellowfive@57
|
172 function AceGUI:Create(type)
|
yellowfive@57
|
173 if WidgetRegistry[type] then
|
yellowfive@57
|
174 local widget = newWidget(type)
|
yellowfive@57
|
175
|
yellowfive@57
|
176 if rawget(widget, "Acquire") then
|
yellowfive@57
|
177 widget.OnAcquire = widget.Acquire
|
yellowfive@57
|
178 widget.Acquire = nil
|
yellowfive@57
|
179 elseif rawget(widget, "Aquire") then
|
yellowfive@57
|
180 widget.OnAcquire = widget.Aquire
|
yellowfive@57
|
181 widget.Aquire = nil
|
yellowfive@57
|
182 end
|
yellowfive@57
|
183
|
yellowfive@57
|
184 if rawget(widget, "Release") then
|
yellowfive@57
|
185 widget.OnRelease = rawget(widget, "Release")
|
yellowfive@57
|
186 widget.Release = nil
|
yellowfive@57
|
187 end
|
yellowfive@57
|
188
|
yellowfive@57
|
189 if widget.OnAcquire then
|
yellowfive@57
|
190 widget:OnAcquire()
|
yellowfive@57
|
191 else
|
yellowfive@57
|
192 error(("Widget type %s doesn't supply an OnAcquire Function"):format(type))
|
yellowfive@57
|
193 end
|
yellowfive@57
|
194 -- Set the default Layout ("List")
|
yellowfive@57
|
195 safecall(widget.SetLayout, widget, "List")
|
yellowfive@57
|
196 safecall(widget.ResumeLayout, widget)
|
yellowfive@57
|
197 return widget
|
yellowfive@57
|
198 end
|
yellowfive@57
|
199 end
|
yellowfive@57
|
200
|
yellowfive@57
|
201 --- Releases a widget Object.
|
yellowfive@57
|
202 -- This function calls OnRelease on the widget and places it back in the widget pool.
|
yellowfive@57
|
203 -- Any data on the widget is being erased, and the widget will be hidden.\\
|
yellowfive@57
|
204 -- If this widget is a Container-Widget, all of its Child-Widgets will be releases as well.
|
yellowfive@57
|
205 -- @param widget The widget to release
|
yellowfive@57
|
206 function AceGUI:Release(widget)
|
yellowfive@57
|
207 safecall(widget.PauseLayout, widget)
|
yellowfive@57
|
208 widget:Fire("OnRelease")
|
yellowfive@57
|
209 safecall(widget.ReleaseChildren, widget)
|
yellowfive@57
|
210
|
yellowfive@57
|
211 if widget.OnRelease then
|
yellowfive@57
|
212 widget:OnRelease()
|
yellowfive@57
|
213 -- else
|
yellowfive@57
|
214 -- error(("Widget type %s doesn't supply an OnRelease Function"):format(widget.type))
|
yellowfive@57
|
215 end
|
yellowfive@57
|
216 for k in pairs(widget.userdata) do
|
yellowfive@57
|
217 widget.userdata[k] = nil
|
yellowfive@57
|
218 end
|
yellowfive@57
|
219 for k in pairs(widget.events) do
|
yellowfive@57
|
220 widget.events[k] = nil
|
yellowfive@57
|
221 end
|
yellowfive@57
|
222 widget.width = nil
|
yellowfive@57
|
223 widget.relWidth = nil
|
yellowfive@57
|
224 widget.height = nil
|
yellowfive@57
|
225 widget.relHeight = nil
|
yellowfive@57
|
226 widget.noAutoHeight = nil
|
yellowfive@57
|
227 widget.frame:ClearAllPoints()
|
yellowfive@57
|
228 widget.frame:Hide()
|
yellowfive@57
|
229 widget.frame:SetParent(UIParent)
|
yellowfive@57
|
230 widget.frame.width = nil
|
yellowfive@57
|
231 widget.frame.height = nil
|
yellowfive@57
|
232 if widget.content then
|
yellowfive@57
|
233 widget.content.width = nil
|
yellowfive@57
|
234 widget.content.height = nil
|
yellowfive@57
|
235 end
|
yellowfive@57
|
236 delWidget(widget, widget.type)
|
yellowfive@57
|
237 end
|
yellowfive@57
|
238
|
yellowfive@57
|
239 -----------
|
yellowfive@57
|
240 -- Focus --
|
yellowfive@57
|
241 -----------
|
yellowfive@57
|
242
|
yellowfive@57
|
243
|
yellowfive@57
|
244 --- Called when a widget has taken focus.
|
yellowfive@57
|
245 -- e.g. Dropdowns opening, Editboxes gaining kb focus
|
yellowfive@57
|
246 -- @param widget The widget that should be focused
|
yellowfive@57
|
247 function AceGUI:SetFocus(widget)
|
yellowfive@57
|
248 if self.FocusedWidget and self.FocusedWidget ~= widget then
|
yellowfive@57
|
249 safecall(self.FocusedWidget.ClearFocus, self.FocusedWidget)
|
yellowfive@57
|
250 end
|
yellowfive@57
|
251 self.FocusedWidget = widget
|
yellowfive@57
|
252 end
|
yellowfive@57
|
253
|
yellowfive@57
|
254
|
yellowfive@57
|
255 --- Called when something has happened that could cause widgets with focus to drop it
|
yellowfive@57
|
256 -- e.g. titlebar of a frame being clicked
|
yellowfive@57
|
257 function AceGUI:ClearFocus()
|
yellowfive@57
|
258 if self.FocusedWidget then
|
yellowfive@57
|
259 safecall(self.FocusedWidget.ClearFocus, self.FocusedWidget)
|
yellowfive@57
|
260 self.FocusedWidget = nil
|
yellowfive@57
|
261 end
|
yellowfive@57
|
262 end
|
yellowfive@57
|
263
|
yellowfive@57
|
264 -------------
|
yellowfive@57
|
265 -- Widgets --
|
yellowfive@57
|
266 -------------
|
yellowfive@57
|
267 --[[
|
yellowfive@57
|
268 Widgets must provide the following functions
|
yellowfive@57
|
269 OnAcquire() - Called when the object is acquired, should set everything to a default hidden state
|
yellowfive@57
|
270
|
yellowfive@57
|
271 And the following members
|
yellowfive@57
|
272 frame - the frame or derivitive object that will be treated as the widget for size and anchoring purposes
|
yellowfive@57
|
273 type - the type of the object, same as the name given to :RegisterWidget()
|
yellowfive@57
|
274
|
yellowfive@57
|
275 Widgets contain a table called userdata, this is a safe place to store data associated with the wigdet
|
yellowfive@57
|
276 It will be cleared automatically when a widget is released
|
yellowfive@57
|
277 Placing values directly into a widget object should be avoided
|
yellowfive@57
|
278
|
yellowfive@57
|
279 If the Widget can act as a container for other Widgets the following
|
yellowfive@57
|
280 content - frame or derivitive that children will be anchored to
|
yellowfive@57
|
281
|
yellowfive@57
|
282 The Widget can supply the following Optional Members
|
yellowfive@57
|
283 :OnRelease() - Called when the object is Released, should remove any additional anchors and clear any data
|
yellowfive@57
|
284 :OnWidthSet(width) - Called when the width of the widget is changed
|
yellowfive@57
|
285 :OnHeightSet(height) - Called when the height of the widget is changed
|
yellowfive@57
|
286 Widgets should not use the OnSizeChanged events of thier frame or content members, use these methods instead
|
yellowfive@57
|
287 AceGUI already sets a handler to the event
|
yellowfive@57
|
288 :LayoutFinished(width, height) - called after a layout has finished, the width and height will be the width and height of the
|
yellowfive@57
|
289 area used for controls. These can be nil if the layout used the existing size to layout the controls.
|
yellowfive@57
|
290
|
yellowfive@57
|
291 ]]
|
yellowfive@57
|
292
|
yellowfive@57
|
293 --------------------------
|
yellowfive@57
|
294 -- Widget Base Template --
|
yellowfive@57
|
295 --------------------------
|
yellowfive@57
|
296 do
|
yellowfive@57
|
297 local WidgetBase = AceGUI.WidgetBase
|
yellowfive@57
|
298
|
yellowfive@57
|
299 WidgetBase.SetParent = function(self, parent)
|
yellowfive@57
|
300 local frame = self.frame
|
yellowfive@57
|
301 frame:SetParent(nil)
|
yellowfive@57
|
302 frame:SetParent(parent.content)
|
yellowfive@57
|
303 self.parent = parent
|
yellowfive@57
|
304 end
|
yellowfive@57
|
305
|
yellowfive@57
|
306 WidgetBase.SetCallback = function(self, name, func)
|
yellowfive@57
|
307 if type(func) == "function" then
|
yellowfive@57
|
308 self.events[name] = func
|
yellowfive@57
|
309 end
|
yellowfive@57
|
310 end
|
yellowfive@57
|
311
|
yellowfive@57
|
312 WidgetBase.Fire = function(self, name, ...)
|
yellowfive@57
|
313 if self.events[name] then
|
yellowfive@57
|
314 local success, ret = safecall(self.events[name], self, name, ...)
|
yellowfive@57
|
315 if success then
|
yellowfive@57
|
316 return ret
|
yellowfive@57
|
317 end
|
yellowfive@57
|
318 end
|
yellowfive@57
|
319 end
|
yellowfive@57
|
320
|
yellowfive@57
|
321 WidgetBase.SetWidth = function(self, width)
|
yellowfive@57
|
322 self.frame:SetWidth(width)
|
yellowfive@57
|
323 self.frame.width = width
|
yellowfive@57
|
324 if self.OnWidthSet then
|
yellowfive@57
|
325 self:OnWidthSet(width)
|
yellowfive@57
|
326 end
|
yellowfive@57
|
327 end
|
yellowfive@57
|
328
|
yellowfive@57
|
329 WidgetBase.SetRelativeWidth = function(self, width)
|
yellowfive@57
|
330 if width <= 0 or width > 1 then
|
yellowfive@57
|
331 error(":SetRelativeWidth(width): Invalid relative width.", 2)
|
yellowfive@57
|
332 end
|
yellowfive@57
|
333 self.relWidth = width
|
yellowfive@57
|
334 self.width = "relative"
|
yellowfive@57
|
335 end
|
yellowfive@57
|
336
|
yellowfive@57
|
337 WidgetBase.SetHeight = function(self, height)
|
yellowfive@57
|
338 self.frame:SetHeight(height)
|
yellowfive@57
|
339 self.frame.height = height
|
yellowfive@57
|
340 if self.OnHeightSet then
|
yellowfive@57
|
341 self:OnHeightSet(height)
|
yellowfive@57
|
342 end
|
yellowfive@57
|
343 end
|
yellowfive@57
|
344
|
yellowfive@57
|
345 --[[ WidgetBase.SetRelativeHeight = function(self, height)
|
yellowfive@57
|
346 if height <= 0 or height > 1 then
|
yellowfive@57
|
347 error(":SetRelativeHeight(height): Invalid relative height.", 2)
|
yellowfive@57
|
348 end
|
yellowfive@57
|
349 self.relHeight = height
|
yellowfive@57
|
350 self.height = "relative"
|
yellowfive@57
|
351 end ]]
|
yellowfive@57
|
352
|
yellowfive@57
|
353 WidgetBase.IsVisible = function(self)
|
yellowfive@57
|
354 return self.frame:IsVisible()
|
yellowfive@57
|
355 end
|
yellowfive@57
|
356
|
yellowfive@57
|
357 WidgetBase.IsShown= function(self)
|
yellowfive@57
|
358 return self.frame:IsShown()
|
yellowfive@57
|
359 end
|
yellowfive@57
|
360
|
yellowfive@57
|
361 WidgetBase.Release = function(self)
|
yellowfive@57
|
362 AceGUI:Release(self)
|
yellowfive@57
|
363 end
|
yellowfive@57
|
364
|
yellowfive@57
|
365 WidgetBase.SetPoint = function(self, ...)
|
yellowfive@57
|
366 return self.frame:SetPoint(...)
|
yellowfive@57
|
367 end
|
yellowfive@57
|
368
|
yellowfive@57
|
369 WidgetBase.ClearAllPoints = function(self)
|
yellowfive@57
|
370 return self.frame:ClearAllPoints()
|
yellowfive@57
|
371 end
|
yellowfive@57
|
372
|
yellowfive@57
|
373 WidgetBase.GetNumPoints = function(self)
|
yellowfive@57
|
374 return self.frame:GetNumPoints()
|
yellowfive@57
|
375 end
|
yellowfive@57
|
376
|
yellowfive@57
|
377 WidgetBase.GetPoint = function(self, ...)
|
yellowfive@57
|
378 return self.frame:GetPoint(...)
|
yellowfive@57
|
379 end
|
yellowfive@57
|
380
|
yellowfive@57
|
381 WidgetBase.GetUserDataTable = function(self)
|
yellowfive@57
|
382 return self.userdata
|
yellowfive@57
|
383 end
|
yellowfive@57
|
384
|
yellowfive@57
|
385 WidgetBase.SetUserData = function(self, key, value)
|
yellowfive@57
|
386 self.userdata[key] = value
|
yellowfive@57
|
387 end
|
yellowfive@57
|
388
|
yellowfive@57
|
389 WidgetBase.GetUserData = function(self, key)
|
yellowfive@57
|
390 return self.userdata[key]
|
yellowfive@57
|
391 end
|
yellowfive@57
|
392
|
yellowfive@57
|
393 WidgetBase.IsFullHeight = function(self)
|
yellowfive@57
|
394 return self.height == "fill"
|
yellowfive@57
|
395 end
|
yellowfive@57
|
396
|
yellowfive@57
|
397 WidgetBase.SetFullHeight = function(self, isFull)
|
yellowfive@57
|
398 if isFull then
|
yellowfive@57
|
399 self.height = "fill"
|
yellowfive@57
|
400 else
|
yellowfive@57
|
401 self.height = nil
|
yellowfive@57
|
402 end
|
yellowfive@57
|
403 end
|
yellowfive@57
|
404
|
yellowfive@57
|
405 WidgetBase.IsFullWidth = function(self)
|
yellowfive@57
|
406 return self.width == "fill"
|
yellowfive@57
|
407 end
|
yellowfive@57
|
408
|
yellowfive@57
|
409 WidgetBase.SetFullWidth = function(self, isFull)
|
yellowfive@57
|
410 if isFull then
|
yellowfive@57
|
411 self.width = "fill"
|
yellowfive@57
|
412 else
|
yellowfive@57
|
413 self.width = nil
|
yellowfive@57
|
414 end
|
yellowfive@57
|
415 end
|
yellowfive@57
|
416
|
yellowfive@57
|
417 -- local function LayoutOnUpdate(this)
|
yellowfive@57
|
418 -- this:SetScript("OnUpdate",nil)
|
yellowfive@57
|
419 -- this.obj:PerformLayout()
|
yellowfive@57
|
420 -- end
|
yellowfive@57
|
421
|
yellowfive@57
|
422 local WidgetContainerBase = AceGUI.WidgetContainerBase
|
yellowfive@57
|
423
|
yellowfive@57
|
424 WidgetContainerBase.PauseLayout = function(self)
|
yellowfive@57
|
425 self.LayoutPaused = true
|
yellowfive@57
|
426 end
|
yellowfive@57
|
427
|
yellowfive@57
|
428 WidgetContainerBase.ResumeLayout = function(self)
|
yellowfive@57
|
429 self.LayoutPaused = nil
|
yellowfive@57
|
430 end
|
yellowfive@57
|
431
|
yellowfive@57
|
432 WidgetContainerBase.PerformLayout = function(self)
|
yellowfive@57
|
433 if self.LayoutPaused then
|
yellowfive@57
|
434 return
|
yellowfive@57
|
435 end
|
yellowfive@57
|
436 safecall(self.LayoutFunc, self.content, self.children)
|
yellowfive@57
|
437 end
|
yellowfive@57
|
438
|
yellowfive@57
|
439 --call this function to layout, makes sure layed out objects get a frame to get sizes etc
|
yellowfive@57
|
440 WidgetContainerBase.DoLayout = function(self)
|
yellowfive@57
|
441 self:PerformLayout()
|
yellowfive@57
|
442 -- if not self.parent then
|
yellowfive@57
|
443 -- self.frame:SetScript("OnUpdate", LayoutOnUpdate)
|
yellowfive@57
|
444 -- end
|
yellowfive@57
|
445 end
|
yellowfive@57
|
446
|
yellowfive@57
|
447 WidgetContainerBase.AddChild = function(self, child, beforeWidget)
|
yellowfive@57
|
448 if beforeWidget then
|
yellowfive@57
|
449 local siblingIndex = 1
|
yellowfive@57
|
450 for _, widget in pairs(self.children) do
|
yellowfive@57
|
451 if widget == beforeWidget then
|
yellowfive@57
|
452 break
|
yellowfive@57
|
453 end
|
yellowfive@57
|
454 siblingIndex = siblingIndex + 1
|
yellowfive@57
|
455 end
|
yellowfive@57
|
456 tinsert(self.children, siblingIndex, child)
|
yellowfive@57
|
457 else
|
yellowfive@57
|
458 tinsert(self.children, child)
|
yellowfive@57
|
459 end
|
yellowfive@57
|
460 child:SetParent(self)
|
yellowfive@57
|
461 child.frame:Show()
|
yellowfive@57
|
462 self:DoLayout()
|
yellowfive@57
|
463 end
|
yellowfive@57
|
464
|
yellowfive@57
|
465 WidgetContainerBase.AddChildren = function(self, ...)
|
yellowfive@57
|
466 for i = 1, select("#", ...) do
|
yellowfive@57
|
467 local child = select(i, ...)
|
yellowfive@57
|
468 tinsert(self.children, child)
|
yellowfive@57
|
469 child:SetParent(self)
|
yellowfive@57
|
470 child.frame:Show()
|
yellowfive@57
|
471 end
|
yellowfive@57
|
472 self:DoLayout()
|
yellowfive@57
|
473 end
|
yellowfive@57
|
474
|
yellowfive@57
|
475 WidgetContainerBase.ReleaseChildren = function(self)
|
yellowfive@57
|
476 local children = self.children
|
yellowfive@57
|
477 for i = 1,#children do
|
yellowfive@57
|
478 AceGUI:Release(children[i])
|
yellowfive@57
|
479 children[i] = nil
|
yellowfive@57
|
480 end
|
yellowfive@57
|
481 end
|
yellowfive@57
|
482
|
yellowfive@57
|
483 WidgetContainerBase.SetLayout = function(self, Layout)
|
yellowfive@57
|
484 self.LayoutFunc = AceGUI:GetLayout(Layout)
|
yellowfive@57
|
485 end
|
yellowfive@57
|
486
|
yellowfive@57
|
487 WidgetContainerBase.SetAutoAdjustHeight = function(self, adjust)
|
yellowfive@57
|
488 if adjust then
|
yellowfive@57
|
489 self.noAutoHeight = nil
|
yellowfive@57
|
490 else
|
yellowfive@57
|
491 self.noAutoHeight = true
|
yellowfive@57
|
492 end
|
yellowfive@57
|
493 end
|
yellowfive@57
|
494
|
yellowfive@57
|
495 local function FrameResize(this)
|
yellowfive@57
|
496 local self = this.obj
|
yellowfive@57
|
497 if this:GetWidth() and this:GetHeight() then
|
yellowfive@57
|
498 if self.OnWidthSet then
|
yellowfive@57
|
499 self:OnWidthSet(this:GetWidth())
|
yellowfive@57
|
500 end
|
yellowfive@57
|
501 if self.OnHeightSet then
|
yellowfive@57
|
502 self:OnHeightSet(this:GetHeight())
|
yellowfive@57
|
503 end
|
yellowfive@57
|
504 end
|
yellowfive@57
|
505 end
|
yellowfive@57
|
506
|
yellowfive@57
|
507 local function ContentResize(this)
|
yellowfive@57
|
508 if this:GetWidth() and this:GetHeight() then
|
yellowfive@57
|
509 this.width = this:GetWidth()
|
yellowfive@57
|
510 this.height = this:GetHeight()
|
yellowfive@57
|
511 this.obj:DoLayout()
|
yellowfive@57
|
512 end
|
yellowfive@57
|
513 end
|
yellowfive@57
|
514
|
yellowfive@57
|
515 setmetatable(WidgetContainerBase, {__index=WidgetBase})
|
yellowfive@57
|
516
|
yellowfive@57
|
517 --One of these function should be called on each Widget Instance as part of its creation process
|
yellowfive@57
|
518
|
yellowfive@57
|
519 --- Register a widget-class as a container for newly created widgets.
|
yellowfive@57
|
520 -- @param widget The widget class
|
yellowfive@57
|
521 function AceGUI:RegisterAsContainer(widget)
|
yellowfive@57
|
522 widget.children = {}
|
yellowfive@57
|
523 widget.userdata = {}
|
yellowfive@57
|
524 widget.events = {}
|
yellowfive@57
|
525 widget.base = WidgetContainerBase
|
yellowfive@57
|
526 widget.content.obj = widget
|
yellowfive@57
|
527 widget.frame.obj = widget
|
yellowfive@57
|
528 widget.content:SetScript("OnSizeChanged", ContentResize)
|
yellowfive@57
|
529 widget.frame:SetScript("OnSizeChanged", FrameResize)
|
yellowfive@57
|
530 setmetatable(widget, {__index = WidgetContainerBase})
|
yellowfive@57
|
531 widget:SetLayout("List")
|
yellowfive@57
|
532 return widget
|
yellowfive@57
|
533 end
|
yellowfive@57
|
534
|
yellowfive@57
|
535 --- Register a widget-class as a widget.
|
yellowfive@57
|
536 -- @param widget The widget class
|
yellowfive@57
|
537 function AceGUI:RegisterAsWidget(widget)
|
yellowfive@57
|
538 widget.userdata = {}
|
yellowfive@57
|
539 widget.events = {}
|
yellowfive@57
|
540 widget.base = WidgetBase
|
yellowfive@57
|
541 widget.frame.obj = widget
|
yellowfive@57
|
542 widget.frame:SetScript("OnSizeChanged", FrameResize)
|
yellowfive@57
|
543 setmetatable(widget, {__index = WidgetBase})
|
yellowfive@57
|
544 return widget
|
yellowfive@57
|
545 end
|
yellowfive@57
|
546 end
|
yellowfive@57
|
547
|
yellowfive@57
|
548
|
yellowfive@57
|
549
|
yellowfive@57
|
550
|
yellowfive@57
|
551 ------------------
|
yellowfive@57
|
552 -- Widget API --
|
yellowfive@57
|
553 ------------------
|
yellowfive@57
|
554
|
yellowfive@57
|
555 --- Registers a widget Constructor, this function returns a new instance of the Widget
|
yellowfive@57
|
556 -- @param Name The name of the widget
|
yellowfive@57
|
557 -- @param Constructor The widget constructor function
|
yellowfive@57
|
558 -- @param Version The version of the widget
|
yellowfive@57
|
559 function AceGUI:RegisterWidgetType(Name, Constructor, Version)
|
yellowfive@57
|
560 assert(type(Constructor) == "function")
|
yellowfive@57
|
561 assert(type(Version) == "number")
|
yellowfive@57
|
562
|
yellowfive@57
|
563 local oldVersion = WidgetVersions[Name]
|
yellowfive@57
|
564 if oldVersion and oldVersion >= Version then return end
|
yellowfive@57
|
565
|
yellowfive@57
|
566 WidgetVersions[Name] = Version
|
yellowfive@57
|
567 WidgetRegistry[Name] = Constructor
|
yellowfive@57
|
568 end
|
yellowfive@57
|
569
|
yellowfive@57
|
570 --- Registers a Layout Function
|
yellowfive@57
|
571 -- @param Name The name of the layout
|
yellowfive@57
|
572 -- @param LayoutFunc Reference to the layout function
|
yellowfive@57
|
573 function AceGUI:RegisterLayout(Name, LayoutFunc)
|
yellowfive@57
|
574 assert(type(LayoutFunc) == "function")
|
yellowfive@57
|
575 if type(Name) == "string" then
|
yellowfive@57
|
576 Name = Name:upper()
|
yellowfive@57
|
577 end
|
yellowfive@57
|
578 LayoutRegistry[Name] = LayoutFunc
|
yellowfive@57
|
579 end
|
yellowfive@57
|
580
|
yellowfive@57
|
581 --- Get a Layout Function from the registry
|
yellowfive@57
|
582 -- @param Name The name of the layout
|
yellowfive@57
|
583 function AceGUI:GetLayout(Name)
|
yellowfive@57
|
584 if type(Name) == "string" then
|
yellowfive@57
|
585 Name = Name:upper()
|
yellowfive@57
|
586 end
|
yellowfive@57
|
587 return LayoutRegistry[Name]
|
yellowfive@57
|
588 end
|
yellowfive@57
|
589
|
yellowfive@57
|
590 AceGUI.counts = AceGUI.counts or {}
|
yellowfive@57
|
591
|
yellowfive@57
|
592 --- A type-based counter to count the number of widgets created.
|
yellowfive@57
|
593 -- This is used by widgets that require a named frame, e.g. when a Blizzard
|
yellowfive@57
|
594 -- Template requires it.
|
yellowfive@57
|
595 -- @param type The widget type
|
yellowfive@57
|
596 function AceGUI:GetNextWidgetNum(type)
|
yellowfive@57
|
597 if not self.counts[type] then
|
yellowfive@57
|
598 self.counts[type] = 0
|
yellowfive@57
|
599 end
|
yellowfive@57
|
600 self.counts[type] = self.counts[type] + 1
|
yellowfive@57
|
601 return self.counts[type]
|
yellowfive@57
|
602 end
|
yellowfive@57
|
603
|
yellowfive@57
|
604 --- Return the number of created widgets for this type.
|
yellowfive@57
|
605 -- In contrast to GetNextWidgetNum, the number is not incremented.
|
yellowfive@57
|
606 -- @param type The widget type
|
yellowfive@57
|
607 function AceGUI:GetWidgetCount(type)
|
yellowfive@57
|
608 return self.counts[type] or 0
|
yellowfive@57
|
609 end
|
yellowfive@57
|
610
|
yellowfive@57
|
611 --- Return the version of the currently registered widget type.
|
yellowfive@57
|
612 -- @param type The widget type
|
yellowfive@57
|
613 function AceGUI:GetWidgetVersion(type)
|
yellowfive@57
|
614 return WidgetVersions[type]
|
yellowfive@57
|
615 end
|
yellowfive@57
|
616
|
yellowfive@57
|
617 -------------
|
yellowfive@57
|
618 -- Layouts --
|
yellowfive@57
|
619 -------------
|
yellowfive@57
|
620
|
yellowfive@57
|
621 --[[
|
yellowfive@57
|
622 A Layout is a func that takes 2 parameters
|
yellowfive@57
|
623 content - the frame that widgets will be placed inside
|
yellowfive@57
|
624 children - a table containing the widgets to layout
|
yellowfive@57
|
625 ]]
|
yellowfive@57
|
626
|
yellowfive@57
|
627 -- Very simple Layout, Children are stacked on top of each other down the left side
|
yellowfive@57
|
628 AceGUI:RegisterLayout("List",
|
yellowfive@57
|
629 function(content, children)
|
yellowfive@57
|
630 local height = 0
|
yellowfive@57
|
631 local width = content.width or content:GetWidth() or 0
|
yellowfive@57
|
632 for i = 1, #children do
|
yellowfive@57
|
633 local child = children[i]
|
yellowfive@57
|
634
|
yellowfive@57
|
635 local frame = child.frame
|
yellowfive@57
|
636 frame:ClearAllPoints()
|
yellowfive@57
|
637 frame:Show()
|
yellowfive@57
|
638 if i == 1 then
|
yellowfive@57
|
639 frame:SetPoint("TOPLEFT", content)
|
yellowfive@57
|
640 else
|
yellowfive@57
|
641 frame:SetPoint("TOPLEFT", children[i-1].frame, "BOTTOMLEFT")
|
yellowfive@57
|
642 end
|
yellowfive@57
|
643
|
yellowfive@57
|
644 if child.width == "fill" then
|
yellowfive@57
|
645 child:SetWidth(width)
|
yellowfive@57
|
646 frame:SetPoint("RIGHT", content)
|
yellowfive@57
|
647
|
yellowfive@57
|
648 if child.DoLayout then
|
yellowfive@57
|
649 child:DoLayout()
|
yellowfive@57
|
650 end
|
yellowfive@57
|
651 elseif child.width == "relative" then
|
yellowfive@57
|
652 child:SetWidth(width * child.relWidth)
|
yellowfive@57
|
653
|
yellowfive@57
|
654 if child.DoLayout then
|
yellowfive@57
|
655 child:DoLayout()
|
yellowfive@57
|
656 end
|
yellowfive@57
|
657 end
|
yellowfive@57
|
658
|
yellowfive@57
|
659 height = height + (frame.height or frame:GetHeight() or 0)
|
yellowfive@57
|
660 end
|
yellowfive@57
|
661 safecall(content.obj.LayoutFinished, content.obj, nil, height)
|
yellowfive@57
|
662 end)
|
yellowfive@57
|
663
|
yellowfive@57
|
664 -- A single control fills the whole content area
|
yellowfive@57
|
665 AceGUI:RegisterLayout("Fill",
|
yellowfive@57
|
666 function(content, children)
|
yellowfive@57
|
667 if children[1] then
|
yellowfive@57
|
668 children[1]:SetWidth(content:GetWidth() or 0)
|
yellowfive@57
|
669 children[1]:SetHeight(content:GetHeight() or 0)
|
yellowfive@57
|
670 children[1].frame:SetAllPoints(content)
|
yellowfive@57
|
671 children[1].frame:Show()
|
yellowfive@57
|
672 safecall(content.obj.LayoutFinished, content.obj, nil, children[1].frame:GetHeight())
|
yellowfive@57
|
673 end
|
yellowfive@57
|
674 end)
|
yellowfive@57
|
675
|
yellowfive@57
|
676 local layoutrecursionblock = nil
|
yellowfive@57
|
677 local function safelayoutcall(object, func, ...)
|
yellowfive@57
|
678 layoutrecursionblock = true
|
yellowfive@57
|
679 object[func](object, ...)
|
yellowfive@57
|
680 layoutrecursionblock = nil
|
yellowfive@57
|
681 end
|
yellowfive@57
|
682
|
yellowfive@57
|
683 AceGUI:RegisterLayout("Flow",
|
yellowfive@57
|
684 function(content, children)
|
yellowfive@57
|
685 if layoutrecursionblock then return end
|
yellowfive@57
|
686 --used height so far
|
yellowfive@57
|
687 local height = 0
|
yellowfive@57
|
688 --width used in the current row
|
yellowfive@57
|
689 local usedwidth = 0
|
yellowfive@57
|
690 --height of the current row
|
yellowfive@57
|
691 local rowheight = 0
|
yellowfive@57
|
692 local rowoffset = 0
|
yellowfive@57
|
693 local lastrowoffset
|
yellowfive@57
|
694
|
yellowfive@57
|
695 local width = content.width or content:GetWidth() or 0
|
yellowfive@57
|
696
|
yellowfive@57
|
697 --control at the start of the row
|
yellowfive@57
|
698 local rowstart
|
yellowfive@57
|
699 local rowstartoffset
|
yellowfive@57
|
700 local lastrowstart
|
yellowfive@57
|
701 local isfullheight
|
yellowfive@57
|
702
|
yellowfive@57
|
703 local frameoffset
|
yellowfive@57
|
704 local lastframeoffset
|
yellowfive@57
|
705 local oversize
|
yellowfive@57
|
706 for i = 1, #children do
|
yellowfive@57
|
707 local child = children[i]
|
yellowfive@57
|
708 oversize = nil
|
yellowfive@57
|
709 local frame = child.frame
|
yellowfive@57
|
710 local frameheight = frame.height or frame:GetHeight() or 0
|
yellowfive@57
|
711 local framewidth = frame.width or frame:GetWidth() or 0
|
yellowfive@57
|
712 lastframeoffset = frameoffset
|
yellowfive@57
|
713 -- HACK: Why did we set a frameoffset of (frameheight / 2) ?
|
yellowfive@57
|
714 -- That was moving all widgets half the widgets size down, is that intended?
|
yellowfive@57
|
715 -- Actually, it seems to be neccessary for many cases, we'll leave it in for now.
|
yellowfive@57
|
716 -- If widgets seem to anchor weirdly with this, provide a valid alignoffset for them.
|
yellowfive@57
|
717 -- TODO: Investigate moar!
|
yellowfive@57
|
718 frameoffset = child.alignoffset or (frameheight / 2)
|
yellowfive@57
|
719
|
yellowfive@57
|
720 if child.width == "relative" then
|
yellowfive@57
|
721 framewidth = width * child.relWidth
|
yellowfive@57
|
722 end
|
yellowfive@57
|
723
|
yellowfive@57
|
724 frame:Show()
|
yellowfive@57
|
725 frame:ClearAllPoints()
|
yellowfive@57
|
726 if i == 1 then
|
yellowfive@57
|
727 -- anchor the first control to the top left
|
yellowfive@57
|
728 frame:SetPoint("TOPLEFT", content)
|
yellowfive@57
|
729 rowheight = frameheight
|
yellowfive@57
|
730 rowoffset = frameoffset
|
yellowfive@57
|
731 rowstart = frame
|
yellowfive@57
|
732 rowstartoffset = frameoffset
|
yellowfive@57
|
733 usedwidth = framewidth
|
yellowfive@57
|
734 if usedwidth > width then
|
yellowfive@57
|
735 oversize = true
|
yellowfive@57
|
736 end
|
yellowfive@57
|
737 else
|
yellowfive@57
|
738 -- if there isn't available width for the control start a new row
|
yellowfive@57
|
739 -- if a control is "fill" it will be on a row of its own full width
|
yellowfive@57
|
740 if usedwidth == 0 or ((framewidth) + usedwidth > width) or child.width == "fill" then
|
yellowfive@57
|
741 if isfullheight then
|
yellowfive@57
|
742 -- a previous row has already filled the entire height, there's nothing we can usefully do anymore
|
yellowfive@57
|
743 -- (maybe error/warn about this?)
|
yellowfive@57
|
744 break
|
yellowfive@57
|
745 end
|
yellowfive@57
|
746 --anchor the previous row, we will now know its height and offset
|
yellowfive@57
|
747 rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(height + (rowoffset - rowstartoffset) + 3))
|
yellowfive@57
|
748 height = height + rowheight + 3
|
yellowfive@57
|
749 --save this as the rowstart so we can anchor it after the row is complete and we have the max height and offset of controls in it
|
yellowfive@57
|
750 rowstart = frame
|
yellowfive@57
|
751 rowstartoffset = frameoffset
|
yellowfive@57
|
752 rowheight = frameheight
|
yellowfive@57
|
753 rowoffset = frameoffset
|
yellowfive@57
|
754 usedwidth = framewidth
|
yellowfive@57
|
755 if usedwidth > width then
|
yellowfive@57
|
756 oversize = true
|
yellowfive@57
|
757 end
|
yellowfive@57
|
758 -- put the control on the current row, adding it to the width and checking if the height needs to be increased
|
yellowfive@57
|
759 else
|
yellowfive@57
|
760 --handles cases where the new height is higher than either control because of the offsets
|
yellowfive@57
|
761 --math.max(rowheight-rowoffset+frameoffset, frameheight-frameoffset+rowoffset)
|
yellowfive@57
|
762
|
yellowfive@57
|
763 --offset is always the larger of the two offsets
|
yellowfive@57
|
764 rowoffset = math_max(rowoffset, frameoffset)
|
yellowfive@57
|
765 rowheight = math_max(rowheight, rowoffset + (frameheight / 2))
|
yellowfive@57
|
766
|
yellowfive@57
|
767 frame:SetPoint("TOPLEFT", children[i-1].frame, "TOPRIGHT", 0, frameoffset - lastframeoffset)
|
yellowfive@57
|
768 usedwidth = framewidth + usedwidth
|
yellowfive@57
|
769 end
|
yellowfive@57
|
770 end
|
yellowfive@57
|
771
|
yellowfive@57
|
772 if child.width == "fill" then
|
yellowfive@57
|
773 safelayoutcall(child, "SetWidth", width)
|
yellowfive@57
|
774 frame:SetPoint("RIGHT", content)
|
yellowfive@57
|
775
|
yellowfive@57
|
776 usedwidth = 0
|
yellowfive@57
|
777 rowstart = frame
|
yellowfive@57
|
778 rowstartoffset = frameoffset
|
yellowfive@57
|
779
|
yellowfive@57
|
780 if child.DoLayout then
|
yellowfive@57
|
781 child:DoLayout()
|
yellowfive@57
|
782 end
|
yellowfive@57
|
783 rowheight = frame.height or frame:GetHeight() or 0
|
yellowfive@57
|
784 rowoffset = child.alignoffset or (rowheight / 2)
|
yellowfive@57
|
785 rowstartoffset = rowoffset
|
yellowfive@57
|
786 elseif child.width == "relative" then
|
yellowfive@57
|
787 safelayoutcall(child, "SetWidth", width * child.relWidth)
|
yellowfive@57
|
788
|
yellowfive@57
|
789 if child.DoLayout then
|
yellowfive@57
|
790 child:DoLayout()
|
yellowfive@57
|
791 end
|
yellowfive@57
|
792 elseif oversize then
|
yellowfive@57
|
793 if width > 1 then
|
yellowfive@57
|
794 frame:SetPoint("RIGHT", content)
|
yellowfive@57
|
795 end
|
yellowfive@57
|
796 end
|
yellowfive@57
|
797
|
yellowfive@57
|
798 if child.height == "fill" then
|
yellowfive@57
|
799 frame:SetPoint("BOTTOM", content)
|
yellowfive@57
|
800 isfullheight = true
|
yellowfive@57
|
801 end
|
yellowfive@57
|
802 end
|
yellowfive@57
|
803
|
yellowfive@57
|
804 --anchor the last row, if its full height needs a special case since its height has just been changed by the anchor
|
yellowfive@57
|
805 if isfullheight then
|
yellowfive@57
|
806 rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -height)
|
yellowfive@57
|
807 elseif rowstart then
|
yellowfive@57
|
808 rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(height + (rowoffset - rowstartoffset) + 3))
|
yellowfive@57
|
809 end
|
yellowfive@57
|
810
|
yellowfive@57
|
811 height = height + rowheight + 3
|
yellowfive@57
|
812 safecall(content.obj.LayoutFinished, content.obj, nil, height)
|
yellowfive@57
|
813 end)
|