Nikita Kruglickiy eaf0a90173 )
2020-12-27 21:29:46 +06:00

351 lines
7.1 KiB
Plaintext

--@include /koptilnya/libs/utils.txt
require("/koptilnya/libs/utils.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
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)
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:_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