mirror of
https://github.com/TangentFoxy/Pop.Box.git
synced 2024-12-15 12:44:20 +00:00
commit
6a42bde50f
21
LICENSE.txt
Normal file
21
LICENSE.txt
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2016 Paul Liverman III
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
52
README.md
Normal file
52
README.md
Normal file
@ -0,0 +1,52 @@
|
||||
# Pop.Box
|
||||
|
||||
*Do not mix with [Cola][1].*
|
||||
|
||||
Pop.Box is a GUI library for use in the [LÖVE][2] engine, designed to be easy to
|
||||
use and require as little code as possible to set up. It is primarily designed
|
||||
to make it easy to experiment with GUIs during development.
|
||||
|
||||
Supports LÖVE versions 0.9.1 and higher.
|
||||
|
||||
## Features
|
||||
|
||||
- Quickly set up and align GUI elements.
|
||||
- Fully customizable alignment / styling.
|
||||
- Moving/resizing elements takes alignment into account.
|
||||
- Mouse and key input handling. (**Note**: Work in progress.)
|
||||
- Extensible: Make your own elements, skins, extensions, and everything is
|
||||
automatically loaded.
|
||||
|
||||
## Usage
|
||||
|
||||
The basics:
|
||||
|
||||
```lua
|
||||
local pop = require "pop"
|
||||
-- define LÖVE callbacks here (update, draw, textinput, mouse/key events)
|
||||
local window = pop.window():align("center"):setTitle("Welcome!")
|
||||
window:addChild(pop.text("Welcome to Pop.Box()!"))
|
||||
```
|
||||
|
||||
**Note**: Due to this being so early in development...the above example doesn't
|
||||
actually work as expected. `window` is a very new element.
|
||||
|
||||
For more examples, see the code in `demo`. For documentation, see `docs`.
|
||||
|
||||
# Documentation
|
||||
|
||||
**Note**: Docs not written just yet. Will be soon.
|
||||
|
||||
- [Pop Module][3] (The main module/interface.)
|
||||
- [Elements][4] (Basic features of elements/types of elements.)
|
||||
- [Skins][5] (A basic system for quickly applying settings to many elements.)
|
||||
- [Extensions][7] (A way to load custom code in.)
|
||||
- [Drawables][6] (Reference for what can be used as a background/color.)
|
||||
|
||||
[1]: https://en.wikipedia.org/wiki/Cola_(programming_language)
|
||||
[2]: https://love2d.org/
|
||||
[3]: ./docs/Pop.md
|
||||
[4]: ./docs/Elements.md
|
||||
[5]: ./docs/Skins.md
|
||||
[6]: ./docs/Drawables.md
|
||||
[7]: ./docs/Extensions.md
|
5
build.sh
Executable file
5
build.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
cd src
|
||||
moonc -t ../lib .
|
||||
cd ..
|
||||
cp -rf ./lib/pop/* ./demo/pop/
|
344
demo/debug-lib/inspect.lua
Normal file
344
demo/debug-lib/inspect.lua
Normal file
@ -0,0 +1,344 @@
|
||||
local inspect ={
|
||||
_VERSION = 'inspect.lua 3.0.3',
|
||||
_URL = 'http://github.com/kikito/inspect.lua',
|
||||
_DESCRIPTION = 'human-readable representations of tables',
|
||||
_LICENSE = [[
|
||||
MIT LICENSE
|
||||
|
||||
Copyright (c) 2013 Enrique García Cota
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
}
|
||||
|
||||
inspect.KEY = setmetatable({}, {__tostring = function() return 'inspect.KEY' end})
|
||||
inspect.METATABLE = setmetatable({}, {__tostring = function() return 'inspect.METATABLE' end})
|
||||
|
||||
-- Apostrophizes the string if it has quotes, but not aphostrophes
|
||||
-- Otherwise, it returns a regular quoted string
|
||||
local function smartQuote(str)
|
||||
if str:match('"') and not str:match("'") then
|
||||
return "'" .. str .. "'"
|
||||
end
|
||||
return '"' .. str:gsub('"', '\\"') .. '"'
|
||||
end
|
||||
|
||||
local controlCharsTranslation = {
|
||||
["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n",
|
||||
["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v"
|
||||
}
|
||||
|
||||
local function escape(str)
|
||||
local result = str:gsub("\\", "\\\\"):gsub("(%c)", controlCharsTranslation)
|
||||
return result
|
||||
end
|
||||
|
||||
local function isIdentifier(str)
|
||||
return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" )
|
||||
end
|
||||
|
||||
local function isSequenceKey(k, sequenceLength)
|
||||
return type(k) == 'number'
|
||||
and 1 <= k
|
||||
and k <= sequenceLength
|
||||
and math.floor(k) == k
|
||||
end
|
||||
|
||||
local defaultTypeOrders = {
|
||||
['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4,
|
||||
['function'] = 5, ['userdata'] = 6, ['thread'] = 7
|
||||
}
|
||||
|
||||
local function sortKeys(a, b)
|
||||
local ta, tb = type(a), type(b)
|
||||
|
||||
-- strings and numbers are sorted numerically/alphabetically
|
||||
if ta == tb and (ta == 'string' or ta == 'number') then return a < b end
|
||||
|
||||
local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb]
|
||||
-- Two default types are compared according to the defaultTypeOrders table
|
||||
if dta and dtb then return defaultTypeOrders[ta] < defaultTypeOrders[tb]
|
||||
elseif dta then return true -- default types before custom ones
|
||||
elseif dtb then return false -- custom types after default ones
|
||||
end
|
||||
|
||||
-- custom types are sorted out alphabetically
|
||||
return ta < tb
|
||||
end
|
||||
|
||||
-- For implementation reasons, the behavior of rawlen & # is "undefined" when
|
||||
-- tables aren't pure sequences. So we implement our own # operator.
|
||||
local function getSequenceLength(t)
|
||||
local len = 1
|
||||
local v = rawget(t,len)
|
||||
while v ~= nil do
|
||||
len = len + 1
|
||||
v = rawget(t,len)
|
||||
end
|
||||
return len - 1
|
||||
end
|
||||
|
||||
local function getNonSequentialKeys(t)
|
||||
local keys = {}
|
||||
local sequenceLength = getSequenceLength(t)
|
||||
for k,_ in pairs(t) do
|
||||
if not isSequenceKey(k, sequenceLength) then table.insert(keys, k) end
|
||||
end
|
||||
table.sort(keys, sortKeys)
|
||||
return keys, sequenceLength
|
||||
end
|
||||
|
||||
local function getToStringResultSafely(t, mt)
|
||||
local __tostring = type(mt) == 'table' and rawget(mt, '__tostring')
|
||||
local str, ok
|
||||
if type(__tostring) == 'function' then
|
||||
ok, str = pcall(__tostring, t)
|
||||
str = ok and str or 'error: ' .. tostring(str)
|
||||
end
|
||||
if type(str) == 'string' and #str > 0 then return str end
|
||||
end
|
||||
|
||||
local maxIdsMetaTable = {
|
||||
__index = function(self, typeName)
|
||||
rawset(self, typeName, 0)
|
||||
return 0
|
||||
end
|
||||
}
|
||||
|
||||
local idsMetaTable = {
|
||||
__index = function (self, typeName)
|
||||
local col = {}
|
||||
rawset(self, typeName, col)
|
||||
return col
|
||||
end
|
||||
}
|
||||
|
||||
local function countTableAppearances(t, tableAppearances)
|
||||
tableAppearances = tableAppearances or {}
|
||||
|
||||
if type(t) == 'table' then
|
||||
if not tableAppearances[t] then
|
||||
tableAppearances[t] = 1
|
||||
for k,v in pairs(t) do
|
||||
countTableAppearances(k, tableAppearances)
|
||||
countTableAppearances(v, tableAppearances)
|
||||
end
|
||||
countTableAppearances(getmetatable(t), tableAppearances)
|
||||
else
|
||||
tableAppearances[t] = tableAppearances[t] + 1
|
||||
end
|
||||
end
|
||||
|
||||
return tableAppearances
|
||||
end
|
||||
|
||||
local copySequence = function(s)
|
||||
local copy, len = {}, #s
|
||||
for i=1, len do copy[i] = s[i] end
|
||||
return copy, len
|
||||
end
|
||||
|
||||
local function makePath(path, ...)
|
||||
local keys = {...}
|
||||
local newPath, len = copySequence(path)
|
||||
for i=1, #keys do
|
||||
newPath[len + i] = keys[i]
|
||||
end
|
||||
return newPath
|
||||
end
|
||||
|
||||
local function processRecursive(process, item, path, visited)
|
||||
|
||||
if item == nil then return nil end
|
||||
if visited[item] then return visited[item] end
|
||||
|
||||
local processed = process(item, path)
|
||||
if type(processed) == 'table' then
|
||||
local processedCopy = {}
|
||||
visited[item] = processedCopy
|
||||
local processedKey
|
||||
|
||||
for k,v in pairs(processed) do
|
||||
processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited)
|
||||
if processedKey ~= nil then
|
||||
processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited)
|
||||
end
|
||||
end
|
||||
|
||||
local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited)
|
||||
setmetatable(processedCopy, mt)
|
||||
processed = processedCopy
|
||||
end
|
||||
return processed
|
||||
end
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
local Inspector = {}
|
||||
local Inspector_mt = {__index = Inspector}
|
||||
|
||||
function Inspector:puts(...)
|
||||
local args = {...}
|
||||
local buffer = self.buffer
|
||||
local len = #buffer
|
||||
for i=1, #args do
|
||||
len = len + 1
|
||||
buffer[len] = tostring(args[i])
|
||||
end
|
||||
end
|
||||
|
||||
function Inspector:down(f)
|
||||
self.level = self.level + 1
|
||||
f()
|
||||
self.level = self.level - 1
|
||||
end
|
||||
|
||||
function Inspector:tabify()
|
||||
self:puts(self.newline, string.rep(self.indent, self.level))
|
||||
end
|
||||
|
||||
function Inspector:alreadyVisited(v)
|
||||
return self.ids[type(v)][v] ~= nil
|
||||
end
|
||||
|
||||
function Inspector:getId(v)
|
||||
local tv = type(v)
|
||||
local id = self.ids[tv][v]
|
||||
if not id then
|
||||
id = self.maxIds[tv] + 1
|
||||
self.maxIds[tv] = id
|
||||
self.ids[tv][v] = id
|
||||
end
|
||||
return id
|
||||
end
|
||||
|
||||
function Inspector:putKey(k)
|
||||
if isIdentifier(k) then return self:puts(k) end
|
||||
self:puts("[")
|
||||
self:putValue(k)
|
||||
self:puts("]")
|
||||
end
|
||||
|
||||
function Inspector:putTable(t)
|
||||
if t == inspect.KEY or t == inspect.METATABLE then
|
||||
self:puts(tostring(t))
|
||||
elseif self:alreadyVisited(t) then
|
||||
self:puts('<table ', self:getId(t), '>')
|
||||
elseif self.level >= self.depth then
|
||||
self:puts('{...}')
|
||||
else
|
||||
if self.tableAppearances[t] > 1 then self:puts('<', self:getId(t), '>') end
|
||||
|
||||
local nonSequentialKeys, sequenceLength = getNonSequentialKeys(t)
|
||||
local mt = getmetatable(t)
|
||||
local toStringResult = getToStringResultSafely(t, mt)
|
||||
|
||||
self:puts('{')
|
||||
self:down(function()
|
||||
if toStringResult then
|
||||
self:puts(' -- ', escape(toStringResult))
|
||||
if sequenceLength >= 1 then self:tabify() end
|
||||
end
|
||||
|
||||
local count = 0
|
||||
for i=1, sequenceLength do
|
||||
if count > 0 then self:puts(',') end
|
||||
self:puts(' ')
|
||||
self:putValue(t[i])
|
||||
count = count + 1
|
||||
end
|
||||
|
||||
for _,k in ipairs(nonSequentialKeys) do
|
||||
if count > 0 then self:puts(',') end
|
||||
self:tabify()
|
||||
self:putKey(k)
|
||||
self:puts(' = ')
|
||||
self:putValue(t[k])
|
||||
count = count + 1
|
||||
end
|
||||
|
||||
if mt then
|
||||
if count > 0 then self:puts(',') end
|
||||
self:tabify()
|
||||
self:puts('<metatable> = ')
|
||||
self:putValue(mt)
|
||||
end
|
||||
end)
|
||||
|
||||
if #nonSequentialKeys > 0 or mt then -- result is multi-lined. Justify closing }
|
||||
self:tabify()
|
||||
elseif sequenceLength > 0 then -- array tables have one extra space before closing }
|
||||
self:puts(' ')
|
||||
end
|
||||
|
||||
self:puts('}')
|
||||
end
|
||||
end
|
||||
|
||||
function Inspector:putValue(v)
|
||||
local tv = type(v)
|
||||
|
||||
if tv == 'string' then
|
||||
self:puts(smartQuote(escape(v)))
|
||||
elseif tv == 'number' or tv == 'boolean' or tv == 'nil' then
|
||||
self:puts(tostring(v))
|
||||
elseif tv == 'table' then
|
||||
self:putTable(v)
|
||||
else
|
||||
self:puts('<',tv,' ',self:getId(v),'>')
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
function inspect.inspect(root, options)
|
||||
options = options or {}
|
||||
|
||||
local depth = options.depth or math.huge
|
||||
local newline = options.newline or '\n'
|
||||
local indent = options.indent or ' '
|
||||
local process = options.process
|
||||
|
||||
if process then
|
||||
root = processRecursive(process, root, {}, {})
|
||||
end
|
||||
|
||||
local inspector = setmetatable({
|
||||
depth = depth,
|
||||
buffer = {},
|
||||
level = 0,
|
||||
ids = setmetatable({}, idsMetaTable),
|
||||
maxIds = setmetatable({}, maxIdsMetaTable),
|
||||
newline = newline,
|
||||
indent = indent,
|
||||
tableAppearances = countTableAppearances(root)
|
||||
}, Inspector_mt)
|
||||
|
||||
inspector:putValue(root)
|
||||
|
||||
return table.concat(inspector.buffer)
|
||||
end
|
||||
|
||||
setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end })
|
||||
|
||||
return inspect
|
||||
|
@ -1,8 +1,14 @@
|
||||
local lg = love.graphics
|
||||
local pop
|
||||
local pop, inspect
|
||||
|
||||
local debugDraw = false
|
||||
|
||||
function love.load()
|
||||
print(love.getVersion())
|
||||
|
||||
inspect = require "debug-lib/inspect"
|
||||
pop = require "pop"
|
||||
---[[
|
||||
local c = pop.box():align("center", "center"):setSize(300, 300)
|
||||
pop.box(c, {255, 0, 0, 255}):setSize(100, 50)
|
||||
pop.box(c, {0, 255, 0, 255}):align("center"):setSize(100, 100)
|
||||
@ -17,6 +23,45 @@ function love.load()
|
||||
pop.skin(pop.text("Here's easier-to-code test text in the center!"):align("center", "center", true)) -- 'true' means align to pixel!
|
||||
w = pop.box(nil, {255, 255, 255, 255}):align(false, "bottom"):setSize(150, 150)
|
||||
b = pop.box(w, {0, 0, 0, 255}):setMargin(5):setSize(100, 100)
|
||||
--]]
|
||||
|
||||
--c:move(100)
|
||||
pop.box({255, 0, 0, 255}):position(50, 500) -- testing streamlined_get_set extension & optional parents
|
||||
--b:margin(2) -- testing streamlined_get_set extension
|
||||
b:fill() -- testing fill!
|
||||
|
||||
---[[
|
||||
w2 = pop.window(nil, "Window")
|
||||
w2:move(100, 100)
|
||||
w2:setWidth(500)
|
||||
w2:move(-50, 80)
|
||||
w2:setHeight(500)
|
||||
w2:move(0, -175)
|
||||
w2.title:align("center")
|
||||
w2:position(0, 0)
|
||||
--w2:setAlignment("right")
|
||||
w2:size(200, 120):position(90, 70)
|
||||
--w2:align("center")
|
||||
--w2:setAlignment("center"):align("center")
|
||||
|
||||
--w2.child[1]:setBackground {100, 100, 100, 255}
|
||||
--w2.child[3]:setBackground {160, 140, 40, 255}
|
||||
--]]
|
||||
|
||||
local test = lg.newImage("test.png")
|
||||
G = pop.element():align("right"):move(-2, 2)
|
||||
a = pop.box(G, test):align("right")
|
||||
b = pop.box(G, test):align("right"):move(-25):setWidth(40)
|
||||
c = pop.box(G, test):align("right"):move(0, 25):setHeight(40)
|
||||
|
||||
print(a.horizontal, a.vertical)
|
||||
print(b.horizontal, b.vertical)
|
||||
print(c.horizontal, c.vertical)
|
||||
|
||||
local window = pop.window():align("center", "center"):setTitle("Welcome!")
|
||||
--window:addChild(pop.text("Welcome to Pop.Box()!"))
|
||||
|
||||
--TODO make debugDraw better
|
||||
end
|
||||
|
||||
function love.update(dt)
|
||||
@ -25,7 +70,15 @@ end
|
||||
|
||||
function love.draw()
|
||||
pop.draw()
|
||||
--pop.debugDraw()
|
||||
|
||||
if debugDraw then
|
||||
pop.debugDraw()
|
||||
--w2:debugDraw()
|
||||
end
|
||||
end
|
||||
|
||||
function love.mousemoved(x, y, dx, dy)
|
||||
pop.mousemoved(x, y, dx, dy)
|
||||
end
|
||||
|
||||
function love.mousepressed(x, y, button)
|
||||
@ -39,6 +92,10 @@ end
|
||||
function love.keypressed(key)
|
||||
local handled = pop.keypressed(key)
|
||||
|
||||
if (key == "d") and (not handled) then
|
||||
debugDraw = not debugDraw
|
||||
end
|
||||
|
||||
if (key == "escape") and (not handled) then
|
||||
love.event.quit()
|
||||
end
|
||||
|
@ -21,6 +21,7 @@ do
|
||||
local w, h = self.background:getDimensions()
|
||||
w = self.w / w
|
||||
h = self.h / h
|
||||
graphics.setColor(255, 255, 255, 255)
|
||||
graphics.draw(self.background, self.x, self.y, 0, w, h)
|
||||
end
|
||||
end
|
||||
@ -70,11 +71,13 @@ do
|
||||
_base_0.__index = _base_0
|
||||
setmetatable(_base_0, _parent_0.__base)
|
||||
_class_0 = setmetatable({
|
||||
__init = function(self, pop, parent, background)
|
||||
__init = function(self, parent, background)
|
||||
if background == nil then
|
||||
background = false
|
||||
end
|
||||
_class_0.__parent.__init(self, pop, parent)
|
||||
_class_0.__parent.__init(self, parent)
|
||||
self.w = 20
|
||||
self.h = 20
|
||||
self.background = background
|
||||
end,
|
||||
__base = _base_0,
|
||||
|
@ -16,6 +16,14 @@ do
|
||||
graphics.print("e", self.x, self.y)
|
||||
return self
|
||||
end,
|
||||
addChild = function(self, child)
|
||||
self.child[#self.child + 1] = child
|
||||
child.parent = self
|
||||
return self
|
||||
end,
|
||||
getChildren = function(self)
|
||||
return self.child
|
||||
end,
|
||||
move = function(self, x, y)
|
||||
if x then
|
||||
self.x = self.x + x
|
||||
@ -105,6 +113,32 @@ do
|
||||
getSize = function(self)
|
||||
return self.w, self.h
|
||||
end,
|
||||
setWidth = function(self, w)
|
||||
local _exp_0 = self.horizontal
|
||||
if "center" == _exp_0 then
|
||||
self.x = self.x - ((w - self.w) / 2)
|
||||
elseif "right" == _exp_0 then
|
||||
self.x = self.x - (w - self.w)
|
||||
end
|
||||
self.w = w
|
||||
return self
|
||||
end,
|
||||
getWidth = function(self)
|
||||
return self.w
|
||||
end,
|
||||
setHeight = function(self, h)
|
||||
local _exp_0 = self.vertical
|
||||
if "center" == _exp_0 then
|
||||
self.y = self.y - ((h - self.h) / 2)
|
||||
elseif "bottom" == _exp_0 then
|
||||
self.y = self.y - (h - self.h)
|
||||
end
|
||||
self.h = h
|
||||
return self
|
||||
end,
|
||||
getHeight = function(self)
|
||||
return self.h
|
||||
end,
|
||||
adjustSize = function(self, w, h)
|
||||
local W, H = self:getSize()
|
||||
if w then
|
||||
@ -136,7 +170,7 @@ do
|
||||
elseif "bottom" == _exp_1 then
|
||||
self.y = self.y + (self.parent.h - self.h - self.margin)
|
||||
end
|
||||
if toPixel then
|
||||
if toPixel or (toPixel == nil) then
|
||||
self.x = floor(self.x)
|
||||
self.y = floor(self.y)
|
||||
end
|
||||
@ -158,6 +192,9 @@ do
|
||||
end
|
||||
return self
|
||||
end,
|
||||
getAlignment = function(self)
|
||||
return self.horizontal, self.vertical
|
||||
end,
|
||||
setMargin = function(self, margin)
|
||||
self.margin = margin
|
||||
self:align()
|
||||
@ -165,25 +202,31 @@ do
|
||||
end,
|
||||
getMargin = function(self)
|
||||
return self.margin
|
||||
end,
|
||||
fill = function(self)
|
||||
self.x = self.parent.x + self.margin
|
||||
self.y = self.parent.y + self.margin
|
||||
self.w = self.parent.w - self.margin * 2
|
||||
self.h = self.parent.h - self.margin * 2
|
||||
end
|
||||
}
|
||||
_base_0.__index = _base_0
|
||||
_class_0 = setmetatable({
|
||||
__init = function(self, pop, parent)
|
||||
__init = function(self, parent)
|
||||
self.parent = parent
|
||||
self.child = { }
|
||||
self.w = 0
|
||||
self.h = 0
|
||||
self.margin = 0
|
||||
if parent then
|
||||
self.x = parent.x or 0
|
||||
self.y = parent.y or 0
|
||||
self.x = parent.x
|
||||
self.y = parent.y
|
||||
else
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
end
|
||||
self.w = 10
|
||||
self.h = 10
|
||||
self.horizontal = "left"
|
||||
self.vertical = "top"
|
||||
self.margin = 0
|
||||
end,
|
||||
__base = _base_0,
|
||||
__name = "element"
|
||||
|
@ -12,19 +12,10 @@ do
|
||||
local _class_0
|
||||
local _parent_0 = element
|
||||
local _base_0 = {
|
||||
wrap = function(pop)
|
||||
return function(parent, ...)
|
||||
if type(parent) == "string" then
|
||||
return pop.create("text", nil, parent, ...)
|
||||
else
|
||||
return pop.create("text", parent, ...)
|
||||
end
|
||||
end
|
||||
end,
|
||||
draw = function(self)
|
||||
graphics.setColor(self.color)
|
||||
graphics.setFont(self.font)
|
||||
graphics.print(self.text, self.x, self.y)
|
||||
graphics.print(self.txt, self.x, self.y)
|
||||
return self
|
||||
end,
|
||||
debugDraw = function(self)
|
||||
@ -38,8 +29,8 @@ do
|
||||
return self
|
||||
end,
|
||||
setSize = function(self)
|
||||
local w = self.font:getWidth(self.text)
|
||||
local h = self.font:getHeight() * (select(2, self.text:gsub("\n", "\n")) + 1)
|
||||
local w = self.font:getWidth(self.txt)
|
||||
local h = self.font:getHeight() * (select(2, self.txt:gsub("\n", "\n")) + 1)
|
||||
local _exp_0 = self.horizontal
|
||||
if "center" == _exp_0 then
|
||||
self.x = self.x - ((w - self.w) / 2)
|
||||
@ -56,16 +47,24 @@ do
|
||||
self.h = h
|
||||
return self
|
||||
end,
|
||||
setWidth = function(self)
|
||||
self:setSize()
|
||||
return self
|
||||
end,
|
||||
setHeight = function(self)
|
||||
self:setSize()
|
||||
return self
|
||||
end,
|
||||
setText = function(self, text)
|
||||
if text == nil then
|
||||
text = ""
|
||||
end
|
||||
self.text = text
|
||||
self.txt = text
|
||||
self:setSize()
|
||||
return self
|
||||
end,
|
||||
getText = function(self)
|
||||
return self.text
|
||||
return self.txt
|
||||
end,
|
||||
setFont = function(self, font)
|
||||
self.font = font
|
||||
@ -98,7 +97,7 @@ do
|
||||
_base_0.__index = _base_0
|
||||
setmetatable(_base_0, _parent_0.__base)
|
||||
_class_0 = setmetatable({
|
||||
__init = function(self, pop, parent, text, color)
|
||||
__init = function(self, parent, text, color)
|
||||
if text == nil then
|
||||
text = ""
|
||||
end
|
||||
@ -110,7 +109,7 @@ do
|
||||
255
|
||||
}
|
||||
end
|
||||
_class_0.__parent.__init(self, pop, parent)
|
||||
_class_0.__parent.__init(self, parent)
|
||||
self.font = graphics.newFont(14)
|
||||
self:setText(text)
|
||||
self.color = color
|
||||
@ -137,6 +136,16 @@ do
|
||||
end
|
||||
})
|
||||
_base_0.__class = _class_0
|
||||
local self = _class_0
|
||||
self.wrap = function(pop)
|
||||
return function(parent, ...)
|
||||
if type(parent) == "string" then
|
||||
return pop.create("text", nil, parent, ...)
|
||||
else
|
||||
return pop.create("text", parent, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
if _parent_0.__inherited then
|
||||
_parent_0.__inherited(_parent_0, _class_0)
|
||||
end
|
||||
|
251
demo/pop/elements/window.lua
Normal file
251
demo/pop/elements/window.lua
Normal file
@ -0,0 +1,251 @@
|
||||
local graphics
|
||||
graphics = love.graphics
|
||||
local sub, len
|
||||
do
|
||||
local _obj_0 = string
|
||||
sub, len = _obj_0.sub, _obj_0.len
|
||||
end
|
||||
local path = sub(..., 1, len(...) - len("/window"))
|
||||
local element = require(tostring(path) .. "/element")
|
||||
local box = require(tostring(path) .. "/box")
|
||||
local text = require(tostring(path) .. "/text")
|
||||
local left = 1
|
||||
local mousemoved_event = true
|
||||
do
|
||||
local major, minor, revision = love.getVersion()
|
||||
if (major == 0) and (minor == 10) and ((revision == 0) or (revision == 1)) then
|
||||
left = 1
|
||||
elseif (major == 0) and (minor == 9) then
|
||||
left = "l"
|
||||
if revision == 1 then
|
||||
mousemoved_event = false
|
||||
end
|
||||
else
|
||||
print("elements/window: unrecognized LÖVE version: " .. tostring(major) .. "." .. tostring(minor) .. "." .. tostring(revision))
|
||||
print(" assuming LÖVE version > 0.10.1 (there may be bugs)")
|
||||
end
|
||||
end
|
||||
local pop_ref = false
|
||||
local window
|
||||
do
|
||||
local _class_0
|
||||
local _parent_0 = element
|
||||
local _base_0 = {
|
||||
load = function(pop)
|
||||
pop_ref = pop
|
||||
end,
|
||||
debugDraw = function(self)
|
||||
graphics.setLineWidth(0.5)
|
||||
graphics.setColor(0, 0, 0, 100)
|
||||
graphics.rectangle("fill", self.x, self.y, self.w, self.h)
|
||||
graphics.setColor(200, 0, 200, 200)
|
||||
graphics.rectangle("line", self.x, self.y, self.w, self.h)
|
||||
graphics.setColor(255, 200, 255, 255)
|
||||
graphics.print("w", self.x, self.y)
|
||||
return self
|
||||
end,
|
||||
addChild = function(self, child)
|
||||
self.window.child[#self.window.child + 1] = child
|
||||
child.parent = self.window
|
||||
return self
|
||||
end,
|
||||
getChildren = function(self)
|
||||
return self.window.child
|
||||
end,
|
||||
align = function(self, horizontal, vertical, toPixel)
|
||||
_class_0.__parent.__base.align(self, horizontal, vertical, toPixel)
|
||||
for i = 1, #self.child do
|
||||
self.child[i]:align()
|
||||
end
|
||||
self.window:move(nil, self.head:getHeight())
|
||||
return self
|
||||
end,
|
||||
setSize = function(self, w, h)
|
||||
local x = 0
|
||||
local y = 0
|
||||
if w then
|
||||
local _exp_0 = self.horizontal
|
||||
if "center" == _exp_0 then
|
||||
x = x - ((w - self.w) / 2)
|
||||
elseif "right" == _exp_0 then
|
||||
x = x - (w - self.w)
|
||||
end
|
||||
self.head:setWidth(w)
|
||||
self.window:setWidth(w)
|
||||
self.w = w
|
||||
self.x = self.x + x
|
||||
self.title:align()
|
||||
end
|
||||
if h then
|
||||
h = h - self.head:getHeight()
|
||||
local _exp_0 = self.vertical
|
||||
if "center" == _exp_0 then
|
||||
y = y - ((h - self.h) / 2)
|
||||
elseif "right" == _exp_0 then
|
||||
y = y - (h - self.h)
|
||||
end
|
||||
self.window:setHeight(h)
|
||||
self.h = h + self.head:getHeight()
|
||||
self.y = self.y + y
|
||||
end
|
||||
self.head:move(x, y)
|
||||
self.window:move(x, y)
|
||||
return self
|
||||
end,
|
||||
setWidth = function(self, w)
|
||||
local x = 0
|
||||
local _exp_0 = self.horizontal
|
||||
if "center" == _exp_0 then
|
||||
x = x - ((w - self.w) / 2)
|
||||
elseif "right" == _exp_0 then
|
||||
x = x - (w - self.w)
|
||||
end
|
||||
self.head:setWidth(w)
|
||||
self.window:setWidth(w)
|
||||
self.w = w
|
||||
self.x = self.x + x
|
||||
self.title:align()
|
||||
self.head:move(x)
|
||||
self.window:move(x)
|
||||
return self
|
||||
end,
|
||||
setHeight = function(self, h)
|
||||
local y = 0
|
||||
h = h - self.head:getHeight()
|
||||
local _exp_0 = self.vertical
|
||||
if "center" == _exp_0 then
|
||||
y = y - ((h - self.h) / 2)
|
||||
elseif "right" == _exp_0 then
|
||||
y = y - (h - self.h)
|
||||
end
|
||||
self.window:setHeight(h)
|
||||
self.h = h + self.head:getHeight()
|
||||
self.y = self.y + y
|
||||
self.head:move(nil, y)
|
||||
self.title:move(nil, y)
|
||||
self.window:move(nil, y)
|
||||
return self
|
||||
end,
|
||||
setTitle = function(self, title)
|
||||
self.title:setText(title)
|
||||
return self
|
||||
end
|
||||
}
|
||||
_base_0.__index = _base_0
|
||||
setmetatable(_base_0, _parent_0.__base)
|
||||
_class_0 = setmetatable({
|
||||
__init = function(self, parent, title, tBackground, tColor, wBackground)
|
||||
if title == nil then
|
||||
title = "window"
|
||||
end
|
||||
if tBackground == nil then
|
||||
tBackground = {
|
||||
25,
|
||||
180,
|
||||
230,
|
||||
255
|
||||
}
|
||||
end
|
||||
if tColor == nil then
|
||||
tColor = {
|
||||
255,
|
||||
255,
|
||||
255,
|
||||
255
|
||||
}
|
||||
end
|
||||
if wBackground == nil then
|
||||
wBackground = {
|
||||
200,
|
||||
200,
|
||||
210,
|
||||
255
|
||||
}
|
||||
end
|
||||
_class_0.__parent.__init(self, parent)
|
||||
self.head = box(self, tBackground)
|
||||
self.title = text(self, title, tColor)
|
||||
self.window = box(self, wBackground)
|
||||
local height = self.title:getHeight()
|
||||
self.head:setSize(self.w, height)
|
||||
self.window:move(nil, height)
|
||||
self:setSize(100, 80)
|
||||
self.child = {
|
||||
self.head,
|
||||
self.title,
|
||||
self.window
|
||||
}
|
||||
self.head.selected = false
|
||||
if mousemoved_event then
|
||||
self.head.mousemoved = function(self, x, y, dx, dy)
|
||||
if self.selected then
|
||||
self.parent:move(y, dx)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
self.head.mousepressed = function(self, x, y, button)
|
||||
if button == left then
|
||||
self.selected = true
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
self.head.mousereleased = function(self, x, y, button)
|
||||
if button == left then
|
||||
self.selected = false
|
||||
pop_ref.focused = false
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
else
|
||||
self.head.mx = 0
|
||||
self.head.my = 0
|
||||
self.head.update = function(self)
|
||||
return false
|
||||
end
|
||||
self.head.mousepressed = function(self, x, y, button)
|
||||
if button == left then
|
||||
self.selected = true
|
||||
self.mx = x
|
||||
self.my = y
|
||||
end
|
||||
end
|
||||
self.head.mousereleased = function(self, x, y, button)
|
||||
if button == left then
|
||||
self.selected = false
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
end,
|
||||
__base = _base_0,
|
||||
__name = "window",
|
||||
__parent = _parent_0
|
||||
}, {
|
||||
__index = function(cls, name)
|
||||
local val = rawget(_base_0, name)
|
||||
if val == nil then
|
||||
local parent = rawget(cls, "__parent")
|
||||
if parent then
|
||||
return parent[name]
|
||||
end
|
||||
else
|
||||
return val
|
||||
end
|
||||
end,
|
||||
__call = function(cls, ...)
|
||||
local _self_0 = setmetatable({}, _base_0)
|
||||
cls.__init(_self_0, ...)
|
||||
return _self_0
|
||||
end
|
||||
})
|
||||
_base_0.__class = _class_0
|
||||
if _parent_0.__inherited then
|
||||
_parent_0.__inherited(_parent_0, _class_0)
|
||||
end
|
||||
window = _class_0
|
||||
return _class_0
|
||||
end
|
51
demo/pop/extensions/streamlined_get_set.lua
Normal file
51
demo/pop/extensions/streamlined_get_set.lua
Normal file
@ -0,0 +1,51 @@
|
||||
local graphics
|
||||
graphics = love.graphics
|
||||
local sub, len
|
||||
do
|
||||
local _obj_0 = string
|
||||
sub, len = _obj_0.sub, _obj_0.len
|
||||
end
|
||||
local path = sub(..., 1, len(...) - len("/extensions/streamlined_get_set"))
|
||||
local element = require(tostring(path) .. "/elements/element")
|
||||
element.__base.position = function(self, x, y)
|
||||
if x or y then
|
||||
return self:setPosition(x, y)
|
||||
else
|
||||
return self:getPosition()
|
||||
end
|
||||
end
|
||||
element.__base.size = function(self, w, h)
|
||||
if w or h then
|
||||
return self:setSize(w, h)
|
||||
else
|
||||
return self:getSize()
|
||||
end
|
||||
end
|
||||
element.__base.width = function(self, w)
|
||||
if w then
|
||||
return self:setWidth(w)
|
||||
else
|
||||
return self:getWidth()
|
||||
end
|
||||
end
|
||||
element.__base.height = function(self, h)
|
||||
if h then
|
||||
return self:setHeight(h)
|
||||
else
|
||||
return self:getHeight()
|
||||
end
|
||||
end
|
||||
element.__base.alignment = function(self, horizontal, vertical)
|
||||
if horizontal or vertical then
|
||||
return self:setAlignment(horizontal, vertical)
|
||||
else
|
||||
return self:getAlignment()
|
||||
end
|
||||
end
|
||||
element.__base.margin = function(self, m)
|
||||
if m then
|
||||
return self:setMargin(m)
|
||||
else
|
||||
return self:getMargin()
|
||||
end
|
||||
end
|
@ -1,3 +1,6 @@
|
||||
if not (love.getVersion) then
|
||||
error("Pop.Box only supports LÖVE versions >= 0.9.1")
|
||||
end
|
||||
local filesystem, graphics
|
||||
do
|
||||
local _obj_0 = love
|
||||
@ -5,11 +8,15 @@ do
|
||||
end
|
||||
local insert
|
||||
insert = table.insert
|
||||
local inheritsFromElement
|
||||
inheritsFromElement = require(tostring(...) .. "/util").inheritsFromElement
|
||||
local path = ...
|
||||
local pop = { }
|
||||
pop.elements = { }
|
||||
pop.skins = { }
|
||||
pop.events = { }
|
||||
pop.screen = false
|
||||
pop.focused = false
|
||||
pop.load = function()
|
||||
local elements = filesystem.getDirectoryItems(tostring(path) .. "/elements")
|
||||
for i = 1, #elements do
|
||||
@ -21,6 +28,9 @@ pop.load = function()
|
||||
end
|
||||
local name = elements[i]:sub(1, -5)
|
||||
pop.elements[name] = require(tostring(path) .. "/elements/" .. tostring(name))
|
||||
if pop.elements[name].load then
|
||||
pop.elements[name].load(pop)
|
||||
end
|
||||
print("element loaded: \"" .. tostring(name) .. "\"")
|
||||
if not (pop[name]) then
|
||||
if pop.elements[name].wrap then
|
||||
@ -55,6 +65,23 @@ pop.load = function()
|
||||
break
|
||||
end
|
||||
end
|
||||
local extensions = filesystem.getDirectoryItems(tostring(path) .. "/extensions")
|
||||
for i = 1, #extensions do
|
||||
local _continue_0 = false
|
||||
repeat
|
||||
if not (extensions[i]:sub(-4) == ".lua") then
|
||||
_continue_0 = true
|
||||
break
|
||||
end
|
||||
local name = extensions[i]:sub(1, -5)
|
||||
require(tostring(path) .. "/extensions/" .. tostring(name))
|
||||
print("extension loaded: \"" .. tostring(name) .. "\"")
|
||||
_continue_0 = true
|
||||
until true
|
||||
if not _continue_0 then
|
||||
break
|
||||
end
|
||||
end
|
||||
pop.screen = pop.create("element", false):setSize(graphics.getWidth(), graphics.getHeight())
|
||||
return print("created \"pop.screen\"")
|
||||
end
|
||||
@ -62,9 +89,14 @@ pop.create = function(element, parent, ...)
|
||||
if parent == nil then
|
||||
parent = pop.screen
|
||||
end
|
||||
element = pop.elements[element](pop, parent, ...)
|
||||
if parent then
|
||||
if inheritsFromElement(parent) then
|
||||
element = pop.elements[element](parent, ...)
|
||||
insert(parent.child, element)
|
||||
elseif parent == false then
|
||||
element = pop.elements[element](false, ...)
|
||||
else
|
||||
element = pop.elements[element](pop.screen, parent, ...)
|
||||
insert(pop.screen.child, element)
|
||||
end
|
||||
return element
|
||||
end
|
||||
@ -94,19 +126,62 @@ pop.draw = function(element)
|
||||
end
|
||||
end
|
||||
end
|
||||
pop.mousemoved = function(self, x, y, dx, dy)
|
||||
if pop.focused and pop.focused.mousemoved then
|
||||
return pop.focused:mousemoved(x, y, dx, dy)
|
||||
end
|
||||
return false
|
||||
end
|
||||
pop.mousepressed = function(x, y, button, element)
|
||||
if element == nil then
|
||||
if not (element) then
|
||||
print("mousepressed", x, y, button)
|
||||
element = pop.screen
|
||||
end
|
||||
print("mousepressed", x, y, button, element)
|
||||
return false
|
||||
local handled = false
|
||||
if (x >= element.x) and (x <= element.x + element.w) and (y >= element.y) and (y <= element.y + element.h) then
|
||||
if element.mousepressed then
|
||||
handled = element:mousepressed(x - element.x, y - element.y, button)
|
||||
end
|
||||
pop.mousereleased = function(x, y, button, element)
|
||||
if element == nil then
|
||||
element = pop.screen
|
||||
if handled then
|
||||
pop.focused = element
|
||||
pop.events[button] = element
|
||||
else
|
||||
for i = 1, #element.child do
|
||||
handled = pop.mousepressed(x, y, button, element.child[i])
|
||||
if handled then
|
||||
break
|
||||
end
|
||||
print("mousereleased", x, y, button, element)
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
return handled
|
||||
end
|
||||
pop.mousereleased = function(x, y, button)
|
||||
print("mousereleased", x, y, button)
|
||||
local clickedHandled = false
|
||||
local mousereleasedHandled = false
|
||||
do
|
||||
local element = pop.events[button]
|
||||
if element then
|
||||
if element.clicked and (x >= element.x) and (x <= element.x + element.w) and (y >= element.y) and (y <= element.y + element.h) then
|
||||
do
|
||||
clickedHandled = element:clicked(x - element.x, y - element.y, button)
|
||||
if clickedHandled then
|
||||
pop.events[button] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
if element.mousereleased then
|
||||
do
|
||||
mousereleasedHandled = element:mousereleased(x - element.x, y - element.y, button)
|
||||
if mousereleasedHandled then
|
||||
pop.events[button] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return clickedHandled, mousereleasedHandled
|
||||
end
|
||||
pop.keypressed = function(key)
|
||||
print("keypressed", key)
|
||||
|
19
demo/pop/util.lua
Normal file
19
demo/pop/util.lua
Normal file
@ -0,0 +1,19 @@
|
||||
local inheritsFromElement
|
||||
inheritsFromElement = function(object)
|
||||
if object and object.__class then
|
||||
local cls = object.__class
|
||||
if cls.__name == "element" then
|
||||
return true
|
||||
end
|
||||
while cls.__parent do
|
||||
cls = cls.__parent
|
||||
if cls.__name == "element" then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
return {
|
||||
inheritsFromElement = inheritsFromElement
|
||||
}
|
BIN
demo/test.ogv
Normal file
BIN
demo/test.ogv
Normal file
Binary file not shown.
BIN
demo/test.png
Normal file
BIN
demo/test.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 355 B |
15
docs/Drawables.md
Normal file
15
docs/Drawables.md
Normal file
@ -0,0 +1,15 @@
|
||||
# Supported Drawables
|
||||
|
||||
Pop.Box supports three [Drawables][1]: Canvas, Image, and Video.
|
||||
|
||||
**Note**: Video and Canvas support are untested.
|
||||
|
||||
Additionally, in the place of a Drawable, you can use `false` to not render
|
||||
anything, or a table of color values. The color values should be in the format
|
||||
LÖVE uses (`{red, green, blue, alpha}`, see [love.graphics.setColor][2]).
|
||||
|
||||
(The alpha value is optional and will default to `255`, but not using an alpha
|
||||
is likely to mess up your rendering if an alpha value is used *anywhere else*.)
|
||||
|
||||
[1]: https://love2d.org/wiki/Drawable
|
||||
[2]: https://love2d.org/wiki/love.graphics.setColor
|
31
docs/Elements.md
Normal file
31
docs/Elements.md
Normal file
@ -0,0 +1,31 @@
|
||||
# Elements
|
||||
|
||||
Elements are the core of Pop.Box.
|
||||
|
||||
Once `pop` has been required, you can create Elements and interact with them.
|
||||
Most elements can be created like this: `local box = pop.box(...)`
|
||||
|
||||
However, if an element's name clashes with a function name used in Pop.Box, you
|
||||
will have to use `pop.create(type, ...)` where `type` is a string naming the
|
||||
element type. (No standard elements do this.)
|
||||
|
||||
When creating an element, the first argument is its parent element. If the first
|
||||
argument is not an element, it will be treated as the second argument. If it is
|
||||
`false`, then an element with no parent will be created.
|
||||
|
||||
When no parent is specified, an element's parent is `pop.screen`, which is the
|
||||
top-level element of Pop.Box. (This behavior can be modified by custom elements,
|
||||
so check their documentation.)
|
||||
|
||||
## Available Elements
|
||||
|
||||
- [Element][1] (The base of all elements, and useful for alignment.)
|
||||
- [Box][2] (A box, can be colored, or display a [supported Drawable][3].)
|
||||
- [Text][4] (Plain text, no special features. Useful for basic labels and such.)
|
||||
- [Window][5] (A moveable window. Has a title and area for other elements.)
|
||||
|
||||
[1]: ./elements/element.md
|
||||
[2]: ./elements/box.md
|
||||
[3]: ./Drawables.md
|
||||
[4]: ./elements/text.md
|
||||
[5]: ./elements/window.md
|
14
docs/Extensions.md
Normal file
14
docs/Extensions.md
Normal file
@ -0,0 +1,14 @@
|
||||
# Extensions
|
||||
|
||||
Extensions are simply a way for custom code to be run after loading elements and
|
||||
skins. Simply place a `.lua` file in the `extensions` directory, and it will be
|
||||
required.
|
||||
|
||||
## Standard Extensions
|
||||
|
||||
There is only one standard extension, which modifies element classes to add a
|
||||
more convenient getter/setter method to most get/set methods. For example,
|
||||
instead of `element:getSize()`, just call `element:size()`. Instead of
|
||||
`element:setSize(w, h)`, call `element:size(w, h)`.
|
||||
|
||||
This is mostly for a demo of what can be possible, but also might be useful.
|
54
docs/Pop.md
Normal file
54
docs/Pop.md
Normal file
@ -0,0 +1,54 @@
|
||||
# Pop Module
|
||||
|
||||
This is the main module that allows you to access everything else in Pop.Box.
|
||||
Simply require it (`local pop = require "pop"`) and define LÖVE callbacks for:
|
||||
|
||||
- `pop.update(dt)`
|
||||
- `pop.draw()`
|
||||
- `pop.mousemoved(x, y, dx, dy)` (when using LÖVE 0.10.0 or later)
|
||||
- `pop.mousepressed(x, y, button)`
|
||||
- `pop.mousereleased(x, y, button)`
|
||||
- `pop.keypressed(key)`
|
||||
- `pop.keyreleased(key)`
|
||||
- `pop.textinput(text)`
|
||||
|
||||
Every callback returns `true`/`false` for whether or not the event was handled.
|
||||
For example, using the `mousepressed` event handler:
|
||||
|
||||
```lua
|
||||
function love.mousepressed(x, y, button)
|
||||
local handled = pop.mousepressed(x, y, button)
|
||||
if not handled then
|
||||
-- do something useful
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
## Creating Elements
|
||||
|
||||
Once `pop` has been required, you can create [Elements][1] and interact with
|
||||
them. Most elements can be created like this: `local box = pop.box(...)`
|
||||
|
||||
For more information, see the [Elements documentation][1].
|
||||
|
||||
## Skinning Elements
|
||||
|
||||
See the [Skins][2] documentation.
|
||||
|
||||
## Custom Elements/Skins/Extensions
|
||||
|
||||
Any `.lua` file placed in the `elements`, `skins`, and `extensions` directories
|
||||
within the module will be loaded and available as appropriate. See the
|
||||
documentation on each for how to make them:
|
||||
|
||||
- [Elements][1]
|
||||
- [Skins][2]
|
||||
- [Extensions][3]
|
||||
|
||||
Also of use, there is a separate set of docs about how Pop.Box works under the
|
||||
surface: [Pop Module (dev)][4]
|
||||
|
||||
[1]: ./Elements.md
|
||||
[2]: ./Skins.md
|
||||
[3]: ./Extensions.md
|
||||
[4]: ./dev/Pop.md
|
19
docs/Skins.md
Normal file
19
docs/Skins.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Skins
|
||||
|
||||
**Note**: This system is mostly an after-thought right now, and will probably
|
||||
be replaced with something else entirely.
|
||||
|
||||
Skins are simple tables containing information to style a variety of elements.
|
||||
Use `pop.skin()` to apply a skin to an element and its children (see
|
||||
[Pop Module][3] documentation). Skins are loaded from the `skins` directory.
|
||||
|
||||
- `color` - A table of RGBA values (see [love.graphics.setColor][2]), used as a
|
||||
foreground color (currently for `text` elements only).
|
||||
- `background` - A [supported Drawable][4], used for backgrounds (currently
|
||||
used on `box` elements only).
|
||||
- `font` - A [Font][5].
|
||||
|
||||
[2]: https://love2d.org/wiki/love.graphics.setColor
|
||||
[3]: ./Pop.md
|
||||
[4]: ./Drawables.md
|
||||
[5]: https://love2d.org/wiki/Font
|
8
docs/dev/Pop.md
Normal file
8
docs/dev/Pop.md
Normal file
@ -0,0 +1,8 @@
|
||||
# Pop Module (dev)
|
||||
|
||||
(This document focuses on the structure and code of Pop.Box, not how to use it.
|
||||
See the [regular documentation][1] for that.)
|
||||
|
||||
TODO: Write me.
|
||||
|
||||
[1]: ../Pop.md
|
17
docs/elements/box.md
Normal file
17
docs/elements/box.md
Normal file
@ -0,0 +1,17 @@
|
||||
# box
|
||||
|
||||
The box element is a rectangle that has a [supported Drawable][1] as its
|
||||
background.
|
||||
|
||||
## Methods
|
||||
|
||||
- `setBackground(background)` Using a supported Drawable (see above), set the
|
||||
background.
|
||||
- `getBackground()` Returns the background in use.
|
||||
- `setColor(red, green, blue, alpha)` Sets the background to the specified
|
||||
color. `alpha` is optional and defaults to `255`. Alternately, pass a table of
|
||||
color values (ex: `{red, green, blue, alpha}`).
|
||||
- `getColor()` Returns red, green, blue, and alpha color values of background.
|
||||
Errors if the background is not a color.
|
||||
|
||||
[1]: ../Drawables.md
|
53
docs/elements/element.md
Normal file
53
docs/elements/element.md
Normal file
@ -0,0 +1,53 @@
|
||||
# element
|
||||
|
||||
This is the base of all elements, and useful for alignment purposes. It is also
|
||||
the element type used for `pop.screen` (the top-level element of Pop.Box). All
|
||||
methods here are available on all other elements (any differences are noted on
|
||||
their documentation pages).
|
||||
|
||||
## Alignment
|
||||
|
||||
All elements have a `horizontal` and `vertical` alignment property. These modify
|
||||
how elements are aligned and how positions are handled. For example, an element
|
||||
aligned to the top-right will return the position of the top-right corner when
|
||||
calling `getPosition()`.
|
||||
|
||||
- `horizontal` can be `left`, `center`, or `right`. Defaults to `left`.
|
||||
- `vertical` can be `top`, `center`, or `bottom`. Defaults to `top`.
|
||||
|
||||
## Methods
|
||||
|
||||
- `addChild(child)` Adds a child element.
|
||||
- `getChildren()` Returns a numerically indexed table of child elements.
|
||||
- `move(x, y)` Moves the element (and its children) by specified values.
|
||||
Parameters optional.
|
||||
- `setPosition(x, y)` Sets position of the element (and its children) based on
|
||||
the alignment of the element. Parameters optional.
|
||||
- `getPosition()` Returns x/y position of the element based on its alignment.
|
||||
- `setSize(w, h)` Sets the width/height of the element, element keeps "in-place"
|
||||
based on its alignment. (For example, a right-aligned element will grow to the
|
||||
left.) Parameters optional.
|
||||
- `getSize()` Returns the width/height of the element.
|
||||
- `setWidth(w)` Sets the width of the element. Element stays "in-place" based on
|
||||
its alignment.
|
||||
- `getWidth()` Returns the width of the element.
|
||||
- `setHeight(h)` Sets the height of the element. Element stays "in-place" based
|
||||
on its alignment.
|
||||
- `getHeight()` Returns the height of the element.
|
||||
- `adjustSize(w, h)` Grows the element by a relative width/height. Element stays
|
||||
"in-place" based on its alignment.
|
||||
- `align(horizontal, vertical, toPixel)` Aligns the element based on its margin
|
||||
and parent. `toPixel` is a boolean for pixel-perfect alignment, defaulting to
|
||||
true. See above section about alignment for valid values of `horizontal` and
|
||||
`vertical`. A parent element is required for this method.
|
||||
- `alignTo(element, horizontal, vertical, toPixel)` Works just like `align()`,
|
||||
except that alignment is based on a specific element instead of the parent.
|
||||
Does not require a parent element.
|
||||
- `setAlignment(horizontal, vertical)` Sets alignment values on the element
|
||||
*without* moving the element.
|
||||
- `getAlignment()` Returns the `horizontal` and `vertical` alignment of the
|
||||
element.
|
||||
- `setMargin(m)` Sets a margin to be used when aligning the element.
|
||||
- `getMargin()` Returns the current margin value.
|
||||
- `fill()` Resizes and aligns the element to fill its parent's area, with the
|
||||
element's margin taken into account on all sides.
|
22
docs/elements/text.md
Normal file
22
docs/elements/text.md
Normal file
@ -0,0 +1,22 @@
|
||||
# text
|
||||
|
||||
The text element is plain text in one color. Nothing special.
|
||||
|
||||
(**Note**: Other, more advanced text elements are planned, with support for
|
||||
things like line-wrapping and custom coloring and formatting of text.)
|
||||
|
||||
## Methods
|
||||
|
||||
- `setSize()` Unlike other elements, a size cannot be set. If this is called, it
|
||||
will fix the size of the text if it somehow was modified incorrectly.
|
||||
- `setWidth()` Width cannot be set. If called, will fix the size of the text.
|
||||
- `setHeight()` Height cannot be set. If called, will fix the size of the text.
|
||||
- `setText(text)` Sets the text of the element. Will resize element to fit text.
|
||||
Newlines are supported. Defaults to an empty string.
|
||||
- `getText()` Returns the text of the element.
|
||||
- `setFont()` Sets the font to be used on this element. Will resize to fit the
|
||||
text and font.
|
||||
- `setColor(red, green, blue, alpha)` Sets color of text. `alpha` is optional
|
||||
and defaults to `255`. Alternately, pass a table of color values (ex: `{red,
|
||||
green, blue, alpha}`).
|
||||
- `getColor()` Returns red, green, blue, and alpha values of color.
|
4
docs/elements/window.md
Normal file
4
docs/elements/window.md
Normal file
@ -0,0 +1,4 @@
|
||||
# window
|
||||
|
||||
Documentation has not been written yet, as this element is still under heavy
|
||||
development.
|
34
dummy/main.lua
Normal file
34
dummy/main.lua
Normal file
@ -0,0 +1,34 @@
|
||||
local lg = love.graphics
|
||||
local pop, parts
|
||||
|
||||
-- pretend parts has been defined
|
||||
|
||||
function love.load()
|
||||
pop = require "lib.pop"
|
||||
local width4 = lg.getWidth()/4
|
||||
local height2 = lg.getHeight()/2
|
||||
local PartList = pop.scrollbox():setSize(width4, height2)--:setSizeControl(true) --defaults to true
|
||||
local PartInfo = pop.scrollbox():setSize(width4, height2):move(nil, height2)
|
||||
local CraftInfo = pop.box():setSize(width4, height2):move(lg.getWidth()*3/4)
|
||||
local columns = math.floor(PartList:getWidth()/128)
|
||||
local rows = math.floor(#parts/columns)
|
||||
local grid = pop.grid(PartList, columns, rows)
|
||||
for i = 1, #parts do
|
||||
-- pretend that parts.gui is a box designed to fix in here properly
|
||||
grid:add(parts[i].gui) -- pretend by default, adding something to a grid like this adds it to first available spot
|
||||
-- also, grids auto-resize their children
|
||||
end
|
||||
PartList:add(grid) -- BULLSHIT ?!
|
||||
end
|
||||
|
||||
-- parts.gui is something like this:
|
||||
|
||||
gui = pop.box(newImage()) -- assumes a box can take 'userdata' as first arg and know it is an image
|
||||
gui.clicked = function(x, y, button)
|
||||
-- don't care about x/y
|
||||
if button == "l" then --left
|
||||
selected = gui.partReference -- or something
|
||||
elseif button == "r" then --right
|
||||
displayPartInfo() -- something happens to display it in the proper spot
|
||||
end
|
||||
end
|
@ -21,6 +21,7 @@ do
|
||||
local w, h = self.background:getDimensions()
|
||||
w = self.w / w
|
||||
h = self.h / h
|
||||
graphics.setColor(255, 255, 255, 255)
|
||||
graphics.draw(self.background, self.x, self.y, 0, w, h)
|
||||
end
|
||||
end
|
||||
@ -70,11 +71,13 @@ do
|
||||
_base_0.__index = _base_0
|
||||
setmetatable(_base_0, _parent_0.__base)
|
||||
_class_0 = setmetatable({
|
||||
__init = function(self, pop, parent, background)
|
||||
__init = function(self, parent, background)
|
||||
if background == nil then
|
||||
background = false
|
||||
end
|
||||
_class_0.__parent.__init(self, pop, parent)
|
||||
_class_0.__parent.__init(self, parent)
|
||||
self.w = 20
|
||||
self.h = 20
|
||||
self.background = background
|
||||
end,
|
||||
__base = _base_0,
|
||||
|
@ -16,6 +16,14 @@ do
|
||||
graphics.print("e", self.x, self.y)
|
||||
return self
|
||||
end,
|
||||
addChild = function(self, child)
|
||||
self.child[#self.child + 1] = child
|
||||
child.parent = self
|
||||
return self
|
||||
end,
|
||||
getChildren = function(self)
|
||||
return self.child
|
||||
end,
|
||||
move = function(self, x, y)
|
||||
if x then
|
||||
self.x = self.x + x
|
||||
@ -105,6 +113,32 @@ do
|
||||
getSize = function(self)
|
||||
return self.w, self.h
|
||||
end,
|
||||
setWidth = function(self, w)
|
||||
local _exp_0 = self.horizontal
|
||||
if "center" == _exp_0 then
|
||||
self.x = self.x - ((w - self.w) / 2)
|
||||
elseif "right" == _exp_0 then
|
||||
self.x = self.x - (w - self.w)
|
||||
end
|
||||
self.w = w
|
||||
return self
|
||||
end,
|
||||
getWidth = function(self)
|
||||
return self.w
|
||||
end,
|
||||
setHeight = function(self, h)
|
||||
local _exp_0 = self.vertical
|
||||
if "center" == _exp_0 then
|
||||
self.y = self.y - ((h - self.h) / 2)
|
||||
elseif "bottom" == _exp_0 then
|
||||
self.y = self.y - (h - self.h)
|
||||
end
|
||||
self.h = h
|
||||
return self
|
||||
end,
|
||||
getHeight = function(self)
|
||||
return self.h
|
||||
end,
|
||||
adjustSize = function(self, w, h)
|
||||
local W, H = self:getSize()
|
||||
if w then
|
||||
@ -136,7 +170,7 @@ do
|
||||
elseif "bottom" == _exp_1 then
|
||||
self.y = self.y + (self.parent.h - self.h - self.margin)
|
||||
end
|
||||
if toPixel then
|
||||
if toPixel or (toPixel == nil) then
|
||||
self.x = floor(self.x)
|
||||
self.y = floor(self.y)
|
||||
end
|
||||
@ -158,6 +192,9 @@ do
|
||||
end
|
||||
return self
|
||||
end,
|
||||
getAlignment = function(self)
|
||||
return self.horizontal, self.vertical
|
||||
end,
|
||||
setMargin = function(self, margin)
|
||||
self.margin = margin
|
||||
self:align()
|
||||
@ -165,25 +202,31 @@ do
|
||||
end,
|
||||
getMargin = function(self)
|
||||
return self.margin
|
||||
end,
|
||||
fill = function(self)
|
||||
self.x = self.parent.x + self.margin
|
||||
self.y = self.parent.y + self.margin
|
||||
self.w = self.parent.w - self.margin * 2
|
||||
self.h = self.parent.h - self.margin * 2
|
||||
end
|
||||
}
|
||||
_base_0.__index = _base_0
|
||||
_class_0 = setmetatable({
|
||||
__init = function(self, pop, parent)
|
||||
__init = function(self, parent)
|
||||
self.parent = parent
|
||||
self.child = { }
|
||||
self.w = 0
|
||||
self.h = 0
|
||||
self.margin = 0
|
||||
if parent then
|
||||
self.x = parent.x or 0
|
||||
self.y = parent.y or 0
|
||||
self.x = parent.x
|
||||
self.y = parent.y
|
||||
else
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
end
|
||||
self.w = 10
|
||||
self.h = 10
|
||||
self.horizontal = "left"
|
||||
self.vertical = "top"
|
||||
self.margin = 0
|
||||
end,
|
||||
__base = _base_0,
|
||||
__name = "element"
|
||||
|
@ -12,19 +12,10 @@ do
|
||||
local _class_0
|
||||
local _parent_0 = element
|
||||
local _base_0 = {
|
||||
wrap = function(pop)
|
||||
return function(parent, ...)
|
||||
if type(parent) == "string" then
|
||||
return pop.create("text", nil, parent, ...)
|
||||
else
|
||||
return pop.create("text", parent, ...)
|
||||
end
|
||||
end
|
||||
end,
|
||||
draw = function(self)
|
||||
graphics.setColor(self.color)
|
||||
graphics.setFont(self.font)
|
||||
graphics.print(self.text, self.x, self.y)
|
||||
graphics.print(self.txt, self.x, self.y)
|
||||
return self
|
||||
end,
|
||||
debugDraw = function(self)
|
||||
@ -38,8 +29,8 @@ do
|
||||
return self
|
||||
end,
|
||||
setSize = function(self)
|
||||
local w = self.font:getWidth(self.text)
|
||||
local h = self.font:getHeight() * (select(2, self.text:gsub("\n", "\n")) + 1)
|
||||
local w = self.font:getWidth(self.txt)
|
||||
local h = self.font:getHeight() * (select(2, self.txt:gsub("\n", "\n")) + 1)
|
||||
local _exp_0 = self.horizontal
|
||||
if "center" == _exp_0 then
|
||||
self.x = self.x - ((w - self.w) / 2)
|
||||
@ -56,16 +47,24 @@ do
|
||||
self.h = h
|
||||
return self
|
||||
end,
|
||||
setWidth = function(self)
|
||||
self:setSize()
|
||||
return self
|
||||
end,
|
||||
setHeight = function(self)
|
||||
self:setSize()
|
||||
return self
|
||||
end,
|
||||
setText = function(self, text)
|
||||
if text == nil then
|
||||
text = ""
|
||||
end
|
||||
self.text = text
|
||||
self.txt = text
|
||||
self:setSize()
|
||||
return self
|
||||
end,
|
||||
getText = function(self)
|
||||
return self.text
|
||||
return self.txt
|
||||
end,
|
||||
setFont = function(self, font)
|
||||
self.font = font
|
||||
@ -98,7 +97,7 @@ do
|
||||
_base_0.__index = _base_0
|
||||
setmetatable(_base_0, _parent_0.__base)
|
||||
_class_0 = setmetatable({
|
||||
__init = function(self, pop, parent, text, color)
|
||||
__init = function(self, parent, text, color)
|
||||
if text == nil then
|
||||
text = ""
|
||||
end
|
||||
@ -110,7 +109,7 @@ do
|
||||
255
|
||||
}
|
||||
end
|
||||
_class_0.__parent.__init(self, pop, parent)
|
||||
_class_0.__parent.__init(self, parent)
|
||||
self.font = graphics.newFont(14)
|
||||
self:setText(text)
|
||||
self.color = color
|
||||
@ -137,6 +136,16 @@ do
|
||||
end
|
||||
})
|
||||
_base_0.__class = _class_0
|
||||
local self = _class_0
|
||||
self.wrap = function(pop)
|
||||
return function(parent, ...)
|
||||
if type(parent) == "string" then
|
||||
return pop.create("text", nil, parent, ...)
|
||||
else
|
||||
return pop.create("text", parent, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
if _parent_0.__inherited then
|
||||
_parent_0.__inherited(_parent_0, _class_0)
|
||||
end
|
||||
|
251
lib/pop/elements/window.lua
Normal file
251
lib/pop/elements/window.lua
Normal file
@ -0,0 +1,251 @@
|
||||
local graphics
|
||||
graphics = love.graphics
|
||||
local sub, len
|
||||
do
|
||||
local _obj_0 = string
|
||||
sub, len = _obj_0.sub, _obj_0.len
|
||||
end
|
||||
local path = sub(..., 1, len(...) - len("/window"))
|
||||
local element = require(tostring(path) .. "/element")
|
||||
local box = require(tostring(path) .. "/box")
|
||||
local text = require(tostring(path) .. "/text")
|
||||
local left = 1
|
||||
local mousemoved_event = true
|
||||
do
|
||||
local major, minor, revision = love.getVersion()
|
||||
if (major == 0) and (minor == 10) and ((revision == 0) or (revision == 1)) then
|
||||
left = 1
|
||||
elseif (major == 0) and (minor == 9) then
|
||||
left = "l"
|
||||
if revision == 1 then
|
||||
mousemoved_event = false
|
||||
end
|
||||
else
|
||||
print("elements/window: unrecognized LÖVE version: " .. tostring(major) .. "." .. tostring(minor) .. "." .. tostring(revision))
|
||||
print(" assuming LÖVE version > 0.10.1 (there may be bugs)")
|
||||
end
|
||||
end
|
||||
local pop_ref = false
|
||||
local window
|
||||
do
|
||||
local _class_0
|
||||
local _parent_0 = element
|
||||
local _base_0 = {
|
||||
load = function(pop)
|
||||
pop_ref = pop
|
||||
end,
|
||||
debugDraw = function(self)
|
||||
graphics.setLineWidth(0.5)
|
||||
graphics.setColor(0, 0, 0, 100)
|
||||
graphics.rectangle("fill", self.x, self.y, self.w, self.h)
|
||||
graphics.setColor(200, 0, 200, 200)
|
||||
graphics.rectangle("line", self.x, self.y, self.w, self.h)
|
||||
graphics.setColor(255, 200, 255, 255)
|
||||
graphics.print("w", self.x, self.y)
|
||||
return self
|
||||
end,
|
||||
addChild = function(self, child)
|
||||
self.window.child[#self.window.child + 1] = child
|
||||
child.parent = self.window
|
||||
return self
|
||||
end,
|
||||
getChildren = function(self)
|
||||
return self.window.child
|
||||
end,
|
||||
align = function(self, horizontal, vertical, toPixel)
|
||||
_class_0.__parent.__base.align(self, horizontal, vertical, toPixel)
|
||||
for i = 1, #self.child do
|
||||
self.child[i]:align()
|
||||
end
|
||||
self.window:move(nil, self.head:getHeight())
|
||||
return self
|
||||
end,
|
||||
setSize = function(self, w, h)
|
||||
local x = 0
|
||||
local y = 0
|
||||
if w then
|
||||
local _exp_0 = self.horizontal
|
||||
if "center" == _exp_0 then
|
||||
x = x - ((w - self.w) / 2)
|
||||
elseif "right" == _exp_0 then
|
||||
x = x - (w - self.w)
|
||||
end
|
||||
self.head:setWidth(w)
|
||||
self.window:setWidth(w)
|
||||
self.w = w
|
||||
self.x = self.x + x
|
||||
self.title:align()
|
||||
end
|
||||
if h then
|
||||
h = h - self.head:getHeight()
|
||||
local _exp_0 = self.vertical
|
||||
if "center" == _exp_0 then
|
||||
y = y - ((h - self.h) / 2)
|
||||
elseif "right" == _exp_0 then
|
||||
y = y - (h - self.h)
|
||||
end
|
||||
self.window:setHeight(h)
|
||||
self.h = h + self.head:getHeight()
|
||||
self.y = self.y + y
|
||||
end
|
||||
self.head:move(x, y)
|
||||
self.window:move(x, y)
|
||||
return self
|
||||
end,
|
||||
setWidth = function(self, w)
|
||||
local x = 0
|
||||
local _exp_0 = self.horizontal
|
||||
if "center" == _exp_0 then
|
||||
x = x - ((w - self.w) / 2)
|
||||
elseif "right" == _exp_0 then
|
||||
x = x - (w - self.w)
|
||||
end
|
||||
self.head:setWidth(w)
|
||||
self.window:setWidth(w)
|
||||
self.w = w
|
||||
self.x = self.x + x
|
||||
self.title:align()
|
||||
self.head:move(x)
|
||||
self.window:move(x)
|
||||
return self
|
||||
end,
|
||||
setHeight = function(self, h)
|
||||
local y = 0
|
||||
h = h - self.head:getHeight()
|
||||
local _exp_0 = self.vertical
|
||||
if "center" == _exp_0 then
|
||||
y = y - ((h - self.h) / 2)
|
||||
elseif "right" == _exp_0 then
|
||||
y = y - (h - self.h)
|
||||
end
|
||||
self.window:setHeight(h)
|
||||
self.h = h + self.head:getHeight()
|
||||
self.y = self.y + y
|
||||
self.head:move(nil, y)
|
||||
self.title:move(nil, y)
|
||||
self.window:move(nil, y)
|
||||
return self
|
||||
end,
|
||||
setTitle = function(self, title)
|
||||
self.title:setText(title)
|
||||
return self
|
||||
end
|
||||
}
|
||||
_base_0.__index = _base_0
|
||||
setmetatable(_base_0, _parent_0.__base)
|
||||
_class_0 = setmetatable({
|
||||
__init = function(self, parent, title, tBackground, tColor, wBackground)
|
||||
if title == nil then
|
||||
title = "window"
|
||||
end
|
||||
if tBackground == nil then
|
||||
tBackground = {
|
||||
25,
|
||||
180,
|
||||
230,
|
||||
255
|
||||
}
|
||||
end
|
||||
if tColor == nil then
|
||||
tColor = {
|
||||
255,
|
||||
255,
|
||||
255,
|
||||
255
|
||||
}
|
||||
end
|
||||
if wBackground == nil then
|
||||
wBackground = {
|
||||
200,
|
||||
200,
|
||||
210,
|
||||
255
|
||||
}
|
||||
end
|
||||
_class_0.__parent.__init(self, parent)
|
||||
self.head = box(self, tBackground)
|
||||
self.title = text(self, title, tColor)
|
||||
self.window = box(self, wBackground)
|
||||
local height = self.title:getHeight()
|
||||
self.head:setSize(self.w, height)
|
||||
self.window:move(nil, height)
|
||||
self:setSize(100, 80)
|
||||
self.child = {
|
||||
self.head,
|
||||
self.title,
|
||||
self.window
|
||||
}
|
||||
self.head.selected = false
|
||||
if mousemoved_event then
|
||||
self.head.mousemoved = function(self, x, y, dx, dy)
|
||||
if self.selected then
|
||||
self.parent:move(y, dx)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
self.head.mousepressed = function(self, x, y, button)
|
||||
if button == left then
|
||||
self.selected = true
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
self.head.mousereleased = function(self, x, y, button)
|
||||
if button == left then
|
||||
self.selected = false
|
||||
pop_ref.focused = false
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
else
|
||||
self.head.mx = 0
|
||||
self.head.my = 0
|
||||
self.head.update = function(self)
|
||||
return false
|
||||
end
|
||||
self.head.mousepressed = function(self, x, y, button)
|
||||
if button == left then
|
||||
self.selected = true
|
||||
self.mx = x
|
||||
self.my = y
|
||||
end
|
||||
end
|
||||
self.head.mousereleased = function(self, x, y, button)
|
||||
if button == left then
|
||||
self.selected = false
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
end,
|
||||
__base = _base_0,
|
||||
__name = "window",
|
||||
__parent = _parent_0
|
||||
}, {
|
||||
__index = function(cls, name)
|
||||
local val = rawget(_base_0, name)
|
||||
if val == nil then
|
||||
local parent = rawget(cls, "__parent")
|
||||
if parent then
|
||||
return parent[name]
|
||||
end
|
||||
else
|
||||
return val
|
||||
end
|
||||
end,
|
||||
__call = function(cls, ...)
|
||||
local _self_0 = setmetatable({}, _base_0)
|
||||
cls.__init(_self_0, ...)
|
||||
return _self_0
|
||||
end
|
||||
})
|
||||
_base_0.__class = _class_0
|
||||
if _parent_0.__inherited then
|
||||
_parent_0.__inherited(_parent_0, _class_0)
|
||||
end
|
||||
window = _class_0
|
||||
return _class_0
|
||||
end
|
51
lib/pop/extensions/streamlined_get_set.lua
Normal file
51
lib/pop/extensions/streamlined_get_set.lua
Normal file
@ -0,0 +1,51 @@
|
||||
local graphics
|
||||
graphics = love.graphics
|
||||
local sub, len
|
||||
do
|
||||
local _obj_0 = string
|
||||
sub, len = _obj_0.sub, _obj_0.len
|
||||
end
|
||||
local path = sub(..., 1, len(...) - len("/extensions/streamlined_get_set"))
|
||||
local element = require(tostring(path) .. "/elements/element")
|
||||
element.__base.position = function(self, x, y)
|
||||
if x or y then
|
||||
return self:setPosition(x, y)
|
||||
else
|
||||
return self:getPosition()
|
||||
end
|
||||
end
|
||||
element.__base.size = function(self, w, h)
|
||||
if w or h then
|
||||
return self:setSize(w, h)
|
||||
else
|
||||
return self:getSize()
|
||||
end
|
||||
end
|
||||
element.__base.width = function(self, w)
|
||||
if w then
|
||||
return self:setWidth(w)
|
||||
else
|
||||
return self:getWidth()
|
||||
end
|
||||
end
|
||||
element.__base.height = function(self, h)
|
||||
if h then
|
||||
return self:setHeight(h)
|
||||
else
|
||||
return self:getHeight()
|
||||
end
|
||||
end
|
||||
element.__base.alignment = function(self, horizontal, vertical)
|
||||
if horizontal or vertical then
|
||||
return self:setAlignment(horizontal, vertical)
|
||||
else
|
||||
return self:getAlignment()
|
||||
end
|
||||
end
|
||||
element.__base.margin = function(self, m)
|
||||
if m then
|
||||
return self:setMargin(m)
|
||||
else
|
||||
return self:getMargin()
|
||||
end
|
||||
end
|
@ -1,3 +1,6 @@
|
||||
if not (love.getVersion) then
|
||||
error("Pop.Box only supports LÖVE versions >= 0.9.1")
|
||||
end
|
||||
local filesystem, graphics
|
||||
do
|
||||
local _obj_0 = love
|
||||
@ -5,11 +8,15 @@ do
|
||||
end
|
||||
local insert
|
||||
insert = table.insert
|
||||
local inheritsFromElement
|
||||
inheritsFromElement = require(tostring(...) .. "/util").inheritsFromElement
|
||||
local path = ...
|
||||
local pop = { }
|
||||
pop.elements = { }
|
||||
pop.skins = { }
|
||||
pop.events = { }
|
||||
pop.screen = false
|
||||
pop.focused = false
|
||||
pop.load = function()
|
||||
local elements = filesystem.getDirectoryItems(tostring(path) .. "/elements")
|
||||
for i = 1, #elements do
|
||||
@ -21,6 +28,9 @@ pop.load = function()
|
||||
end
|
||||
local name = elements[i]:sub(1, -5)
|
||||
pop.elements[name] = require(tostring(path) .. "/elements/" .. tostring(name))
|
||||
if pop.elements[name].load then
|
||||
pop.elements[name].load(pop)
|
||||
end
|
||||
print("element loaded: \"" .. tostring(name) .. "\"")
|
||||
if not (pop[name]) then
|
||||
if pop.elements[name].wrap then
|
||||
@ -55,6 +65,23 @@ pop.load = function()
|
||||
break
|
||||
end
|
||||
end
|
||||
local extensions = filesystem.getDirectoryItems(tostring(path) .. "/extensions")
|
||||
for i = 1, #extensions do
|
||||
local _continue_0 = false
|
||||
repeat
|
||||
if not (extensions[i]:sub(-4) == ".lua") then
|
||||
_continue_0 = true
|
||||
break
|
||||
end
|
||||
local name = extensions[i]:sub(1, -5)
|
||||
require(tostring(path) .. "/extensions/" .. tostring(name))
|
||||
print("extension loaded: \"" .. tostring(name) .. "\"")
|
||||
_continue_0 = true
|
||||
until true
|
||||
if not _continue_0 then
|
||||
break
|
||||
end
|
||||
end
|
||||
pop.screen = pop.create("element", false):setSize(graphics.getWidth(), graphics.getHeight())
|
||||
return print("created \"pop.screen\"")
|
||||
end
|
||||
@ -62,9 +89,14 @@ pop.create = function(element, parent, ...)
|
||||
if parent == nil then
|
||||
parent = pop.screen
|
||||
end
|
||||
element = pop.elements[element](pop, parent, ...)
|
||||
if parent then
|
||||
if inheritsFromElement(parent) then
|
||||
element = pop.elements[element](parent, ...)
|
||||
insert(parent.child, element)
|
||||
elseif parent == false then
|
||||
element = pop.elements[element](false, ...)
|
||||
else
|
||||
element = pop.elements[element](pop.screen, parent, ...)
|
||||
insert(pop.screen.child, element)
|
||||
end
|
||||
return element
|
||||
end
|
||||
@ -94,19 +126,62 @@ pop.draw = function(element)
|
||||
end
|
||||
end
|
||||
end
|
||||
pop.mousemoved = function(self, x, y, dx, dy)
|
||||
if pop.focused and pop.focused.mousemoved then
|
||||
return pop.focused:mousemoved(x, y, dx, dy)
|
||||
end
|
||||
return false
|
||||
end
|
||||
pop.mousepressed = function(x, y, button, element)
|
||||
if element == nil then
|
||||
if not (element) then
|
||||
print("mousepressed", x, y, button)
|
||||
element = pop.screen
|
||||
end
|
||||
print("mousepressed", x, y, button, element)
|
||||
return false
|
||||
local handled = false
|
||||
if (x >= element.x) and (x <= element.x + element.w) and (y >= element.y) and (y <= element.y + element.h) then
|
||||
if element.mousepressed then
|
||||
handled = element:mousepressed(x - element.x, y - element.y, button)
|
||||
end
|
||||
pop.mousereleased = function(x, y, button, element)
|
||||
if element == nil then
|
||||
element = pop.screen
|
||||
if handled then
|
||||
pop.focused = element
|
||||
pop.events[button] = element
|
||||
else
|
||||
for i = 1, #element.child do
|
||||
handled = pop.mousepressed(x, y, button, element.child[i])
|
||||
if handled then
|
||||
break
|
||||
end
|
||||
print("mousereleased", x, y, button, element)
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
return handled
|
||||
end
|
||||
pop.mousereleased = function(x, y, button)
|
||||
print("mousereleased", x, y, button)
|
||||
local clickedHandled = false
|
||||
local mousereleasedHandled = false
|
||||
do
|
||||
local element = pop.events[button]
|
||||
if element then
|
||||
if element.clicked and (x >= element.x) and (x <= element.x + element.w) and (y >= element.y) and (y <= element.y + element.h) then
|
||||
do
|
||||
clickedHandled = element:clicked(x - element.x, y - element.y, button)
|
||||
if clickedHandled then
|
||||
pop.events[button] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
if element.mousereleased then
|
||||
do
|
||||
mousereleasedHandled = element:mousereleased(x - element.x, y - element.y, button)
|
||||
if mousereleasedHandled then
|
||||
pop.events[button] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return clickedHandled, mousereleasedHandled
|
||||
end
|
||||
pop.keypressed = function(key)
|
||||
print("keypressed", key)
|
||||
|
19
lib/pop/util.lua
Normal file
19
lib/pop/util.lua
Normal file
@ -0,0 +1,19 @@
|
||||
local inheritsFromElement
|
||||
inheritsFromElement = function(object)
|
||||
if object and object.__class then
|
||||
local cls = object.__class
|
||||
if cls.__name == "element" then
|
||||
return true
|
||||
end
|
||||
while cls.__parent do
|
||||
cls = cls.__parent
|
||||
if cls.__name == "element" then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
return {
|
||||
inheritsFromElement = inheritsFromElement
|
||||
}
|
@ -5,8 +5,11 @@ path = sub ..., 1, len(...) - len "/box"
|
||||
element = require "#{path}/element"
|
||||
|
||||
class box extends element
|
||||
new: (pop, parent, background=false) =>
|
||||
super pop, parent
|
||||
new: (parent, background=false) =>
|
||||
super parent
|
||||
|
||||
@w = 20
|
||||
@h = 20
|
||||
|
||||
@background = background
|
||||
|
||||
@ -19,6 +22,7 @@ class box extends element
|
||||
w, h = @background\getDimensions!
|
||||
w = @w / w
|
||||
h = @h / h
|
||||
graphics.setColor 255, 255, 255, 255
|
||||
graphics.draw @background, @x, @y, 0, w, h
|
||||
|
||||
return @
|
||||
|
@ -2,23 +2,29 @@ import graphics from love
|
||||
import floor from math
|
||||
|
||||
class element
|
||||
new: (pop, parent) =>
|
||||
new: (parent) =>
|
||||
@parent = parent
|
||||
@child = {}
|
||||
|
||||
@w = 0
|
||||
@h = 0
|
||||
|
||||
@margin = 0
|
||||
|
||||
if parent
|
||||
@x = parent.x or 0
|
||||
@y = parent.y or 0
|
||||
@x = parent.x
|
||||
@y = parent.y
|
||||
--@horizontal = parent.horizontal
|
||||
--@vertical = parent.vertical
|
||||
--@align!
|
||||
else
|
||||
@x = 0
|
||||
@y = 0
|
||||
|
||||
@w = 10
|
||||
@h = 10
|
||||
--@horizontal = "left"
|
||||
--@vertical = "top"
|
||||
|
||||
@horizontal = "left"
|
||||
@vertical = "top"
|
||||
@margin = 0
|
||||
|
||||
debugDraw: =>
|
||||
graphics.setLineWidth 0.5
|
||||
@ -31,6 +37,15 @@ class element
|
||||
|
||||
return @
|
||||
|
||||
addChild: (child) =>
|
||||
@child[#@child+1] = child
|
||||
child.parent = @
|
||||
|
||||
return @
|
||||
|
||||
getChildren: =>
|
||||
return @child
|
||||
|
||||
move: (x, y) =>
|
||||
if x
|
||||
@x = @x + x
|
||||
@ -117,6 +132,34 @@ class element
|
||||
getSize: =>
|
||||
return @w, @h
|
||||
|
||||
setWidth: (w) =>
|
||||
switch @horizontal
|
||||
when "center"
|
||||
@x -= (w - @w)/2
|
||||
when "right"
|
||||
@x -= w - @w
|
||||
|
||||
@w = w
|
||||
|
||||
return @
|
||||
|
||||
getWidth: =>
|
||||
return @w
|
||||
|
||||
setHeight: (h) =>
|
||||
switch @vertical
|
||||
when "center"
|
||||
@y -= (h - @h)/2
|
||||
when "bottom"
|
||||
@y -= h - @h
|
||||
|
||||
@h = h
|
||||
|
||||
return @
|
||||
|
||||
getHeight: =>
|
||||
return @h
|
||||
|
||||
adjustSize: (w, h) =>
|
||||
W, H = @getSize!
|
||||
|
||||
@ -130,7 +173,7 @@ class element
|
||||
return @
|
||||
|
||||
--TODO note that align requires a parent!
|
||||
align: (horizontal, vertical, toPixel) =>
|
||||
align: (horizontal, vertical, toPixel=true) =>
|
||||
@setAlignment horizontal, vertical
|
||||
|
||||
@x = @parent.x
|
||||
@ -158,11 +201,11 @@ class element
|
||||
|
||||
return @
|
||||
|
||||
alignTo: (element, horizontal, vertical) =>
|
||||
alignTo: (element, horizontal, vertical, toPixel=true) =>
|
||||
parent = @parent
|
||||
@parent = element
|
||||
|
||||
@align horizontal, vertical
|
||||
@align horizontal, vertical, toPixel
|
||||
|
||||
@parent = parent
|
||||
|
||||
@ -176,6 +219,9 @@ class element
|
||||
|
||||
return @
|
||||
|
||||
getAlignment: =>
|
||||
return @horizontal, @vertical
|
||||
|
||||
setMargin: (margin) =>
|
||||
@margin = margin
|
||||
@align!
|
||||
@ -183,3 +229,9 @@ class element
|
||||
|
||||
getMargin: =>
|
||||
return @margin
|
||||
|
||||
fill: =>
|
||||
@x = @parent.x + @margin
|
||||
@y = @parent.y + @margin
|
||||
@w = @parent.w - @margin*2
|
||||
@h = @parent.h - @margin*2
|
||||
|
@ -5,15 +5,16 @@ path = sub ..., 1, len(...) - len "/box"
|
||||
element = require "#{path}/element"
|
||||
|
||||
class text extends element
|
||||
wrap: (pop) ->
|
||||
-- this should be completely unneccessary, but I'm keeping it just in case
|
||||
@wrap = (pop) ->
|
||||
return (parent, ...) ->
|
||||
if type(parent) == "string"
|
||||
return pop.create("text", nil, parent, ...)
|
||||
else
|
||||
return pop.create("text", parent, ...)
|
||||
|
||||
new: (pop, parent, text="", color={255,255,255,255}) =>
|
||||
super pop, parent
|
||||
new: (parent, text="", color={255,255,255,255}) =>
|
||||
super parent
|
||||
|
||||
@font = graphics.newFont 14
|
||||
@setText text
|
||||
@ -22,7 +23,7 @@ class text extends element
|
||||
draw: =>
|
||||
graphics.setColor @color
|
||||
graphics.setFont @font
|
||||
graphics.print @text, @x, @y
|
||||
graphics.print @txt, @x, @y
|
||||
|
||||
return @
|
||||
|
||||
@ -39,8 +40,8 @@ class text extends element
|
||||
|
||||
-- unlike most elements, you cannot set a size for text elements
|
||||
setSize: =>
|
||||
w = @font\getWidth @text
|
||||
h = @font\getHeight! * (select(2, @text\gsub("\n", "\n")) + 1) --hack to get height of multiple lines
|
||||
w = @font\getWidth @txt
|
||||
h = @font\getHeight! * (select(2, @txt\gsub("\n", "\n")) + 1) --hack to get height of multiple lines
|
||||
|
||||
switch @horizontal
|
||||
when "center"
|
||||
@ -59,13 +60,23 @@ class text extends element
|
||||
|
||||
return @
|
||||
|
||||
-- cannot set width!
|
||||
setWidth: =>
|
||||
@setSize!
|
||||
return @
|
||||
|
||||
-- cannot set height!
|
||||
setHeight: =>
|
||||
@setSize!
|
||||
return @
|
||||
|
||||
setText: (text="") =>
|
||||
@text = text
|
||||
@txt = text
|
||||
@setSize!
|
||||
return @
|
||||
|
||||
getText: =>
|
||||
return @text
|
||||
return @txt
|
||||
|
||||
setFont: (font) =>
|
||||
@font = font
|
||||
|
223
src/pop/elements/window.moon
Normal file
223
src/pop/elements/window.moon
Normal file
@ -0,0 +1,223 @@
|
||||
import graphics from love
|
||||
import sub, len from string
|
||||
|
||||
path = sub ..., 1, len(...) - len "/window"
|
||||
element = require "#{path}/element"
|
||||
box = require "#{path}/box"
|
||||
text = require "#{path}/text"
|
||||
|
||||
-- version compatibility
|
||||
left = 1 -- what is the left mouse button?
|
||||
mousemoved_event = true -- is the mousemoved event available?
|
||||
|
||||
do
|
||||
major, minor, revision = love.getVersion!
|
||||
if (major == 0) and (minor == 10) and ((revision == 0) or (revision == 1))
|
||||
left = 1 -- redundant, but whatever
|
||||
elseif (major == 0) and (minor == 9)
|
||||
left = "l"
|
||||
if revision == 1
|
||||
mousemoved_event = false
|
||||
else
|
||||
print "elements/window: unrecognized LOVE version: #{major}.#{minor}.#{revision}"
|
||||
print " assuming LOVE version > 0.10.1 (there may be bugs)"
|
||||
|
||||
pop_ref = false -- reference to pop, loaded by pop.load!
|
||||
|
||||
class window extends element
|
||||
load: (pop) ->
|
||||
pop_ref = pop
|
||||
|
||||
--wrap: (pop) ->
|
||||
-- pop_ref = pop -- set our reference to pop (needed for mouse handling)
|
||||
-- return (...) -> -- standard wrapper, nothing special needed
|
||||
-- return pop.create("window", ...)
|
||||
|
||||
new: (parent, title="window", tBackground={25, 180, 230, 255}, tColor={255, 255, 255, 255}, wBackground={200, 200, 210, 255}) =>
|
||||
super parent
|
||||
|
||||
@head = box @, tBackground -- title box at top
|
||||
@title = text @, title, tColor -- text at top
|
||||
@window = box @, wBackground -- main window area
|
||||
|
||||
-- correct placement / sizes of elements
|
||||
height = @title\getHeight!
|
||||
@head\setSize @w, height
|
||||
@window\move nil, height
|
||||
@setSize 100, 80
|
||||
|
||||
-- our child elements are still child elements
|
||||
--TODO change title to be a child of head ?
|
||||
@child = {
|
||||
@head, @title, @window
|
||||
}
|
||||
|
||||
--@selected = false -- whether or not the window title (and thus, the window) has been selected
|
||||
--NOTE all of these commented out, because I realized these event handlers should be attached to the title element
|
||||
|
||||
@head.selected = false -- whether or not the window title (and thus, the window) has been selected
|
||||
|
||||
if mousemoved_event
|
||||
@head.mousemoved = (x, y, dx, dy) =>
|
||||
if @selected
|
||||
-- for some reason, y and dx are actually dx and dy...what the fuck? (note: in version 0.10.0)
|
||||
@parent\move y, dx --dx, dy
|
||||
return true
|
||||
return false
|
||||
|
||||
@head.mousepressed = (x, y, button) =>
|
||||
if button == left
|
||||
@selected = true
|
||||
return true
|
||||
return false
|
||||
|
||||
@head.mousereleased = (x, y, button) =>
|
||||
if button == left
|
||||
@selected = false
|
||||
pop_ref.focused = false -- clear our focus
|
||||
return true
|
||||
return false
|
||||
|
||||
else
|
||||
@head.mx = 0 -- local mouse coordinates when selected
|
||||
@head.my = 0
|
||||
|
||||
@head.update = =>
|
||||
--TODO write me!
|
||||
return false
|
||||
|
||||
@head.mousepressed = (x, y, button) =>
|
||||
if button == left
|
||||
@selected = true
|
||||
@mx = x
|
||||
@my = y
|
||||
|
||||
@head.mousereleased = (x, y, button) => -- this is actually the same for both versions...
|
||||
if button == left
|
||||
@selected = false
|
||||
return true
|
||||
return false
|
||||
|
||||
debugDraw: =>
|
||||
graphics.setLineWidth 0.5
|
||||
graphics.setColor 0, 0, 0, 100
|
||||
graphics.rectangle "fill", @x, @y, @w, @h
|
||||
graphics.setColor 200, 0, 200, 200
|
||||
graphics.rectangle "line", @x, @y, @w, @h
|
||||
graphics.setColor 255, 200, 255, 255
|
||||
graphics.print "w", @x, @y
|
||||
|
||||
return @
|
||||
|
||||
addChild: (child) =>
|
||||
@window.child[#@window.child+1] = child
|
||||
child.parent = @window
|
||||
|
||||
return @
|
||||
|
||||
getChildren: =>
|
||||
return @window.child
|
||||
|
||||
align: (horizontal, vertical, toPixel) =>
|
||||
super horizontal, vertical, toPixel
|
||||
|
||||
for i = 1, #@child
|
||||
@child[i]\align!
|
||||
|
||||
@window\move nil, @head\getHeight!
|
||||
|
||||
return @
|
||||
|
||||
--update: =>
|
||||
-- if selected, set position based on current mouse position relative to position it was when mousepressed
|
||||
|
||||
--mousemoved: (x, y, dx, dy) =>
|
||||
-- if selected, set position based on new mouse position relative to position it was when mousepressed
|
||||
|
||||
--mousepressed: (x, y, button) =>
|
||||
-- if button == "l" -> selected = true, mouse position saved
|
||||
|
||||
--mousereleased: (x, y, button) =>
|
||||
-- if button == "l" -> set position based on position relative to when mousepressed, selected == false
|
||||
|
||||
setSize: (w, h) =>
|
||||
x = 0
|
||||
y = 0
|
||||
|
||||
if w
|
||||
switch @horizontal
|
||||
when "center"
|
||||
x -= (w - @w)/2
|
||||
when "right"
|
||||
x -= w - @w
|
||||
|
||||
@head\setWidth w
|
||||
@window\setWidth w
|
||||
@w = w
|
||||
@x += x
|
||||
|
||||
@title\align!
|
||||
|
||||
if h
|
||||
h = h - @head\getHeight!
|
||||
switch @vertical
|
||||
when "center"
|
||||
y -= (h - @h)/2
|
||||
when "right"
|
||||
y -= h - @h
|
||||
|
||||
@window\setHeight h
|
||||
@h = h + @head\getHeight!
|
||||
@y += y
|
||||
|
||||
@head\move x, y
|
||||
--@title\move x, y
|
||||
@window\move x, y
|
||||
|
||||
return @
|
||||
|
||||
setWidth: (w) =>
|
||||
x = 0
|
||||
|
||||
switch @horizontal
|
||||
when "center"
|
||||
x -= (w - @w)/2
|
||||
when "right"
|
||||
x -= w - @w
|
||||
|
||||
@head\setWidth w
|
||||
@window\setWidth w
|
||||
@w = w
|
||||
@x += x
|
||||
|
||||
@title\align!
|
||||
|
||||
@head\move x
|
||||
--@title\move x
|
||||
@window\move x
|
||||
|
||||
return @
|
||||
|
||||
setHeight: (h) =>
|
||||
y = 0
|
||||
|
||||
h = h - @head\getHeight!
|
||||
switch @vertical
|
||||
when "center"
|
||||
y -= (h - @h)/2
|
||||
when "right"
|
||||
y -= h - @h
|
||||
|
||||
@window\setHeight h
|
||||
@h = h + @head\getHeight!
|
||||
@y += y
|
||||
|
||||
@head\move nil, y
|
||||
@title\move nil, y
|
||||
@window\move nil, y
|
||||
|
||||
return @
|
||||
|
||||
setTitle: (title) =>
|
||||
@title\setText title
|
||||
return @
|
86
src/pop/extensions/streamlined_get_set.moon
Normal file
86
src/pop/extensions/streamlined_get_set.moon
Normal file
@ -0,0 +1,86 @@
|
||||
-- adds methods to elements using a single function for get and set operations
|
||||
-- ex: instead of getWidth() and setWidth(val), use width() and width(val)
|
||||
|
||||
import graphics from love
|
||||
import sub, len from string
|
||||
|
||||
path = sub ..., 1, len(...) - len "/extensions/streamlined_get_set"
|
||||
element = require "#{path}/elements/element"
|
||||
box = require "#{path}/elements/box"
|
||||
text = require "#{path}/elements/text"
|
||||
|
||||
element.__base.position = (x, y) =>
|
||||
if x or y
|
||||
return @setPosition x, y
|
||||
else
|
||||
return @getPosition!
|
||||
|
||||
element.__base.size = (w, h) =>
|
||||
if w or h
|
||||
return @setSize w, h
|
||||
else
|
||||
return @getSize!
|
||||
|
||||
element.__base.width = (w) =>
|
||||
if w
|
||||
return @setWidth w
|
||||
else
|
||||
return @getWidth!
|
||||
|
||||
element.__base.height = (h) =>
|
||||
if h
|
||||
return @setHeight h
|
||||
else
|
||||
return @getHeight!
|
||||
|
||||
element.__base.alignment = (horizontal, vertical) =>
|
||||
if horizontal or vertical
|
||||
return @setAlignment horizontal, vertical
|
||||
else
|
||||
return @getAlignment!
|
||||
|
||||
-- why is this bit here? Oo
|
||||
element.__base.margin = (m) =>
|
||||
if m
|
||||
return @setMargin m
|
||||
else
|
||||
return @getMargin!
|
||||
|
||||
--oldinit = element.__init
|
||||
--
|
||||
--element.__init = (...) ->
|
||||
-- object = oldinit ...
|
||||
-- value = object.margin
|
||||
--
|
||||
-- object.margin = setmetatable {:value}, {
|
||||
-- __call: (...) ->
|
||||
-- print ...
|
||||
-- }
|
||||
|
||||
element.__base.resize = element.__base.adjustSize
|
||||
|
||||
-- box.__base.background -- can't be done!
|
||||
|
||||
box.__base.color = (r, g, b, a) =>
|
||||
if r or g or b or a
|
||||
return @setColor r, g, b, a
|
||||
else
|
||||
return @getColor!
|
||||
|
||||
text.__base.text = (text) =>
|
||||
if text
|
||||
return @setText text
|
||||
else
|
||||
return @getText!
|
||||
|
||||
text.__base.font = (font) =>
|
||||
if font
|
||||
return @setFont font
|
||||
else
|
||||
return @getFont!
|
||||
|
||||
text.__base.color = (r, g, b, a) =>
|
||||
if r or g or b or a
|
||||
return @setColor r, g, b, a
|
||||
else
|
||||
return @getColor!
|
@ -1,5 +1,9 @@
|
||||
unless love.getVersion
|
||||
error "Pop.Box only supports LOVE versions >= 0.9.1"
|
||||
|
||||
import filesystem, graphics from love
|
||||
import insert from table
|
||||
import inheritsFromElement from require "#{...}/util"
|
||||
|
||||
path = ...
|
||||
|
||||
@ -7,13 +11,15 @@ pop = {}
|
||||
|
||||
pop.elements = {}
|
||||
pop.skins = {}
|
||||
pop.events = {}
|
||||
|
||||
pop.screen = false -- initialized in pop.load()
|
||||
--pop.focused ?
|
||||
pop.focused = false
|
||||
|
||||
-- loads elements and skins, creates pop.screen (intended to only be called once at the beginning)
|
||||
pop.load = ->
|
||||
elements = filesystem.getDirectoryItems "#{path}/elements"
|
||||
|
||||
for i = 1, #elements
|
||||
-- only attempt to load lua files
|
||||
unless elements[i]\sub(-4) == ".lua"
|
||||
@ -22,6 +28,10 @@ pop.load = ->
|
||||
-- load into pop.elements table
|
||||
name = elements[i]\sub 1, -5
|
||||
pop.elements[name] = require "#{path}/elements/#{name}"
|
||||
|
||||
if pop.elements[name].load
|
||||
pop.elements[name].load pop
|
||||
|
||||
print "element loaded: \"#{name}\""
|
||||
|
||||
-- create pop.element() wrapper if possible
|
||||
@ -36,27 +46,47 @@ pop.load = ->
|
||||
|
||||
-- works just like above, except no wrappers
|
||||
skins = filesystem.getDirectoryItems "#{path}/skins"
|
||||
|
||||
for i = 1, #skins
|
||||
unless skins[i]\sub(-4) == ".lua"
|
||||
continue
|
||||
|
||||
name = skins[i]\sub 1, -5
|
||||
pop.skins[name] = require "#{path}/skins/#{name}"
|
||||
|
||||
print "skin loaded: \"#{name}\""
|
||||
|
||||
-- load extensions by just running them via require
|
||||
extensions = filesystem.getDirectoryItems "#{path}/extensions"
|
||||
|
||||
for i = 1, #extensions
|
||||
unless extensions[i]\sub(-4) == ".lua"
|
||||
continue
|
||||
|
||||
name = extensions[i]\sub 1, -5
|
||||
require "#{path}/extensions/#{name}"
|
||||
|
||||
print "extension loaded: \"#{name}\""
|
||||
|
||||
-- main window (called screen because there will be a window element class)
|
||||
pop.screen = pop.create("element", false)\setSize(graphics.getWidth!, graphics.getHeight!)
|
||||
print "created \"pop.screen\""
|
||||
|
||||
-- creates an element with specified parent (parent can be false)
|
||||
-- creates an element with specified parent (parent can be false or non-existent)
|
||||
pop.create = (element, parent=pop.screen, ...) ->
|
||||
element = pop.elements[element](pop, parent, ...)
|
||||
|
||||
if parent
|
||||
if inheritsFromElement parent
|
||||
element = pop.elements[element](parent, ...)
|
||||
insert parent.child, element
|
||||
elseif parent == false
|
||||
element = pop.elements[element](false, ...)
|
||||
else
|
||||
element = pop.elements[element](pop.screen, parent, ...)
|
||||
insert pop.screen.child, element
|
||||
|
||||
return element
|
||||
|
||||
pop.update = (dt, element=pop.screen) ->
|
||||
--pop.screen\update dt
|
||||
unless element.excludeUpdate
|
||||
if element.update
|
||||
element\update dt
|
||||
@ -64,19 +94,56 @@ pop.update = (dt, element=pop.screen) ->
|
||||
pop.update dt, element.child[i]
|
||||
|
||||
pop.draw = (element=pop.screen) ->
|
||||
--pop.screen\draw!
|
||||
unless element.excludeDraw
|
||||
if element.draw
|
||||
element\draw!
|
||||
for i = 1, #element.child
|
||||
pop.draw element.child[i]
|
||||
|
||||
pop.mousepressed = (x, y, button, element=pop.screen) ->
|
||||
print "mousepressed", x, y, button, element
|
||||
return false --TODO event handlers return if they have handled the event!
|
||||
pop.mousemoved = (x, y, dx, dy) =>
|
||||
if pop.focused and pop.focused.mousemoved
|
||||
return pop.focused\mousemoved x, y, dx, dy
|
||||
|
||||
pop.mousereleased = (x, y, button, element=pop.screen) ->
|
||||
print "mousereleased", x, y, button, element
|
||||
return false --TODO event handlers return if they have handled the event!
|
||||
return false
|
||||
|
||||
pop.mousepressed = (x, y, button, element) ->
|
||||
unless element
|
||||
print "mousepressed", x, y, button
|
||||
element = pop.screen
|
||||
|
||||
handled = false
|
||||
|
||||
if (x >= element.x) and (x <= element.x + element.w) and (y >= element.y) and (y <= element.y + element.h)
|
||||
if element.mousepressed
|
||||
handled = element\mousepressed x - element.x, y - element.y, button
|
||||
if handled
|
||||
pop.focused = element
|
||||
pop.events[button] = element
|
||||
else
|
||||
for i = 1, #element.child
|
||||
handled = pop.mousepressed x, y, button, element.child[i]
|
||||
if handled
|
||||
break
|
||||
|
||||
return handled
|
||||
|
||||
pop.mousereleased = (x, y, button) ->
|
||||
print "mousereleased", x, y, button
|
||||
|
||||
clickedHandled = false
|
||||
mousereleasedHandled = false
|
||||
|
||||
if element = pop.events[button]
|
||||
if element.clicked and (x >= element.x) and (x <= element.x + element.w) and (y >= element.y) and (y <= element.y + element.h)
|
||||
if clickedHandled = element\clicked x - element.x, y - element.y, button
|
||||
pop.events[button] = nil
|
||||
|
||||
if element.mousereleased
|
||||
if mousereleasedHandled = element\mousereleased x - element.x, y - element.y, button
|
||||
pop.events[button] = nil
|
||||
|
||||
return clickedHandled, mousereleasedHandled
|
||||
|
||||
pop.keypressed = (key) ->
|
||||
print "keypressed", key
|
||||
@ -90,6 +157,8 @@ pop.textinput = (text) ->
|
||||
print "textinput", text
|
||||
return false --TODO event handlers return if they have handled the event!
|
||||
|
||||
--TODO rewrite skin system to not rely on knowing internals of elements,
|
||||
-- instead call functions like setColor and setBackground
|
||||
-- skins an element (and its children unless depth == true or 0)
|
||||
-- depth can be an integer for how many levels to go down when skinning
|
||||
-- defaults to pop.screen and the default skin
|
||||
|
@ -1,3 +1,6 @@
|
||||
-- Note that the "default" name is a bit of a misnomer, as this does not
|
||||
-- specify the defaults used in Pop.Box elements (they define their own)
|
||||
|
||||
import graphics from love
|
||||
|
||||
return {
|
||||
|
17
src/pop/util.moon
Normal file
17
src/pop/util.moon
Normal file
@ -0,0 +1,17 @@
|
||||
inheritsFromElement = (object) ->
|
||||
if object and object.__class
|
||||
cls = object.__class
|
||||
|
||||
if cls.__name == "element"
|
||||
return true
|
||||
|
||||
while cls.__parent
|
||||
cls = cls.__parent
|
||||
if cls.__name == "element"
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
return {
|
||||
:inheritsFromElement
|
||||
}
|
Loading…
Reference in New Issue
Block a user