--@include ../utils.txt --@include ../skins/default.txt require("../utils.txt") local defaultSkin = require("../skins/default.txt") Element = class("Element") accessorFunc(Element, "_x", "X", 0) accessorFunc(Element, "_y", "Y", 0) function Element:initialize() self._width = 0 self._height = 0 self._enabled = true self._visible = true self._draggable = true self._hovered = false self._parent = nil self._firstChild = nil self._prevSibling = nil self._nextSibling = nil self._skin = defaultSkin end function Element:setWidth(width) self._width = width self:performLayout(self:getSize()) end function Element:getWidth() return self._width end function Element:setHeight(height) self._height = height self:performLayout(self:getSize()) end function Element:getHeight() return self._height end function Element:setSize(width, height) self:setWidth(width) self:setHeight(height) end function Element:getSize() return self:getWidth(), self:getHeight() end function Element:setPos(x, y) self:setX(x) self:setY(y) end function Element:getPos() return self._x, self._y end function Element:getAbsolutePos(x, y) x = x == nil and self:getX() or x + self:getX() y = y == nil and self:getY() or y + self:getY() if self:hasParent() then x, y = self:getParent():getAbsolutePos(x, y) end return x, y end function Element:getBounds() return self:getX(), self:getY(), self:getX() + self:getWidth(), self:getY() + self:getHeight() end function Element:getAbsoluteBounds() local aX, aY = self:getAbsolutePos() return aX, aY, aX + self:getWidth(), aY + self:getHeight() end function Element:setEnabled(enabled) self._enabled = enabled end function Element:isEnabled() return self._enabled end function Element:setVisible(visible) self._visible = visible end function Element:isVisible() return self._visible end function Element:setDraggable(draggable) self._draggable = draggable end function Element:isDraggable() return self._draggable end function Element:isHovered() return self._hovered end function Element:setParent(parent) checkVarClass(parent, Element) self._parent = parent end function Element:getParent() return self._parent end function Element:hasParent() return self:getParent() ~= nil end function Element:addChild(child) checkVarClass(child, Element) child:setParent(self) child:_setSkin(self._skin) if not self._firstChild then self._firstChild = child else local temp = self._firstChild while temp._nextSibling do temp = temp._nextSibling end temp._nextSibling = child child._prevSibling = temp end end function Element:requestFocus() --return end function Element:hasFocus() --return self._focus end function Element:cursorIntersect(x, y) --local self:getAbsoluteBounds() local aX, aY = self:getAbsolutePos() if x >= aX and x <= aX + self:getWidth() and y >= aY and y <= aY + self:getHeight() then return true end return false end function Element:moveToFront(child) if child then local next = child._nextSibling local prev = child._prevSibling if prev then prev._nextSibling = next if next then next._prevSibling = prev end else return end child._nextSibling = self._firstChild self._firstChild._prevSibling = child child._prevSibling = nil self._firstChild = child end end -- PROTECTED function Element:_setSkin(skin) self._skin = skin end function Element:_postEvent(eventKey, ...) if eventKey == "THINK" then return self:_onThink() elseif eventKey == "PAINT" then return self:_onPaint() elseif eventKey == "MOUSE_PRESSED" then return self:_onMousePressed(...) elseif eventKey == "MOUSE_RELEASED" then return self:_onMouseReleased(...) elseif eventKey == "MOUSE_MOVED" then return self:_onMouseMoved(...) end end function Element:_postEventToAll(eventKey, ...) local temp = self._firstChild while temp do local next = temp._nextSibling if temp:_postEvent(eventKey, ...) then return temp end temp = next end return nil end function Element:_postEventToAllReverse(eventKey, ...) local next = self._nextSibling if next then next:_postEventToAllReverse(eventKey, ...) end self:_postEvent(eventKey, ...) return nil end function Element:_onThink() if self:isEnabled() then if type(self.think) == "function" then self:think() end if self._firstChild then self._firstChild:_postEventToAllReverse("THINK") end end end function Element:_onPaint() if self:isVisible() then --[[ if self:hasParent() then render.enableScissorRect(self:getParent():getBounds()) end ]] self:paint() if self._firstChild then self._firstChild:_postEventToAllReverse("PAINT") end end end function Element:_onMousePressed(x, y, key, keyName) if self:cursorIntersect(x, y) and self:isEnabled() then local element = self:_postEventToAll("MOUSE_PRESSED", x, y, key, keyName) if not element then self:onMousePressed(x, y, key, keyName) if self:hasParent() then self:getParent():moveToFront(self) end -- focus end return true else -- unfocus return false end end function Element:_onMouseReleased(x, y, key, keyName) if self:cursorIntersect(x, y) and self:isEnabled() then local element = self:_postEventToAll("MOUSE_RELEASED", x, y, key, keyName) if not element then self:onMouseReleased(x, y, key, keyName) end return true else return false end end function Element:_onMouseMoved(x, y) if self:cursorIntersect(x, y) and self:isEnabled() then local element = self:_postEventToAll("MOUSE_MOVED", x, y) if not element then if not self:isHovered() then self._hovered = true self:onMouseEnter() end self:onMouseMoved(x, y) end return true else if self:isHovered() then self._hovered = false self:onMouseLeave() end return false end end function Element:_onButtonPressed(key, keyName) end function Element:_onButtonReleased(key, keyName) end -- STUB function Element:performLayout() end function Element:paint() end function Element:onMousePressed(x, y, key, keyName) end function Element:onMouseReleased(x, y, key, keyName) end function Element:onMouseMoved(x, y) end function Element:onMouseEnter() end function Element:onMouseLeave() end function Element:onButtonPressed(key, keyName) end function Element:onButtonReleased(key, keyName) end