annotate modules/FuBar_ReActionFu/lib/AceOO-2.0/AceOO-2.0.lua @ 28:21bcaf8215ff

- converted to Ace3 - rearranged file layout - configGUI menus not working right now
author Flick <flickerstreak@gmail.com>
date Mon, 17 Mar 2008 18:24:53 +0000
parents
children
rev   line source
flickerstreak@28 1 --[[
flickerstreak@28 2 Name: AceOO-2.0
flickerstreak@28 3 Revision: $Rev: 38641 $
flickerstreak@28 4 Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
flickerstreak@28 5 Inspired By: Ace 1.x by Turan (turan@gryphon.com)
flickerstreak@28 6 Website: http://www.wowace.com/
flickerstreak@28 7 Documentation: http://www.wowace.com/index.php/AceOO-2.0
flickerstreak@28 8 SVN: http://svn.wowace.com/root/trunk/Ace2/AceOO-2.0
flickerstreak@28 9 Description: Library to provide an object-orientation framework.
flickerstreak@28 10 Dependencies: AceLibrary
flickerstreak@28 11 License: MIT
flickerstreak@28 12 ]]
flickerstreak@28 13
flickerstreak@28 14 local MAJOR_VERSION = "AceOO-2.0"
flickerstreak@28 15 local MINOR_VERSION = "$Revision: 38641 $"
flickerstreak@28 16
flickerstreak@28 17 -- This ensures the code is only executed if the libary doesn't already exist, or is a newer version
flickerstreak@28 18 if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end
flickerstreak@28 19 if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
flickerstreak@28 20
flickerstreak@28 21 local AceOO = {
flickerstreak@28 22 error = AceLibrary.error,
flickerstreak@28 23 argCheck = AceLibrary.argCheck
flickerstreak@28 24 }
flickerstreak@28 25
flickerstreak@28 26 -- @function getuid
flickerstreak@28 27 -- @brief Obtain a unique string identifier for the object in question.
flickerstreak@28 28 -- @param t The object to obtain the uid for.
flickerstreak@28 29 -- @return The uid string.
flickerstreak@28 30 local function getuid(t)
flickerstreak@28 31 local mt = getmetatable(t)
flickerstreak@28 32 setmetatable(t, nil)
flickerstreak@28 33 local str = tostring(t)
flickerstreak@28 34 setmetatable(t, mt)
flickerstreak@28 35 local cap = str:match("[^:]*: 0x(.*)$") or str:match("[^:]*: (.*)$")
flickerstreak@28 36 if cap then
flickerstreak@28 37 return ("0"):rep(8 - #cap) .. cap
flickerstreak@28 38 end
flickerstreak@28 39 end
flickerstreak@28 40
flickerstreak@28 41 local function getlibrary(o)
flickerstreak@28 42 if type(o) == "table" then
flickerstreak@28 43 return o
flickerstreak@28 44 elseif type(o) == "string" then
flickerstreak@28 45 if not AceLibrary:HasInstance(o) then
flickerstreak@28 46 AceOO:error("Library %q does not exist.", o)
flickerstreak@28 47 end
flickerstreak@28 48 return AceLibrary(o)
flickerstreak@28 49 end
flickerstreak@28 50 end
flickerstreak@28 51
flickerstreak@28 52 local function deeprawget(self, k)
flickerstreak@28 53 while true do
flickerstreak@28 54 local v = rawget(self, k)
flickerstreak@28 55 if v ~= nil then
flickerstreak@28 56 return v
flickerstreak@28 57 end
flickerstreak@28 58 local mt = getmetatable(self)
flickerstreak@28 59 if not mt or type(mt.__index) ~= "table" then
flickerstreak@28 60 return nil
flickerstreak@28 61 end
flickerstreak@28 62 self = mt.__index
flickerstreak@28 63 end
flickerstreak@28 64 end
flickerstreak@28 65
flickerstreak@28 66 -- @function Factory
flickerstreak@28 67 -- @brief Construct a factory for the creation of objects.
flickerstreak@28 68 -- @param obj The object whose init method will be called on the new factory
flickerstreak@28 69 -- object.
flickerstreak@28 70 -- @param newobj The object whose init method will be called on the new
flickerstreak@28 71 -- objects that the Factory creates, to initialize them.
flickerstreak@28 72 -- @param (...) Arguments which will be passed to obj.init() in addition
flickerstreak@28 73 -- to the Factory object.
flickerstreak@28 74 -- @return The new factory which creates a newobj when its new method is called,
flickerstreak@28 75 -- or when it is called directly (__call metamethod).
flickerstreak@28 76 local Factory
flickerstreak@28 77 do
flickerstreak@28 78 local function getlibraries(...)
flickerstreak@28 79 if select('#', ...) == 0 then
flickerstreak@28 80 return
flickerstreak@28 81 end
flickerstreak@28 82 return getlibrary((select(1, ...))), getlibraries(select(2, ...))
flickerstreak@28 83 end
flickerstreak@28 84 local arg = {}
flickerstreak@28 85 local function new(obj, ...)
flickerstreak@28 86 local t = {}
flickerstreak@28 87 local uid = getuid(t)
flickerstreak@28 88 obj:init(t, getlibraries(...))
flickerstreak@28 89 t.uid = uid
flickerstreak@28 90 return t
flickerstreak@28 91 end
flickerstreak@28 92
flickerstreak@28 93 local function createnew(self, ...)
flickerstreak@28 94 local o = self.prototype
flickerstreak@28 95 local x = new(o, getlibraries(...))
flickerstreak@28 96 return x
flickerstreak@28 97 end
flickerstreak@28 98
flickerstreak@28 99 function Factory(obj, newobj, ...)
flickerstreak@28 100 local t = new(obj, ...)
flickerstreak@28 101 t.prototype = newobj
flickerstreak@28 102 t.new = createnew
flickerstreak@28 103 getmetatable(t).__call = t.new
flickerstreak@28 104 return t
flickerstreak@28 105 end
flickerstreak@28 106 end
flickerstreak@28 107
flickerstreak@28 108
flickerstreak@28 109 local function objtostring(self)
flickerstreak@28 110 if self.ToString then
flickerstreak@28 111 return self:ToString()
flickerstreak@28 112 elseif self.GetLibraryVersion then
flickerstreak@28 113 return (self:GetLibraryVersion())
flickerstreak@28 114 elseif self.super then
flickerstreak@28 115 local s = "Sub-" .. tostring(self.super)
flickerstreak@28 116 local first = true
flickerstreak@28 117 if self.interfaces then
flickerstreak@28 118 for interface in pairs(self.interfaces) do
flickerstreak@28 119 if first then
flickerstreak@28 120 s = s .. "(" .. tostring(interface)
flickerstreak@28 121 first = false
flickerstreak@28 122 else
flickerstreak@28 123 s = s .. ", " .. tostring(interface)
flickerstreak@28 124 end
flickerstreak@28 125 end
flickerstreak@28 126 end
flickerstreak@28 127 if self.mixins then
flickerstreak@28 128 for mixin in pairs(self.mixins) do
flickerstreak@28 129 if first then
flickerstreak@28 130 s = s .. tostring(mixin)
flickerstreak@28 131 first = false
flickerstreak@28 132 else
flickerstreak@28 133 s = s .. ", " .. tostring(mixin)
flickerstreak@28 134 end
flickerstreak@28 135 end
flickerstreak@28 136 end
flickerstreak@28 137 if first then
flickerstreak@28 138 if self.uid then
flickerstreak@28 139 return s .. ":" .. self.uid
flickerstreak@28 140 else
flickerstreak@28 141 return s
flickerstreak@28 142 end
flickerstreak@28 143 else
flickerstreak@28 144 return s .. ")"
flickerstreak@28 145 end
flickerstreak@28 146 else
flickerstreak@28 147 return self.uid and 'Subclass:' .. self.uid or 'Subclass'
flickerstreak@28 148 end
flickerstreak@28 149 end
flickerstreak@28 150
flickerstreak@28 151 -- @table Object
flickerstreak@28 152 -- @brief Base of all objects, including Class.
flickerstreak@28 153 --
flickerstreak@28 154 -- @method init
flickerstreak@28 155 -- @brief Initialize a new object.
flickerstreak@28 156 -- @param newobject The object to initialize
flickerstreak@28 157 -- @param class The class to make newobject inherit from
flickerstreak@28 158 local Object
flickerstreak@28 159 do
flickerstreak@28 160 Object = {}
flickerstreak@28 161 function Object:init(newobject, class)
flickerstreak@28 162 local parent = class or self
flickerstreak@28 163 if not rawget(newobject, 'uid') then
flickerstreak@28 164 newobject.uid = getuid(newobject)
flickerstreak@28 165 end
flickerstreak@28 166 local mt = {
flickerstreak@28 167 __index = parent,
flickerstreak@28 168 __tostring = objtostring,
flickerstreak@28 169 }
flickerstreak@28 170 setmetatable(newobject, mt)
flickerstreak@28 171 end
flickerstreak@28 172 Object.uid = getuid(Object)
flickerstreak@28 173 setmetatable(Object, { __tostring = function() return 'Object' end })
flickerstreak@28 174 end
flickerstreak@28 175
flickerstreak@28 176 local Interface
flickerstreak@28 177
flickerstreak@28 178 local function validateInterface(object, interface)
flickerstreak@28 179 if not object.class and object.prototype then
flickerstreak@28 180 object = object.prototype
flickerstreak@28 181 end
flickerstreak@28 182 for k,v in pairs(interface.interface) do
flickerstreak@28 183 if tostring(type(object[k])) ~= v then
flickerstreak@28 184 return false
flickerstreak@28 185 end
flickerstreak@28 186 end
flickerstreak@28 187 if interface.superinterfaces then
flickerstreak@28 188 for superinterface in pairs(interface.superinterfaces) do
flickerstreak@28 189 if not validateInterface(object, superinterface) then
flickerstreak@28 190 return false
flickerstreak@28 191 end
flickerstreak@28 192 end
flickerstreak@28 193 end
flickerstreak@28 194 if type(object.class) == "table" and rawequal(object.class.prototype, object) then
flickerstreak@28 195 if not object.class.interfaces then
flickerstreak@28 196 rawset(object.class, 'interfaces', {})
flickerstreak@28 197 end
flickerstreak@28 198 object.class.interfaces[interface] = true
flickerstreak@28 199 elseif type(object.class) == "table" and type(object.class.prototype) == "table" then
flickerstreak@28 200 validateInterface(object.class.prototype, interface)
flickerstreak@28 201 -- check if class is proper, thus preventing future checks.
flickerstreak@28 202 end
flickerstreak@28 203 return true
flickerstreak@28 204 end
flickerstreak@28 205
flickerstreak@28 206 -- @function inherits
flickerstreak@28 207 -- @brief Return whether an Object or Class inherits from a given
flickerstreak@28 208 -- parent.
flickerstreak@28 209 -- @param object Object or Class to check
flickerstreak@28 210 -- @param parent Parent to test inheritance from
flickerstreak@28 211 -- @return whether an Object or Class inherits from a given
flickerstreak@28 212 -- parent.
flickerstreak@28 213 local function inherits(object, parent)
flickerstreak@28 214 object = getlibrary(object)
flickerstreak@28 215 if type(parent) == "string" then
flickerstreak@28 216 if not AceLibrary:HasInstance(parent) then
flickerstreak@28 217 return false
flickerstreak@28 218 else
flickerstreak@28 219 parent = AceLibrary(parent)
flickerstreak@28 220 end
flickerstreak@28 221 end
flickerstreak@28 222 AceOO:argCheck(parent, 2, "table")
flickerstreak@28 223 if type(object) ~= "table" then
flickerstreak@28 224 return false
flickerstreak@28 225 end
flickerstreak@28 226 local current
flickerstreak@28 227 local class = deeprawget(object, 'class')
flickerstreak@28 228 if class then
flickerstreak@28 229 current = class
flickerstreak@28 230 else
flickerstreak@28 231 current = object
flickerstreak@28 232 end
flickerstreak@28 233 if type(current) ~= "table" then
flickerstreak@28 234 return false
flickerstreak@28 235 end
flickerstreak@28 236 if rawequal(current, parent) then
flickerstreak@28 237 return true
flickerstreak@28 238 end
flickerstreak@28 239 if parent.class then
flickerstreak@28 240 while true do
flickerstreak@28 241 if rawequal(current, Object) then
flickerstreak@28 242 break
flickerstreak@28 243 end
flickerstreak@28 244 if current.mixins then
flickerstreak@28 245 for mixin in pairs(current.mixins) do
flickerstreak@28 246 if rawequal(mixin, parent) then
flickerstreak@28 247 return true
flickerstreak@28 248 end
flickerstreak@28 249 end
flickerstreak@28 250 end
flickerstreak@28 251 if current.interfaces then
flickerstreak@28 252 for interface in pairs(current.interfaces) do
flickerstreak@28 253 if rawequal(interface, parent) then
flickerstreak@28 254 return true
flickerstreak@28 255 end
flickerstreak@28 256 end
flickerstreak@28 257 end
flickerstreak@28 258 current = deeprawget(current, 'super')
flickerstreak@28 259 if type(current) ~= "table" then
flickerstreak@28 260 break
flickerstreak@28 261 end
flickerstreak@28 262 end
flickerstreak@28 263
flickerstreak@28 264 local isInterface = false
flickerstreak@28 265 local curr = parent.class
flickerstreak@28 266 while true do
flickerstreak@28 267 if rawequal(curr, Object) then
flickerstreak@28 268 break
flickerstreak@28 269 elseif rawequal(curr, Interface) then
flickerstreak@28 270 isInterface = true
flickerstreak@28 271 break
flickerstreak@28 272 end
flickerstreak@28 273 curr = deeprawget(curr, 'super')
flickerstreak@28 274 if type(curr) ~= "table" then
flickerstreak@28 275 break
flickerstreak@28 276 end
flickerstreak@28 277 end
flickerstreak@28 278 return isInterface and validateInterface(object, parent)
flickerstreak@28 279 else
flickerstreak@28 280 while true do
flickerstreak@28 281 if rawequal(current, parent) then
flickerstreak@28 282 return true
flickerstreak@28 283 elseif rawequal(current, Object) then
flickerstreak@28 284 return false
flickerstreak@28 285 end
flickerstreak@28 286 current = deeprawget(current, 'super')
flickerstreak@28 287 if type(current) ~= "table" then
flickerstreak@28 288 return false
flickerstreak@28 289 end
flickerstreak@28 290 end
flickerstreak@28 291 end
flickerstreak@28 292 end
flickerstreak@28 293
flickerstreak@28 294 -- @table Class
flickerstreak@28 295 -- @brief An object factory which sets up inheritence and supports
flickerstreak@28 296 -- 'mixins'.
flickerstreak@28 297 --
flickerstreak@28 298 -- @metamethod Class call
flickerstreak@28 299 -- @brief Call ClassFactory:new() to create a new class.
flickerstreak@28 300 --
flickerstreak@28 301 -- @method Class new
flickerstreak@28 302 -- @brief Construct a new object.
flickerstreak@28 303 -- @param (...) Arguments to pass to the object init function.
flickerstreak@28 304 -- @return The new object.
flickerstreak@28 305 --
flickerstreak@28 306 -- @method Class init
flickerstreak@28 307 -- @brief Initialize a new class.
flickerstreak@28 308 -- @param parent Superclass.
flickerstreak@28 309 -- @param (...) Mixins.
flickerstreak@28 310 --
flickerstreak@28 311 -- @method Class ToString
flickerstreak@28 312 -- @return A string representing the object, in this case 'Class'.
flickerstreak@28 313 local initStatus
flickerstreak@28 314 local Class
flickerstreak@28 315 local Mixin
flickerstreak@28 316 local autoEmbed = false
flickerstreak@28 317 local function traverseInterfaces(bit, total)
flickerstreak@28 318 if bit.superinterfaces then
flickerstreak@28 319 for interface in pairs(bit.superinterfaces) do
flickerstreak@28 320 if not total[interface] then
flickerstreak@28 321 total[interface] = true
flickerstreak@28 322 traverseInterfaces(interface, total)
flickerstreak@28 323 end
flickerstreak@28 324 end
flickerstreak@28 325 end
flickerstreak@28 326 end
flickerstreak@28 327 local class_new
flickerstreak@28 328 do
flickerstreak@28 329 Class = Factory(Object, setmetatable({}, {__index = Object}), Object)
flickerstreak@28 330 Class.super = Object
flickerstreak@28 331
flickerstreak@28 332 local function protostring(t)
flickerstreak@28 333 return '<' .. tostring(t.class) .. ' prototype>'
flickerstreak@28 334 end
flickerstreak@28 335 local function classobjectstring(t)
flickerstreak@28 336 if t.ToString then
flickerstreak@28 337 return t:ToString()
flickerstreak@28 338 elseif t.GetLibraryVersion then
flickerstreak@28 339 return (t:GetLibraryVersion())
flickerstreak@28 340 else
flickerstreak@28 341 return '<' .. tostring(t.class) .. ' instance>'
flickerstreak@28 342 end
flickerstreak@28 343 end
flickerstreak@28 344 local function classobjectequal(self, other)
flickerstreak@28 345 if type(self) == "table" and self.Equals then
flickerstreak@28 346 return self:Equals(other)
flickerstreak@28 347 elseif type(other) == "table" and other.Equals then
flickerstreak@28 348 return other:Equals(self)
flickerstreak@28 349 elseif type(self) == "table" and self.CompareTo then
flickerstreak@28 350 return self:CompareTo(other) == 0
flickerstreak@28 351 elseif type(other) == "table" and other.CompareTo then
flickerstreak@28 352 return other:CompareTo(self) == 0
flickerstreak@28 353 else
flickerstreak@28 354 return rawequal(self, other)
flickerstreak@28 355 end
flickerstreak@28 356 end
flickerstreak@28 357 local function classobjectlessthan(self, other)
flickerstreak@28 358 if type(self) == "table" and self.IsLessThan then
flickerstreak@28 359 return self:IsLessThan(other)
flickerstreak@28 360 elseif type(other) == "table" and other.IsLessThanOrEqualTo then
flickerstreak@28 361 return not other:IsLessThanOrEqualTo(self)
flickerstreak@28 362 elseif type(self) == "table" and self.CompareTo then
flickerstreak@28 363 return self:CompareTo(other) < 0
flickerstreak@28 364 elseif type(other) == "table" and other.CompareTo then
flickerstreak@28 365 return other:CompareTo(self) > 0
flickerstreak@28 366 elseif type(other) == "table" and other.IsLessThan and other.Equals then
flickerstreak@28 367 return other:Equals(self) or other:IsLessThan(self)
flickerstreak@28 368 else
flickerstreak@28 369 AceOO:error("cannot compare two objects")
flickerstreak@28 370 end
flickerstreak@28 371 end
flickerstreak@28 372 local function classobjectlessthanequal(self, other)
flickerstreak@28 373 if type(self) == "table" and self.IsLessThanOrEqualTo then
flickerstreak@28 374 return self:IsLessThanOrEqualTo(other)
flickerstreak@28 375 elseif type(other) == "table" and other.IsLessThan then
flickerstreak@28 376 return not other:IsLessThan(self)
flickerstreak@28 377 elseif type(self) == "table" and self.CompareTo then
flickerstreak@28 378 return self:CompareTo(other) <= 0
flickerstreak@28 379 elseif type(other) == "table" and other.CompareTo then
flickerstreak@28 380 return other:CompareTo(self) >= 0
flickerstreak@28 381 elseif type(self) == "table" and self.IsLessThan and self.Equals then
flickerstreak@28 382 return self:Equals(other) or self:IsLessThan(other)
flickerstreak@28 383 else
flickerstreak@28 384 AceOO:error("cannot compare two incompatible objects")
flickerstreak@28 385 end
flickerstreak@28 386 end
flickerstreak@28 387 local function classobjectadd(self, other)
flickerstreak@28 388 if type(self) == "table" and self.Add then
flickerstreak@28 389 return self:Add(other)
flickerstreak@28 390 else
flickerstreak@28 391 AceOO:error("cannot add two incompatible objects")
flickerstreak@28 392 end
flickerstreak@28 393 end
flickerstreak@28 394 local function classobjectsub(self, other)
flickerstreak@28 395 if type(self) == "table" and self.Subtract then
flickerstreak@28 396 return self:Subtract(other)
flickerstreak@28 397 else
flickerstreak@28 398 AceOO:error("cannot subtract two incompatible objects")
flickerstreak@28 399 end
flickerstreak@28 400 end
flickerstreak@28 401 local function classobjectunm(self, other)
flickerstreak@28 402 if type(self) == "table" and self.UnaryNegation then
flickerstreak@28 403 return self:UnaryNegation(other)
flickerstreak@28 404 else
flickerstreak@28 405 AceOO:error("attempt to negate an incompatible object")
flickerstreak@28 406 end
flickerstreak@28 407 end
flickerstreak@28 408 local function classobjectmul(self, other)
flickerstreak@28 409 if type(self) == "table" and self.Multiply then
flickerstreak@28 410 return self:Multiply(other)
flickerstreak@28 411 else
flickerstreak@28 412 AceOO:error("cannot multiply two incompatible objects")
flickerstreak@28 413 end
flickerstreak@28 414 end
flickerstreak@28 415 local function classobjectdiv(self, other)
flickerstreak@28 416 if type(self) == "table" and self.Divide then
flickerstreak@28 417 return self:Divide(other)
flickerstreak@28 418 else
flickerstreak@28 419 AceOO:error("cannot divide two incompatible objects")
flickerstreak@28 420 end
flickerstreak@28 421 end
flickerstreak@28 422 local function classobjectpow(self, other)
flickerstreak@28 423 if type(self) == "table" and self.Exponent then
flickerstreak@28 424 return self:Exponent(other)
flickerstreak@28 425 else
flickerstreak@28 426 AceOO:error("cannot exponentiate two incompatible objects")
flickerstreak@28 427 end
flickerstreak@28 428 end
flickerstreak@28 429 local function classobjectconcat(self, other)
flickerstreak@28 430 if type(self) == "table" and self.Concatenate then
flickerstreak@28 431 return self:Concatenate(other)
flickerstreak@28 432 else
flickerstreak@28 433 AceOO:error("cannot concatenate two incompatible objects")
flickerstreak@28 434 end
flickerstreak@28 435 end
flickerstreak@28 436 function class_new(self, ...)
flickerstreak@28 437 if self.virtual then
flickerstreak@28 438 AceOO:error("Cannot instantiate a virtual class.")
flickerstreak@28 439 end
flickerstreak@28 440
flickerstreak@28 441 local o = self.prototype
flickerstreak@28 442 local newobj = {}
flickerstreak@28 443 if o.class and o.class.instancemeta then
flickerstreak@28 444 setmetatable(newobj, o.class.instancemeta)
flickerstreak@28 445 else
flickerstreak@28 446 Object:init(newobj, o)
flickerstreak@28 447 end
flickerstreak@28 448
flickerstreak@28 449 if self.interfaces and not self.interfacesVerified then
flickerstreak@28 450 -- Verify the interfaces
flickerstreak@28 451
flickerstreak@28 452 for interface in pairs(self.interfaces) do
flickerstreak@28 453 for field,kind in pairs(interface.interface) do
flickerstreak@28 454 if tostring(type(newobj[field])) ~= kind then
flickerstreak@28 455 AceOO:error("Class did not satisfy all interfaces. %q is required to be a %s. It is a %s", field, kind, tostring(type(newobj[field])))
flickerstreak@28 456 end
flickerstreak@28 457 end
flickerstreak@28 458 end
flickerstreak@28 459 self.interfacesVerified = true
flickerstreak@28 460 end
flickerstreak@28 461 local tmp = initStatus
flickerstreak@28 462 initStatus = newobj
flickerstreak@28 463 newobj:init(...)
flickerstreak@28 464 if initStatus then
flickerstreak@28 465 initStatus = tmp
flickerstreak@28 466 AceOO:error("Initialization not completed, be sure to call the superclass's init method.")
flickerstreak@28 467 return
flickerstreak@28 468 end
flickerstreak@28 469 initStatus = tmp
flickerstreak@28 470 return newobj
flickerstreak@28 471 end
flickerstreak@28 472 local classmeta = {
flickerstreak@28 473 __tostring = objtostring,
flickerstreak@28 474 __call = function(self, ...)
flickerstreak@28 475 return self:new(...)
flickerstreak@28 476 end,
flickerstreak@28 477 }
flickerstreak@28 478 function Class:init(newclass, parent, ...)
flickerstreak@28 479 parent = parent or self
flickerstreak@28 480
flickerstreak@28 481 local total
flickerstreak@28 482
flickerstreak@28 483 if parent.class then
flickerstreak@28 484 total = { parent, ... }
flickerstreak@28 485 parent = self
flickerstreak@28 486 else
flickerstreak@28 487 total = { ... }
flickerstreak@28 488 end
flickerstreak@28 489 if not inherits(parent, Class) then
flickerstreak@28 490 AceOO:error("Classes must inherit from a proper class")
flickerstreak@28 491 end
flickerstreak@28 492 if parent.sealed then
flickerstreak@28 493 AceOO:error("Cannot inherit from a sealed class")
flickerstreak@28 494 end
flickerstreak@28 495 for i,v in ipairs(total) do
flickerstreak@28 496 if inherits(v, Mixin) and v.class then
flickerstreak@28 497 if v.__deprecated then
flickerstreak@28 498 AceOO:error(v.__deprecated)
flickerstreak@28 499 end
flickerstreak@28 500 if not newclass.mixins then
flickerstreak@28 501 newclass.mixins = {}
flickerstreak@28 502 end
flickerstreak@28 503 if newclass.mixins[v] then
flickerstreak@28 504 AceOO:error("Cannot explicitly inherit from the same mixin twice")
flickerstreak@28 505 end
flickerstreak@28 506 newclass.mixins[v] = true
flickerstreak@28 507 elseif inherits(v, Interface) and v.class then
flickerstreak@28 508 if not newclass.interfaces then
flickerstreak@28 509 newclass.interfaces = {}
flickerstreak@28 510 end
flickerstreak@28 511 if newclass.interfaces[v] then
flickerstreak@28 512 AceOO:error("Cannot explicitly inherit from the same interface twice")
flickerstreak@28 513 end
flickerstreak@28 514 newclass.interfaces[v] = true
flickerstreak@28 515 else
flickerstreak@28 516 AceOO:error("Classes can only inherit from one or zero classes and any number of mixins or interfaces")
flickerstreak@28 517 end
flickerstreak@28 518 end
flickerstreak@28 519 if parent.interfaces then
flickerstreak@28 520 if not newclass.interfaces then
flickerstreak@28 521 newclass.interfaces = {}
flickerstreak@28 522 end
flickerstreak@28 523 for interface in pairs(parent.interfaces) do
flickerstreak@28 524 newclass.interfaces[interface] = true
flickerstreak@28 525 end
flickerstreak@28 526 end
flickerstreak@28 527 for k in pairs(total) do
flickerstreak@28 528 total[k] = nil
flickerstreak@28 529 end
flickerstreak@28 530
flickerstreak@28 531 newclass.super = parent
flickerstreak@28 532
flickerstreak@28 533 newclass.prototype = setmetatable(total, {
flickerstreak@28 534 __index = parent.prototype,
flickerstreak@28 535 __tostring = protostring,
flickerstreak@28 536 })
flickerstreak@28 537 total = nil
flickerstreak@28 538
flickerstreak@28 539 newclass.instancemeta = {
flickerstreak@28 540 __index = newclass.prototype,
flickerstreak@28 541 __tostring = classobjectstring,
flickerstreak@28 542 __eq = classobjectequal,
flickerstreak@28 543 __lt = classobjectlessthan,
flickerstreak@28 544 __le = classobjectlessthanequal,
flickerstreak@28 545 __add = classobjectadd,
flickerstreak@28 546 __sub = classobjectsub,
flickerstreak@28 547 __unm = classobjectunm,
flickerstreak@28 548 __mul = classobjectmul,
flickerstreak@28 549 __div = classobjectdiv,
flickerstreak@28 550 __pow = classobjectpow,
flickerstreak@28 551 __concat = classobjectconcat,
flickerstreak@28 552 }
flickerstreak@28 553
flickerstreak@28 554 setmetatable(newclass, classmeta)
flickerstreak@28 555
flickerstreak@28 556 newclass.new = class_new
flickerstreak@28 557
flickerstreak@28 558 if newclass.mixins then
flickerstreak@28 559 -- Fold in the mixins
flickerstreak@28 560 local err, msg
flickerstreak@28 561 for mixin in pairs(newclass.mixins) do
flickerstreak@28 562 local ret
flickerstreak@28 563 autoEmbed = true
flickerstreak@28 564 ret, msg = pcall(mixin.embed, mixin, newclass.prototype)
flickerstreak@28 565 autoEmbed = false
flickerstreak@28 566 if not ret then
flickerstreak@28 567 err = true
flickerstreak@28 568 break
flickerstreak@28 569 end
flickerstreak@28 570 end
flickerstreak@28 571
flickerstreak@28 572 if err then
flickerstreak@28 573 local pt = newclass.prototype
flickerstreak@28 574 for k,v in pairs(pt) do
flickerstreak@28 575 pt[k] = nil
flickerstreak@28 576 end
flickerstreak@28 577
flickerstreak@28 578 -- method conflict
flickerstreak@28 579 AceOO:error(msg)
flickerstreak@28 580 end
flickerstreak@28 581 end
flickerstreak@28 582
flickerstreak@28 583 newclass.prototype.class = newclass
flickerstreak@28 584
flickerstreak@28 585 if newclass.interfaces then
flickerstreak@28 586 for interface in pairs(newclass.interfaces) do
flickerstreak@28 587 traverseInterfaces(interface, newclass.interfaces)
flickerstreak@28 588 end
flickerstreak@28 589 end
flickerstreak@28 590 if newclass.mixins then
flickerstreak@28 591 for mixin in pairs(newclass.mixins) do
flickerstreak@28 592 if mixin.interfaces then
flickerstreak@28 593 if not newclass.interfaces then
flickerstreak@28 594 newclass.interfaces = {}
flickerstreak@28 595 end
flickerstreak@28 596 for interface in pairs(mixin.interfaces) do
flickerstreak@28 597 newclass.interfaces[interface] = true
flickerstreak@28 598 end
flickerstreak@28 599 end
flickerstreak@28 600 end
flickerstreak@28 601 end
flickerstreak@28 602 end
flickerstreak@28 603 function Class:ToString()
flickerstreak@28 604 if type(self.GetLibraryVersion) == "function" then
flickerstreak@28 605 return (self:GetLibraryVersion())
flickerstreak@28 606 else
flickerstreak@28 607 return "Class"
flickerstreak@28 608 end
flickerstreak@28 609 end
flickerstreak@28 610
flickerstreak@28 611 local tmp
flickerstreak@28 612 function Class.prototype:init()
flickerstreak@28 613 if rawequal(self, initStatus) then
flickerstreak@28 614 initStatus = nil
flickerstreak@28 615 else
flickerstreak@28 616 AceOO:error("Improper self passed to init. You must do MyClass.super.prototype.init(self, ...)", 2)
flickerstreak@28 617 end
flickerstreak@28 618 self.uid = getuid(self)
flickerstreak@28 619 local current = self.class
flickerstreak@28 620 while true do
flickerstreak@28 621 if current == Class then
flickerstreak@28 622 break
flickerstreak@28 623 end
flickerstreak@28 624 if current.mixins then
flickerstreak@28 625 for mixin in pairs(current.mixins) do
flickerstreak@28 626 if type(mixin.OnInstanceInit) == "function" then
flickerstreak@28 627 mixin:OnInstanceInit(self)
flickerstreak@28 628 end
flickerstreak@28 629 end
flickerstreak@28 630 end
flickerstreak@28 631 current = current.super
flickerstreak@28 632 end
flickerstreak@28 633 end
flickerstreak@28 634 end
flickerstreak@28 635
flickerstreak@28 636
flickerstreak@28 637 -- @object ClassFactory
flickerstreak@28 638 -- @brief A factory for creating classes. Rarely used directly.
flickerstreak@28 639 local ClassFactory = Factory(Object, Class, Object)
flickerstreak@28 640
flickerstreak@28 641 function Class:new(...)
flickerstreak@28 642 local x = ClassFactory:new(...)
flickerstreak@28 643 if AceOO.classes then
flickerstreak@28 644 AceOO.classes[x] = true
flickerstreak@28 645 end
flickerstreak@28 646 return x
flickerstreak@28 647 end
flickerstreak@28 648 getmetatable(Class).__call = Class.new
flickerstreak@28 649
flickerstreak@28 650 -- @class Mixin
flickerstreak@28 651 -- @brief A class to create mixin objects, which contain methods that get
flickerstreak@28 652 -- "mixed in" to class prototypes.
flickerstreak@28 653 --
flickerstreak@28 654 -- @object Mixin prototype
flickerstreak@28 655 -- @brief The prototype that mixin objects inherit their methods from.
flickerstreak@28 656 --
flickerstreak@28 657 -- @method Mixin prototype embed
flickerstreak@28 658 -- @brief Mix in the methods of our object which are listed in our interface
flickerstreak@28 659 -- to the supplied target table.
flickerstreak@28 660 --
flickerstreak@28 661 -- @method Mixin prototype init
flickerstreak@28 662 -- @brief Initialize the mixin object.
flickerstreak@28 663 -- @param newobj The new object we're initializing.
flickerstreak@28 664 -- @param interface The interface we implement (the list of methods our
flickerstreak@28 665 -- prototype provides which should be mixed into the target
flickerstreak@28 666 -- table by embed).
flickerstreak@28 667 do
flickerstreak@28 668 Mixin = Class()
flickerstreak@28 669 function Mixin:ToString()
flickerstreak@28 670 if self.GetLibraryVersion then
flickerstreak@28 671 return (self:GetLibraryVersion())
flickerstreak@28 672 else
flickerstreak@28 673 return 'Mixin'
flickerstreak@28 674 end
flickerstreak@28 675 end
flickerstreak@28 676 local function _Embed(state, field, target)
flickerstreak@28 677 field = next(state.export, field)
flickerstreak@28 678 if field == nil then
flickerstreak@28 679 return
flickerstreak@28 680 end
flickerstreak@28 681
flickerstreak@28 682 if rawget(target, field) or (target[field] and target[field] ~= state[field]) then
flickerstreak@28 683 AceOO:error("Method conflict in attempt to mixin. Field %q", field)
flickerstreak@28 684 end
flickerstreak@28 685
flickerstreak@28 686 target[field] = state[field]
flickerstreak@28 687
flickerstreak@28 688 local ret,msg = pcall(_Embed, state, field, target)
flickerstreak@28 689 if not ret then
flickerstreak@28 690 -- Mix in the next method according to the defined interface. If that
flickerstreak@28 691 -- fails due to a conflict, re-raise to back out the previous mixed
flickerstreak@28 692 -- methods.
flickerstreak@28 693
flickerstreak@28 694 target[field] = nil
flickerstreak@28 695 AceOO:error(msg)
flickerstreak@28 696 end
flickerstreak@28 697 end
flickerstreak@28 698 function Mixin.prototype:embed(target)
flickerstreak@28 699 if self.__deprecated then
flickerstreak@28 700 AceOO:error(self.__deprecated)
flickerstreak@28 701 end
flickerstreak@28 702 local mt = getmetatable(target)
flickerstreak@28 703 setmetatable(target, nil)
flickerstreak@28 704 local err, msg = pcall(_Embed, self, nil, target)
flickerstreak@28 705 if not err then
flickerstreak@28 706 setmetatable(target, mt)
flickerstreak@28 707 AceOO:error(msg)
flickerstreak@28 708 return
flickerstreak@28 709 end
flickerstreak@28 710 if type(self.embedList) == "table" then
flickerstreak@28 711 self.embedList[target] = true
flickerstreak@28 712 end
flickerstreak@28 713 if type(target.class) ~= "table" then
flickerstreak@28 714 target[self] = true
flickerstreak@28 715 end
flickerstreak@28 716 if not autoEmbed and type(self.OnManualEmbed) == "function" then
flickerstreak@28 717 self:OnManualEmbed(target)
flickerstreak@28 718 end
flickerstreak@28 719 setmetatable(target, mt)
flickerstreak@28 720 end
flickerstreak@28 721
flickerstreak@28 722 function Mixin.prototype:activate(oldLib, oldDeactivate)
flickerstreak@28 723 if oldLib and oldLib.embedList then
flickerstreak@28 724 for target in pairs(oldLib.embedList) do
flickerstreak@28 725 local mt = getmetatable(target)
flickerstreak@28 726 setmetatable(target, nil)
flickerstreak@28 727 for field in pairs(oldLib.export) do
flickerstreak@28 728 target[field] = nil
flickerstreak@28 729 end
flickerstreak@28 730 setmetatable(target, mt)
flickerstreak@28 731 end
flickerstreak@28 732 self.embedList = oldLib.embedList
flickerstreak@28 733 for target in pairs(self.embedList) do
flickerstreak@28 734 self:embed(target)
flickerstreak@28 735 end
flickerstreak@28 736 else
flickerstreak@28 737 self.embedList = setmetatable({}, {__mode="k"})
flickerstreak@28 738 end
flickerstreak@28 739 end
flickerstreak@28 740
flickerstreak@28 741 function Mixin.prototype:init(export, ...)
flickerstreak@28 742 AceOO:argCheck(export, 2, "table")
flickerstreak@28 743 for k,v in pairs(export) do
flickerstreak@28 744 if type(k) ~= "number" then
flickerstreak@28 745 AceOO:error("All keys to argument #2 must be numbers.")
flickerstreak@28 746 elseif type(v) ~= "string" then
flickerstreak@28 747 AceOO:error("All values to argument #2 must be strings.")
flickerstreak@28 748 end
flickerstreak@28 749 end
flickerstreak@28 750 local num = #export
flickerstreak@28 751 for i = 1, num do
flickerstreak@28 752 local v = export[i]
flickerstreak@28 753 export[i] = nil
flickerstreak@28 754 export[v] = true
flickerstreak@28 755 end
flickerstreak@28 756
flickerstreak@28 757 local interfaces
flickerstreak@28 758 if select('#', ...) >= 1 then
flickerstreak@28 759 interfaces = { ... }
flickerstreak@28 760 for i,v in ipairs(interfaces) do
flickerstreak@28 761 v = getlibrary(v)
flickerstreak@28 762 interfaces[i] = v
flickerstreak@28 763 if not v.class or not inherits(v, Interface) then
flickerstreak@28 764 AceOO:error("Mixins can inherit only from interfaces")
flickerstreak@28 765 end
flickerstreak@28 766 end
flickerstreak@28 767 local num = #interfaces
flickerstreak@28 768 for i = 1, num do
flickerstreak@28 769 local v = interfaces[i]
flickerstreak@28 770 interfaces[i] = nil
flickerstreak@28 771 interfaces[v] = true
flickerstreak@28 772 end
flickerstreak@28 773 for interface in pairs(interfaces) do
flickerstreak@28 774 traverseInterfaces(interface, interfaces)
flickerstreak@28 775 end
flickerstreak@28 776 for interface in pairs(interfaces) do
flickerstreak@28 777 for field,kind in pairs(interface.interface) do
flickerstreak@28 778 if kind ~= "nil" then
flickerstreak@28 779 local good = false
flickerstreak@28 780 for bit in pairs(export) do
flickerstreak@28 781 if bit == field then
flickerstreak@28 782 good = true
flickerstreak@28 783 break
flickerstreak@28 784 end
flickerstreak@28 785 end
flickerstreak@28 786 if not good then
flickerstreak@28 787 AceOO:error("Mixin does not fully accommodate field %q", field)
flickerstreak@28 788 end
flickerstreak@28 789 end
flickerstreak@28 790 end
flickerstreak@28 791 end
flickerstreak@28 792 end
flickerstreak@28 793 self.super = Mixin.prototype
flickerstreak@28 794 Mixin.super.prototype.init(self)
flickerstreak@28 795 self.export = export
flickerstreak@28 796 self.interfaces = interfaces
flickerstreak@28 797 end
flickerstreak@28 798 end
flickerstreak@28 799
flickerstreak@28 800 -- @class Interface
flickerstreak@28 801 -- @brief A class to create interfaces, which contain contracts that classes
flickerstreak@28 802 -- which inherit from this must comply with.
flickerstreak@28 803 --
flickerstreak@28 804 -- @object Interface prototype
flickerstreak@28 805 -- @brief The prototype that interface objects must adhere to.
flickerstreak@28 806 --
flickerstreak@28 807 -- @method Interface prototype init
flickerstreak@28 808 -- @brief Initialize the mixin object.
flickerstreak@28 809 -- @param interface The interface we contract (the hash of fields forced).
flickerstreak@28 810 -- @param (...) Superinterfaces
flickerstreak@28 811 do
flickerstreak@28 812 Interface = Class()
flickerstreak@28 813 function Interface:ToString()
flickerstreak@28 814 if self.GetLibraryVersion then
flickerstreak@28 815 return (self:GetLibraryVersion())
flickerstreak@28 816 else
flickerstreak@28 817 return 'Instance'
flickerstreak@28 818 end
flickerstreak@28 819 end
flickerstreak@28 820 function Interface.prototype:init(interface, ...)
flickerstreak@28 821 Interface.super.prototype.init(self)
flickerstreak@28 822 AceOO:argCheck(interface, 2, "table")
flickerstreak@28 823 for k,v in pairs(interface) do
flickerstreak@28 824 if type(k) ~= "string" then
flickerstreak@28 825 AceOO:error("All keys to argument #2 must be numbers.")
flickerstreak@28 826 elseif type(v) ~= "string" then
flickerstreak@28 827 AceOO:error("All values to argument #2 must be strings.")
flickerstreak@28 828 elseif v ~= "nil" and v ~= "string" and v ~= "number" and v ~= "table" and v ~= "function" then
flickerstreak@28 829 AceOO:error('All values to argument #2 must either be "nil", "string", "number", "table", or "function".')
flickerstreak@28 830 end
flickerstreak@28 831 end
flickerstreak@28 832 if select('#', ...) >= 1 then
flickerstreak@28 833 self.superinterfaces = { ... }
flickerstreak@28 834 for i,v in ipairs(self.superinterfaces) do
flickerstreak@28 835 v = getlibrary(v)
flickerstreak@28 836 self.superinterfaces[i] = v
flickerstreak@28 837 if not inherits(v, Interface) or not v.class then
flickerstreak@28 838 AceOO:error('Cannot provide a non-Interface to inherit from')
flickerstreak@28 839 end
flickerstreak@28 840 end
flickerstreak@28 841 local num = #self.superinterfaces
flickerstreak@28 842 for i = 1, num do
flickerstreak@28 843 local v = self.superinterfaces[i]
flickerstreak@28 844 self.superinterfaces[i] = nil
flickerstreak@28 845 self.superinterfaces[v] = true
flickerstreak@28 846 end
flickerstreak@28 847 end
flickerstreak@28 848 self.interface = interface
flickerstreak@28 849 end
flickerstreak@28 850 end
flickerstreak@28 851
flickerstreak@28 852 -- @function Classpool
flickerstreak@28 853 -- @brief Obtain a read only class from our pool of classes, indexed by the
flickerstreak@28 854 -- superclass and mixins.
flickerstreak@28 855 -- @param sc The superclass of the class we want.
flickerstreak@28 856 -- @param (m1..m20) Mixins of the class we want's objects.
flickerstreak@28 857 -- @return A read only class from the class pool.
flickerstreak@28 858 local Classpool
flickerstreak@28 859 do
flickerstreak@28 860 local pool = setmetatable({}, {__mode = 'v'})
flickerstreak@28 861 local function newindex(k, v)
flickerstreak@28 862 AceOO:error('Attempt to modify a read-only class.')
flickerstreak@28 863 end
flickerstreak@28 864 local function protonewindex(k, v)
flickerstreak@28 865 AceOO:error('Attempt to modify a read-only class prototype.')
flickerstreak@28 866 end
flickerstreak@28 867 local function ts(bit)
flickerstreak@28 868 if type(bit) ~= "table" then
flickerstreak@28 869 return tostring(bit)
flickerstreak@28 870 elseif getmetatable(bit) and bit.__tostring then
flickerstreak@28 871 return tostring(bit)
flickerstreak@28 872 elseif type(bit.GetLibraryVersion) == "function" then
flickerstreak@28 873 return bit:GetLibraryVersion()
flickerstreak@28 874 else
flickerstreak@28 875 return tostring(bit)
flickerstreak@28 876 end
flickerstreak@28 877 end
flickerstreak@28 878 local t = {}
flickerstreak@28 879 local function getcomplexuid(sc, ...)
flickerstreak@28 880 if sc then
flickerstreak@28 881 if sc.uid then
flickerstreak@28 882 table.insert(t, sc.uid)
flickerstreak@28 883 else
flickerstreak@28 884 AceOO:error("%s is not an appropriate class/mixin", ts(sc))
flickerstreak@28 885 end
flickerstreak@28 886 end
flickerstreak@28 887 for i = 1, select('#', ...) do
flickerstreak@28 888 local m = select(i, ...)
flickerstreak@28 889 if m.uid then
flickerstreak@28 890 table.insert(t, m.uid)
flickerstreak@28 891 else
flickerstreak@28 892 AceOO:error("%s is not an appropriate mixin", ts(m))
flickerstreak@28 893 end
flickerstreak@28 894 end
flickerstreak@28 895 table.sort(t)
flickerstreak@28 896 local uid = table.concat(t, '')
flickerstreak@28 897 local num = #t
flickerstreak@28 898 for i = 1, num do
flickerstreak@28 899 t[i] = nil
flickerstreak@28 900 end
flickerstreak@28 901 return uid
flickerstreak@28 902 end
flickerstreak@28 903 local classmeta
flickerstreak@28 904 local arg = {}
flickerstreak@28 905 function Classpool(superclass, ...)
flickerstreak@28 906 local l = getlibrary
flickerstreak@28 907 superclass = getlibrary(superclass)
flickerstreak@28 908 arg = { ... }
flickerstreak@28 909 for i, v in ipairs(arg) do
flickerstreak@28 910 arg[i] = getlibrary(v)
flickerstreak@28 911 end
flickerstreak@28 912 if superclass then
flickerstreak@28 913 if superclass.class then -- mixin
flickerstreak@28 914 table.insert(arg, 1, superclass)
flickerstreak@28 915 superclass = Class
flickerstreak@28 916 end
flickerstreak@28 917 else
flickerstreak@28 918 superclass = Class
flickerstreak@28 919 end
flickerstreak@28 920 local key = getcomplexuid(superclass, unpack(arg))
flickerstreak@28 921 if not pool[key] then
flickerstreak@28 922 local class = Class(superclass, unpack(arg))
flickerstreak@28 923 if not classmeta then
flickerstreak@28 924 classmeta = {}
flickerstreak@28 925 local mt = getmetatable(class)
flickerstreak@28 926 for k,v in pairs(mt) do
flickerstreak@28 927 classmeta[k] = v
flickerstreak@28 928 end
flickerstreak@28 929 classmeta.__newindex = newindex
flickerstreak@28 930 end
flickerstreak@28 931 -- Prevent the user from adding methods to this class.
flickerstreak@28 932 -- NOTE: I'm not preventing modifications of existing class members,
flickerstreak@28 933 -- but it's likely that only a truly malicious user will be doing so.
flickerstreak@28 934 class.sealed = true
flickerstreak@28 935 setmetatable(class, classmeta)
flickerstreak@28 936 getmetatable(class.prototype).__newindex = protonewindex
flickerstreak@28 937 pool[key] = class
flickerstreak@28 938 end
flickerstreak@28 939 return pool[key]
flickerstreak@28 940 end
flickerstreak@28 941 end
flickerstreak@28 942
flickerstreak@28 943 AceOO.Factory = Factory
flickerstreak@28 944 AceOO.Object = Object
flickerstreak@28 945 AceOO.Class = Class
flickerstreak@28 946 AceOO.Mixin = Mixin
flickerstreak@28 947 AceOO.Interface = Interface
flickerstreak@28 948 AceOO.Classpool = Classpool
flickerstreak@28 949 AceOO.inherits = inherits
flickerstreak@28 950
flickerstreak@28 951 -- Library handling bits
flickerstreak@28 952
flickerstreak@28 953 local function activate(self, oldLib, oldDeactivate)
flickerstreak@28 954 AceOO = self
flickerstreak@28 955 Factory = self.Factory
flickerstreak@28 956 Object = self.Object
flickerstreak@28 957 Class = self.Class
flickerstreak@28 958 ClassFactory.prototype = Class
flickerstreak@28 959 Mixin = self.Mixin
flickerstreak@28 960 Interface = self.Interface
flickerstreak@28 961 Classpool = self.Classpool
flickerstreak@28 962
flickerstreak@28 963 if oldLib then
flickerstreak@28 964 self.classes = oldLib.classes
flickerstreak@28 965 end
flickerstreak@28 966 if not self.classes then
flickerstreak@28 967 self.classes = setmetatable({}, {__mode="k"})
flickerstreak@28 968 else
flickerstreak@28 969 for class in pairs(self.classes) do
flickerstreak@28 970 class.new = class_new
flickerstreak@28 971 end
flickerstreak@28 972 end
flickerstreak@28 973
flickerstreak@28 974 if oldDeactivate then
flickerstreak@28 975 oldDeactivate(oldLib)
flickerstreak@28 976 end
flickerstreak@28 977 end
flickerstreak@28 978
flickerstreak@28 979 AceLibrary:Register(AceOO, MAJOR_VERSION, MINOR_VERSION, activate)
flickerstreak@28 980 AceOO = AceLibrary(MAJOR_VERSION)