diff --git a/demo/debug-lib/inspect.lua b/demo/debug-lib/inspect.lua
new file mode 100644
index 0000000..4b654b2
--- /dev/null
+++ b/demo/debug-lib/inspect.lua
@@ -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('
')
+ 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(' = ')
+ 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
+
diff --git a/demo/main.lua b/demo/main.lua
index e857148..ff5e1f0 100644
--- a/demo/main.lua
+++ b/demo/main.lua
@@ -1,11 +1,12 @@
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)
@@ -57,7 +58,9 @@ function love.load()
print(b.horizontal, b.vertical)
print(c.horizontal, c.vertical)
- --TODO make rounding to nearest pixel DEFAULT BEHAVIOR
+ local window = pop.window():align("center", "center"):setTitle("Welcome!")
+ --window:addChild(pop.text("Welcome to Pop.Box()!"))
+
--TODO make debugDraw better
end
diff --git a/demo/pop/elements/element.lua b/demo/pop/elements/element.lua
index 8af555a..e0d5301 100644
--- a/demo/pop/elements/element.lua
+++ b/demo/pop/elements/element.lua
@@ -21,6 +21,9 @@ do
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
diff --git a/demo/pop/elements/text.lua b/demo/pop/elements/text.lua
index 44ee6a3..9d5df18 100644
--- a/demo/pop/elements/text.lua
+++ b/demo/pop/elements/text.lua
@@ -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)
@@ -68,12 +59,12 @@ do
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
@@ -145,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
diff --git a/demo/pop/elements/window.lua b/demo/pop/elements/window.lua
index f791a16..72b2033 100644
--- a/demo/pop/elements/window.lua
+++ b/demo/pop/elements/window.lua
@@ -44,6 +44,22 @@ do
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
@@ -109,6 +125,10 @@ do
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
diff --git a/lib/pop/elements/element.lua b/lib/pop/elements/element.lua
index 8af555a..e0d5301 100644
--- a/lib/pop/elements/element.lua
+++ b/lib/pop/elements/element.lua
@@ -21,6 +21,9 @@ do
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
diff --git a/lib/pop/elements/text.lua b/lib/pop/elements/text.lua
index 44ee6a3..9d5df18 100644
--- a/lib/pop/elements/text.lua
+++ b/lib/pop/elements/text.lua
@@ -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)
@@ -68,12 +59,12 @@ do
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
@@ -145,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
diff --git a/lib/pop/elements/window.lua b/lib/pop/elements/window.lua
index f791a16..72b2033 100644
--- a/lib/pop/elements/window.lua
+++ b/lib/pop/elements/window.lua
@@ -44,6 +44,22 @@ do
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
@@ -109,6 +125,10 @@ do
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
diff --git a/src/pop/elements/text.moon b/src/pop/elements/text.moon
index fc5347b..80d611e 100644
--- a/src/pop/elements/text.moon
+++ b/src/pop/elements/text.moon
@@ -6,7 +6,7 @@ element = require "#{path}/element"
class text extends element
-- this should be completely unneccessary, but I'm keeping it just in case
- wrap: (pop) ->
+ @wrap = (pop) ->
return (parent, ...) ->
if type(parent) == "string"
return pop.create("text", nil, parent, ...)
@@ -23,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 @
@@ -40,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"
@@ -71,12 +71,12 @@ class text extends element
return @
setText: (text="") =>
- @text = text
+ @txt = text
@setSize!
return @
getText: =>
- return @text
+ return @txt
setFont: (font) =>
@font = font
diff --git a/src/pop/elements/window.moon b/src/pop/elements/window.moon
index 994ad02..9a4aa8c 100644
--- a/src/pop/elements/window.moon
+++ b/src/pop/elements/window.moon
@@ -118,6 +118,16 @@ class window extends element
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
@@ -207,3 +217,7 @@ class window extends element
@window\move nil, y
return @
+
+ setTitle: (title) =>
+ @title\setText title
+ return @