diff --git a/demo/main.lua b/demo/main.lua index ff5e1f0..85617c0 100644 --- a/demo/main.lua +++ b/demo/main.lua @@ -2,6 +2,7 @@ local lg = love.graphics local pop, inspect local debugDraw = false +local videoFile = lg.newVideo("test.ogv") -- so we can loop playback function love.load() print(love.getVersion()) @@ -30,7 +31,6 @@ function love.load() --b:margin(2) -- testing streamlined_get_set extension b:fill() -- testing fill! - ---[[ w2 = pop.window(nil, "Window") w2:move(100, 100) w2:setWidth(500) @@ -39,14 +39,15 @@ function love.load() 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} - --]] + w2:setClose(false) + local t2 = pop.text("Click here to toggle close\nbutton on this window."):setMargin(10):setColor(0,0,0) + t2.clicked = function() + print("CALLED") --NOTE not working! + w2:setClose(not w2:hasClose()) + return true + end + w2:addChild(t2) local test = lg.newImage("test.png") G = pop.element():align("right"):move(-2, 2) @@ -58,14 +59,23 @@ function love.load() print(b.horizontal, b.vertical) print(c.horizontal, c.vertical) - local window = pop.window():align("center", "center"):setTitle("Welcome!") + local window = pop.window():align("center", "center"):setTitle("Welcome! This title is far too big!") --window:addChild(pop.text("Welcome to Pop.Box()!")) + pop.window():setClose(false):setClose(true) + + local video = pop.box():align("right", "bottom"):setBackground(videoFile):setSize(320/2, 240/2):move(-20, -20) + videoFile:play() + --TODO make debugDraw better end function love.update(dt) pop.update(dt) + + if not videoFile:isPlaying() then + videoFile:rewind() + end end function love.draw() diff --git a/demo/pop/elements/element.lua b/demo/pop/elements/element.lua index 1bbba88..ecfaf51 100644 --- a/demo/pop/elements/element.lua +++ b/demo/pop/elements/element.lua @@ -28,6 +28,7 @@ do end insert(self.child, child) child.parent = self + child:align() return self end, removeChild = function(self, child) @@ -41,7 +42,7 @@ do return self end end - return error("Element \"" .. tostring(child) .. "\" is not a child of element \"" .. tostring(self) .. "\". Cannot remove it.") + return "Element \"" .. tostring(child) .. "\" is not a child of element \"" .. tostring(self) .. "\". Cannot remove it." end end, getChildren = function(self) @@ -240,7 +241,8 @@ do for k, v in ipairs(self.child) do v:delete() end - return self.parent:removeChild(self) + self.parent:removeChild(self) + self = nil end } _base_0.__index = _base_0 diff --git a/demo/pop/elements/img/close.png b/demo/pop/elements/img/close.png new file mode 100644 index 0000000..bf19d3b Binary files /dev/null and b/demo/pop/elements/img/close.png differ diff --git a/demo/pop/elements/window.lua b/demo/pop/elements/window.lua index 650a5c2..96af1d9 100644 --- a/demo/pop/elements/window.lua +++ b/demo/pop/elements/window.lua @@ -17,6 +17,12 @@ 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 closeImage = { + 100, + 0, + 0, + 80 +} local left = 1 local mousemoved_event = true do @@ -60,6 +66,14 @@ do local result = self.window:removeChild(child) if result == self.window then return self + elseif type(result) == "string" then + for k, v in ipairs(self.child) do + if v == child then + remove(self.child, k) + return self + end + end + return "Element \"" .. tostring(child) .. "\" is not a child of window \"" .. tostring(self) .. "\". Cannot remove it." else return result end @@ -85,11 +99,18 @@ do elseif "right" == _exp_0 then x = x - (w - self.w) end - self.head:setWidth(w) + if self.close then + self.head:setWidth(w - self.head:getHeight()) + else + self.head:setWidth(w) + end self.window:setWidth(w) self.w = w self.x = self.x + x self.title:align() + if self.close then + self.close:align() + end end if h then h = h - self.head:getHeight() @@ -115,11 +136,18 @@ do elseif "right" == _exp_0 then x = x - (w - self.w) end - self.head:setWidth(w) + if self.close then + self.head:setWidth(w - self.head:getHeight()) + else + self.head:setWidth(w) + end self.window:setWidth(w) self.w = w self.x = self.x + x self.title:align() + if self.close then + self.close:align() + end self.head:move(x) self.window:move(x) return self @@ -143,10 +171,50 @@ do end, setTitle = function(self, title) self.title:setText(title) + if self.titleOverflow == "trunicate" then + while self.title:getWidth() > self.head:getWidth() do + title = title:sub(1, -3) + self.title:setText(title .. "…") + end + elseif self.titleOverflow == "resize" then + if self.title:getWidth() > self.head:getWidth() then + self:setWidth(self.title:getWidth()) + end + end return self end, getTitle = function(self) return self.title:getText() + end, + setTitleOverflow = function(self, method) + self.titleOverflow = method + return self + end, + getTitleOverflow = function(self) + return self.titleOverflow + end, + setClose = function(self, enabled) + if enabled then + self.close = box(self, closeImage) + local height = self.head:getHeight() + self.close:align("right"):setSize(height, height) + self.head:setWidth(self.w - height) + self.title:align() + insert(self.child, self.close) + else + self.close:delete() + self.head:setWidth(self.w) + self.title:align() + self.close = false + end + return self + end, + hasClose = function(self) + if self.close then + return true + else + return false + end end } _base_0.__index = _base_0 @@ -184,15 +252,24 @@ do self.head = box(self, tBackground) self.title = text(self, title, tColor) self.window = box(self, wBackground) + self.close = box(self, closeImage) local height = self.title:getHeight() - self.head:setSize(self.w, height) + self.head:setSize(self.w - height, height) self.window:move(nil, height) + self.close:align("right"):setSize(height, height) self:setSize(100, 80) self.child = { self.head, self.title, - self.window + self.window, + self.close } + self.titleOverflow = "trunicate" + self.close.clicked = function() + print("CLOSE WAS CLICKED") + self:delete() + return true + end self.head.selected = false if mousemoved_event then self.head.mousemoved = function(self, x, y, dx, dy) diff --git a/demo/pop/init.lua b/demo/pop/init.lua index 1d557e9..04d7b3c 100644 --- a/demo/pop/init.lua +++ b/demo/pop/init.lua @@ -156,30 +156,57 @@ pop.mousepressed = function(x, y, button, element) end return handled end -pop.mousereleased = function(x, y, button) - print("mousereleased", x, y, button) +pop.mousereleased = function(x, y, button, element) local clickedHandled = false local mousereleasedHandled = false - do - local element = pop.events[button] - if element then + if element then + if (x >= element.x) and (x <= element.x + element.w) and (y >= element.y) and (y <= element.y + element.h) then if element.clicked and (not element.excludeDraw) then - do - clickedHandled = element:clicked(x - element.x, y - element.y, button) - if clickedHandled then - pop.events[button] = nil - end - end + clickedHandled = element:clicked(x - element.x, y - element.y, button) end if element.mousereleased then - do - mousereleasedHandled = element:mousereleased(x - element.x, y - element.y, button) - if mousereleasedHandled then - pop.events[button] = nil + mousereleasedHandled = element:mousereleased(x - element.x, y - element.y, button) + end + if clickedHandled then + pop.focused = element + end + if clickedHandled or mousereleasedHandled then + return clickedHandled, mousereleasedHandled + else + for i = 1, #element.child do + clickedHandled, mousereleasedHandled = pop.mousereleased(x, y, button, element.child[i]) + if clickedHandled or mousereleasedHandled then + break end end end end + else + print("mousereleased", x, y, button) + do + element = pop.events[button] + if element then + if element.clicked and (not element.excludeDraw) 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 + if (not clickedHandled) and (not mousereleasedHandled) then + clickedHandled, mousereleasedHandled = pop.mousereleased(x, y, button, pop.screen) + end end return clickedHandled, mousereleasedHandled end diff --git a/lib/pop/elements/element.lua b/lib/pop/elements/element.lua index 1bbba88..ecfaf51 100644 --- a/lib/pop/elements/element.lua +++ b/lib/pop/elements/element.lua @@ -28,6 +28,7 @@ do end insert(self.child, child) child.parent = self + child:align() return self end, removeChild = function(self, child) @@ -41,7 +42,7 @@ do return self end end - return error("Element \"" .. tostring(child) .. "\" is not a child of element \"" .. tostring(self) .. "\". Cannot remove it.") + return "Element \"" .. tostring(child) .. "\" is not a child of element \"" .. tostring(self) .. "\". Cannot remove it." end end, getChildren = function(self) @@ -240,7 +241,8 @@ do for k, v in ipairs(self.child) do v:delete() end - return self.parent:removeChild(self) + self.parent:removeChild(self) + self = nil end } _base_0.__index = _base_0 diff --git a/lib/pop/elements/img/close.png b/lib/pop/elements/img/close.png new file mode 100644 index 0000000..bf19d3b Binary files /dev/null and b/lib/pop/elements/img/close.png differ diff --git a/lib/pop/elements/window.lua b/lib/pop/elements/window.lua index 650a5c2..96af1d9 100644 --- a/lib/pop/elements/window.lua +++ b/lib/pop/elements/window.lua @@ -17,6 +17,12 @@ 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 closeImage = { + 100, + 0, + 0, + 80 +} local left = 1 local mousemoved_event = true do @@ -60,6 +66,14 @@ do local result = self.window:removeChild(child) if result == self.window then return self + elseif type(result) == "string" then + for k, v in ipairs(self.child) do + if v == child then + remove(self.child, k) + return self + end + end + return "Element \"" .. tostring(child) .. "\" is not a child of window \"" .. tostring(self) .. "\". Cannot remove it." else return result end @@ -85,11 +99,18 @@ do elseif "right" == _exp_0 then x = x - (w - self.w) end - self.head:setWidth(w) + if self.close then + self.head:setWidth(w - self.head:getHeight()) + else + self.head:setWidth(w) + end self.window:setWidth(w) self.w = w self.x = self.x + x self.title:align() + if self.close then + self.close:align() + end end if h then h = h - self.head:getHeight() @@ -115,11 +136,18 @@ do elseif "right" == _exp_0 then x = x - (w - self.w) end - self.head:setWidth(w) + if self.close then + self.head:setWidth(w - self.head:getHeight()) + else + self.head:setWidth(w) + end self.window:setWidth(w) self.w = w self.x = self.x + x self.title:align() + if self.close then + self.close:align() + end self.head:move(x) self.window:move(x) return self @@ -143,10 +171,50 @@ do end, setTitle = function(self, title) self.title:setText(title) + if self.titleOverflow == "trunicate" then + while self.title:getWidth() > self.head:getWidth() do + title = title:sub(1, -3) + self.title:setText(title .. "…") + end + elseif self.titleOverflow == "resize" then + if self.title:getWidth() > self.head:getWidth() then + self:setWidth(self.title:getWidth()) + end + end return self end, getTitle = function(self) return self.title:getText() + end, + setTitleOverflow = function(self, method) + self.titleOverflow = method + return self + end, + getTitleOverflow = function(self) + return self.titleOverflow + end, + setClose = function(self, enabled) + if enabled then + self.close = box(self, closeImage) + local height = self.head:getHeight() + self.close:align("right"):setSize(height, height) + self.head:setWidth(self.w - height) + self.title:align() + insert(self.child, self.close) + else + self.close:delete() + self.head:setWidth(self.w) + self.title:align() + self.close = false + end + return self + end, + hasClose = function(self) + if self.close then + return true + else + return false + end end } _base_0.__index = _base_0 @@ -184,15 +252,24 @@ do self.head = box(self, tBackground) self.title = text(self, title, tColor) self.window = box(self, wBackground) + self.close = box(self, closeImage) local height = self.title:getHeight() - self.head:setSize(self.w, height) + self.head:setSize(self.w - height, height) self.window:move(nil, height) + self.close:align("right"):setSize(height, height) self:setSize(100, 80) self.child = { self.head, self.title, - self.window + self.window, + self.close } + self.titleOverflow = "trunicate" + self.close.clicked = function() + print("CLOSE WAS CLICKED") + self:delete() + return true + end self.head.selected = false if mousemoved_event then self.head.mousemoved = function(self, x, y, dx, dy) diff --git a/lib/pop/init.lua b/lib/pop/init.lua index 1d557e9..04d7b3c 100644 --- a/lib/pop/init.lua +++ b/lib/pop/init.lua @@ -156,30 +156,57 @@ pop.mousepressed = function(x, y, button, element) end return handled end -pop.mousereleased = function(x, y, button) - print("mousereleased", x, y, button) +pop.mousereleased = function(x, y, button, element) local clickedHandled = false local mousereleasedHandled = false - do - local element = pop.events[button] - if element then + if element then + if (x >= element.x) and (x <= element.x + element.w) and (y >= element.y) and (y <= element.y + element.h) then if element.clicked and (not element.excludeDraw) then - do - clickedHandled = element:clicked(x - element.x, y - element.y, button) - if clickedHandled then - pop.events[button] = nil - end - end + clickedHandled = element:clicked(x - element.x, y - element.y, button) end if element.mousereleased then - do - mousereleasedHandled = element:mousereleased(x - element.x, y - element.y, button) - if mousereleasedHandled then - pop.events[button] = nil + mousereleasedHandled = element:mousereleased(x - element.x, y - element.y, button) + end + if clickedHandled then + pop.focused = element + end + if clickedHandled or mousereleasedHandled then + return clickedHandled, mousereleasedHandled + else + for i = 1, #element.child do + clickedHandled, mousereleasedHandled = pop.mousereleased(x, y, button, element.child[i]) + if clickedHandled or mousereleasedHandled then + break end end end end + else + print("mousereleased", x, y, button) + do + element = pop.events[button] + if element then + if element.clicked and (not element.excludeDraw) 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 + if (not clickedHandled) and (not mousereleasedHandled) then + clickedHandled, mousereleasedHandled = pop.mousereleased(x, y, button, pop.screen) + end end return clickedHandled, mousereleasedHandled end diff --git a/src/pop/elements/element.moon b/src/pop/elements/element.moon index 80dfcec..57b9667 100644 --- a/src/pop/elements/element.moon +++ b/src/pop/elements/element.moon @@ -47,6 +47,8 @@ class element insert @child, child child.parent = @ + child\align! --NOTE not 100% sure if this is a good idea + return @ -- remove child by index and return it OR remove child by reference @@ -60,7 +62,7 @@ class element if v == child remove @child, k return @ - error "Element \"#{child}\" is not a child of element \"#{@}\". Cannot remove it." + return "Element \"#{child}\" is not a child of element \"#{@}\". Cannot remove it." getChildren: => return @child @@ -259,3 +261,4 @@ class element v\delete! @parent\removeChild @ + @ = nil diff --git a/src/pop/elements/img/close.png b/src/pop/elements/img/close.png new file mode 100644 index 0000000..bf19d3b Binary files /dev/null and b/src/pop/elements/img/close.png differ diff --git a/src/pop/elements/window.moon b/src/pop/elements/window.moon index b9d89fc..c6708d6 100644 --- a/src/pop/elements/window.moon +++ b/src/pop/elements/window.moon @@ -7,6 +7,8 @@ element = require "#{path}/element" box = require "#{path}/box" text = require "#{path}/text" +closeImage = {100, 0, 0, 80} --graphics.newImage "#{path}/img/close.png" + -- version compatibility left = 1 -- what is the left mouse button? mousemoved_event = true -- is the mousemoved event available? @@ -35,19 +37,28 @@ class window extends element @head = box @, tBackground -- title box at top @title = text @, title, tColor -- text at top @window = box @, wBackground -- main window area + @close = box @, closeImage -- close button -- correct placement / sizes of elements height = @title\getHeight! - @head\setSize @w, height + @head\setSize @w - height, height @window\move nil, height + @close\align("right")\setSize height, height @setSize 100, 80 -- our child elements are still child elements --TODO change title to be a child of head ? @child = { - @head, @title, @window + @head, @title, @window, @close } + @titleOverflow = "trunicate" -- defaults to trunicating title to fit in window + + @close.clicked = -> + print "CLOSE WAS CLICKED" + @delete! + return true + @head.selected = false -- whether or not the window title (and thus, the window) has been selected if mousemoved_event @@ -108,6 +119,12 @@ class window extends element result = @window\removeChild child if result == @window return @ + elseif type(result) == "string" + for k,v in ipairs @child + if v == child + remove @child, k + return @ + return "Element \"#{child}\" is not a child of window \"#{@}\". Cannot remove it." else return result @@ -135,13 +152,20 @@ class window extends element when "right" x -= w - @w - @head\setWidth w + if @close + @head\setWidth w - @head\getHeight! + else + @head\setWidth w + @window\setWidth w @w = w @x += x @title\align! + if @close + @close\align! + if h h = h - @head\getHeight! switch @vertical @@ -169,13 +193,20 @@ class window extends element when "right" x -= w - @w - @head\setWidth w + if @close + @head\setWidth w - @head\getHeight! + else + @head\setWidth w + @window\setWidth w @w = w @x += x @title\align! + if @close + @close\align! + @head\move x --@title\move x @window\move x @@ -204,7 +235,47 @@ class window extends element setTitle: (title) => @title\setText title + + if @titleOverflow == "trunicate" + while @title\getWidth! > @head\getWidth! + title = title\sub 1, -3 + @title\setText title .. "…" + + elseif @titleOverflow == "resize" + if @title\getWidth! > @head\getWidth! + @setWidth @title\getWidth! + return @ getTitle: => return @title\getText! + + setTitleOverflow: (method) => + @titleOverflow = method + + return @ + + getTitleOverflow: => + return @titleOverflow + + setClose: (enabled) => + if enabled + @close = box @, closeImage + height = @head\getHeight! + @close\align("right")\setSize height, height + @head\setWidth @w - height + @title\align! -- new might not be working? + insert @child, @close + else + @close\delete! + @head\setWidth @w + @title\align! -- new might not be working? + @close = false + + return @ + + hasClose: => + if @close + return true + else + return false diff --git a/src/pop/init.moon b/src/pop/init.moon index 7f8a8c6..19517ce 100644 --- a/src/pop/init.moon +++ b/src/pop/init.moon @@ -129,20 +129,41 @@ pop.mousepressed = (x, y, button, element) -> return handled -pop.mousereleased = (x, y, button) -> - print "mousereleased", x, y, button - +pop.mousereleased = (x, y, button, element) -> clickedHandled = false mousereleasedHandled = false - if element = pop.events[button] - if element.clicked and (not element.excludeDraw) --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 + if (x >= element.x) and (x <= element.x + element.w) and (y >= element.y) and (y <= element.y + element.h) + if element.clicked and (not element.excludeDraw) + clickedHandled = element\clicked x - element.x, y - element.y, button + if element.mousereleased + mousereleasedHandled = element\mousereleased x - element.x, y - element.y, button - if element.mousereleased - if mousereleasedHandled = element\mousereleased x - element.x, y - element.y, button - pop.events[button] = nil + if clickedHandled + pop.focused = element + + if clickedHandled or mousereleasedHandled + return clickedHandled, mousereleasedHandled + else + for i = 1, #element.child + clickedHandled, mousereleasedHandled = pop.mousereleased x, y, button, element.child[i] + if clickedHandled or mousereleasedHandled + break + + else + print "mousereleased", x, y, button + if element = pop.events[button] + if element.clicked and (not element.excludeDraw) --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 + + if (not clickedHandled) and (not mousereleasedHandled) + clickedHandled, mousereleasedHandled = pop.mousereleased x, y, button, pop.screen return clickedHandled, mousereleasedHandled