diff --git a/objects/internal/treenode.lua b/objects/internal/treenode.lua new file mode 100644 index 0000000..0de276b --- /dev/null +++ b/objects/internal/treenode.lua @@ -0,0 +1,212 @@ +--[[------------------------------------------------ + -- Love Frames - A GUI library for LOVE -- + -- Copyright (c) 2012-2014 Kenny Shields -- +--]]------------------------------------------------ + +-- button object +local newobject = loveframes.NewObject("treenode", "loveframes_object_treenode", true) + +--[[--------------------------------------------------------- + - func: initialize() + - desc: initializes the object +--]]--------------------------------------------------------- +function newobject:initialize() + + self.type = "treenode" + self.text = "Node" + self.width = 250 + self.height = 16 + self.level = 0 + self.leftpadding = 0 + self.open = false + self.internal = true + self.internals = {} + self.icon = nil + +end + +--[[--------------------------------------------------------- + - func: update(deltatime) + - desc: updates the object +--]]--------------------------------------------------------- +function newobject:update(dt) + + local state = loveframes.state + local selfstate = self.state + + if state ~= selfstate then + return + end + + local visible = self.visible + local alwaysupdate = self.alwaysupdate + + if not visible then + if not alwaysupdate then + return + end + end + + self:CheckHover() + + local parent = self.parent + local base = loveframes.base + local update = self.Update + + local tree = self.tree + self:SetClickBounds(tree.x, tree.y, tree.width, tree.height) + + for k, v in ipairs(self.internals) do + if v.type == "treenode" then + if self.open then + v.x = v.tree.x - v.tree.offsetx + v.y = (v.tree.y + self.tree.itemheight) - v.tree.offsety + if v.width > self.tree.itemwidth then + self.tree.itemwidth = v.width + end + self.tree.itemheight = self.tree.itemheight + v.height + v:update(dt) + end + else + v:update(dt) + end + end + + if update then + update(self, dt) + end + +end + +--[[--------------------------------------------------------- + - func: draw() + - desc: draws the object +--]]--------------------------------------------------------- +function newobject:draw() + + local state = loveframes.state + local selfstate = self.state + + if state ~= selfstate then + return + end + + local visible = self.visible + + if not visible then + return + end + + local skins = loveframes.skins.available + local skinindex = loveframes.config["ACTIVESKIN"] + local defaultskin = loveframes.config["DEFAULTSKIN"] + local selfskin = self.skin + local skin = skins[selfskin] or skins[skinindex] + local drawfunc = skin.DrawTreeNode or skins[defaultskin].DrawTreeNode + local draw = self.Draw + local drawcount = loveframes.drawcount + + -- set the object's draw order + self:SetDrawOrder() + + if draw then + draw(self) + else + drawfunc(self) + end + + for k, v in ipairs(self.internals) do + if v.type == "treenode" then + if self.open then + v:draw() + end + else + v:draw() + end + end + +end + +--[[--------------------------------------------------------- + - func: mousepressed(x, y, button) + - desc: called when the player presses a mouse button +--]]--------------------------------------------------------- +function newobject:mousepressed(x, y, button) + + local state = loveframes.state + local selfstate = self.state + + if state ~= selfstate then + return + end + + local visible = self.visible + + if not visible then + return + end + + for k, v in ipairs(self.internals) do + v:mousepressed(x, y, button) + end + +end + +--[[--------------------------------------------------------- + - func: mousereleased(x, y, button) + - desc: called when the player releases a mouse button +--]]--------------------------------------------------------- +function newobject:mousereleased(x, y, button) + + local state = loveframes.state + local selfstate = self.state + + if state ~= selfstate then + return + end + + local visible = self.visible + + if not visible then + return + end + + for k, v in ipairs(self.internals) do + v:mousereleased(x, y, button) + end + +end + +function newobject:SetIcon(icon) + + self.icon = icon + return self + +end + +function newobject:AddNode(text) + + if not self.internals[1] then + local openbutton = loveframes.objects["treenodebutton"]:new() + openbutton.parent = self + openbutton.staticx = 2 + openbutton.staticy = 2 + table.insert(self.internals, openbutton) + end + + local node = loveframes.objects["treenode"]:new() + node.parent = self + node.tree = self.tree + node.text = text + node.level = self.level + 1 + table.insert(self.internals, node) + return node + +end + +function newobject:SetOpen(bool) + + self.open = bool + return self + +end \ No newline at end of file diff --git a/objects/internal/treenodebutton.lua b/objects/internal/treenodebutton.lua new file mode 100644 index 0000000..dc55e8d --- /dev/null +++ b/objects/internal/treenodebutton.lua @@ -0,0 +1,128 @@ +--[[------------------------------------------------ + -- Love Frames - A GUI library for LOVE -- + -- Copyright (c) 2012-2014 Kenny Shields -- +--]]------------------------------------------------ + +-- button object +local newobject = loveframes.NewObject("treenodebutton", "loveframes_object_treenodebutton", true) + +--[[--------------------------------------------------------- + - func: initialize() + - desc: initializes the object +--]]--------------------------------------------------------- +function newobject:initialize() + + self.type = "treenodebutton" + self.width = 16 + self.height = 16 + self.internal = true + +end + +--[[--------------------------------------------------------- + - func: update(deltatime) + - desc: updates the object +--]]--------------------------------------------------------- +function newobject:update(dt) + + local state = loveframes.state + local selfstate = self.state + + if state ~= selfstate then + return + end + + local visible = self.visible + local alwaysupdate = self.alwaysupdate + + if not visible then + if not alwaysupdate then + return + end + end + + self:CheckHover() + + local parent = self.parent + local base = loveframes.base + local update = self.Update + + -- move to parent if there is a parent + if parent ~= base then + self.x = self.parent.x + self.staticx + self.y = self.parent.y + self.staticy + end + + if update then + update(self, dt) + end + +end + +--[[--------------------------------------------------------- + - func: draw() + - desc: draws the object +--]]--------------------------------------------------------- +function newobject:draw() + + local state = loveframes.state + local selfstate = self.state + + if state ~= selfstate then + return + end + + local visible = self.visible + + if not visible then + return + end + + local skins = loveframes.skins.available + local skinindex = loveframes.config["ACTIVESKIN"] + local defaultskin = loveframes.config["DEFAULTSKIN"] + local selfskin = self.skin + local skin = skins[selfskin] or skins[skinindex] + local drawfunc = skin.DrawTreeNodeButton or skins[defaultskin].DrawTreeNodeButton + local draw = self.Draw + local drawcount = loveframes.drawcount + + -- set the object's draw order + self:SetDrawOrder() + + if draw then + draw(self) + else + drawfunc(self) + end + +end + +--[[--------------------------------------------------------- + - func: mousepressed(x, y, button) + - desc: called when the player presses a mouse button +--]]--------------------------------------------------------- +function newobject:mousepressed(x, y, button) + + local state = loveframes.state + local selfstate = self.state + + if state ~= selfstate then + return + end + + local visible = self.visible + + if not visible then + return + end + + local hover = self.hover + + if hover and button == "l" then + self.parent:SetOpen(not self.parent.open) + print("!") + print(self.parent.level) + end + +end \ No newline at end of file diff --git a/objects/tree.lua b/objects/tree.lua new file mode 100644 index 0000000..08cbf47 --- /dev/null +++ b/objects/tree.lua @@ -0,0 +1,323 @@ +--[[------------------------------------------------ + -- Love Frames - A GUI library for LOVE -- + -- Copyright (c) 2012-2014 Kenny Shields -- +--]]------------------------------------------------ + +-- button object +local newobject = loveframes.NewObject("tree", "loveframes_object_tree", true) + +--[[--------------------------------------------------------- + - func: initialize() + - desc: initializes the object +--]]--------------------------------------------------------- +function newobject:initialize() + + self.type = "tree" + self.width = 200 + self.height = 200 + self.offsetx = 0 + self.offsety = 0 + self.itemwidth = 0 + self.itemheight = 0 + self.extrawidth = 0 + self.extraheight = 0 + self.buttonscrollamount = 0.10 + self.vbar = false + self.hbar = false + self.internal = false + self.children = {} + self.internals = {} + +end + +--[[--------------------------------------------------------- + - func: update(deltatime) + - desc: updates the object +--]]--------------------------------------------------------- +function newobject:update(dt) + + local state = loveframes.state + local selfstate = self.state + + if state ~= selfstate then + return + end + + local visible = self.visible + local alwaysupdate = self.alwaysupdate + + if not visible then + if not alwaysupdate then + return + end + end + + self:CheckHover() + + local parent = self.parent + local base = loveframes.base + local update = self.Update + + -- move to parent if there is a parent + if parent ~= base then + self.x = self.parent.x + self.staticx + self.y = self.parent.y + self.staticy + end + + self.itemwidth = 0 + self.itemheight = 0 + + for k, v in ipairs(self.children) do + v.x = (v.parent.x + v.staticx) - self.offsetx + v.y = (self.y + self.itemheight) - self.offsety + if v.width > self.itemwidth then + self.itemwidth = v.width + end + self.itemheight = self.itemheight + v.height + v:update(dt) + end + + if self.vbar then + self.itemwidth = self.itemwidth + 16 + 5 + end + + self.extrawidth = self.itemwidth - self.width + self.extraheight = self.itemheight - self.height + + if self.itemheight > self.height then + if not self.vbar then + local scrollbody = loveframes.objects["scrollbody"]:new(self, "vertical") + table.insert(self.internals, scrollbody) + self.vbar = true + if self.hbar then + local vbody = self:GetVerticalScrollBody() + local vbodyheight = vbody:GetHeight() - 15 + local hbody = self:GetHorizontalScrollBody() + local hbodywidth = hbody:GetWidth() - 15 + vbody:SetHeight(vbodyheight) + hbody:SetWidth(hbodywidth) + end + end + else + if self.vbar then + self:GetVerticalScrollBody():Remove() + self.vbar = false + self.offsety = 0 + if self.hbar then + local hbody = self:GetHorizontalScrollBody() + local hbodywidth = hbody:GetWidth() - 15 + hbody:SetWidth(hbodywidth) + end + end + end + + if self.itemwidth > self.width then + if not self.hbar then + local scrollbody = loveframes.objects["scrollbody"]:new(self, "horizontal") + table.insert(self.internals, scrollbody) + self.hbar = true + if self.vbar then + local vbody = self:GetVerticalScrollBody() + local hbody = self:GetHorizontalScrollBody() + vbody:SetHeight(vbody:GetHeight() - 15) + hbody:SetWidth(hbody:GetWidth() - 15) + end + end + else + if self.hbar then + self:GetHorizontalScrollBody():Remove() + self.hbar = false + self.offsetx = 0 + if self.vbar then + local vbody = self:GetVerticalScrollBody() + if vbody then + vbody:SetHeight(vbody:GetHeight() + 15) + end + end + end + end + + for k, v in ipairs(self.internals) do + v:update(dt) + end + + if update then + update(self, dt) + end + +end + +--[[--------------------------------------------------------- + - func: draw() + - desc: draws the object +--]]--------------------------------------------------------- +function newobject:draw() + + local state = loveframes.state + local selfstate = self.state + + if state ~= selfstate then + return + end + + local visible = self.visible + + if not visible then + return + end + + local skins = loveframes.skins.available + local skinindex = loveframes.config["ACTIVESKIN"] + local defaultskin = loveframes.config["DEFAULTSKIN"] + local selfskin = self.skin + local skin = skins[selfskin] or skins[skinindex] + local drawfunc = skin.DrawTree or skins[defaultskin].DrawTree + local draw = self.Draw + local drawcount = loveframes.drawcount + local stencilfunc + + if self.vbar and not self.hbar then + stencilfunc = function() love.graphics.rectangle("fill", self.x, self.y, self.width - 16, self.height) end + elseif self.hbar and not self.vbar then + stencilfunc = function() love.graphics.rectangle("fill", self.x, self.y, self.width, self.height - 16) end + elseif self.vbar and self.hbar then + stencilfunc = function() love.graphics.rectangle("fill", self.x, self.y, self.width - 16, self.height - 16) end + end + + -- set the object's draw order + self:SetDrawOrder() + + love.graphics.setStencil(stencilfunc) + + if draw then + draw(self) + else + drawfunc(self) + end + + for k, v in ipairs(self.children) do + v:draw() + end + + love.graphics.setStencil() + + for k, v in ipairs(self.internals) do + v:draw() + end + +end + +--[[--------------------------------------------------------- + - func: mousepressed(x, y, button) + - desc: called when the player presses a mouse button +--]]--------------------------------------------------------- +function newobject:mousepressed(x, y, button) + + local state = loveframes.state + local selfstate = self.state + + if state ~= selfstate then + return + end + + local visible = self.visible + + if not visible then + return + end + + for k, v in ipairs(self.internals) do + v:mousepressed(x, y, button) + end + + for k, v in ipairs(self.children) do + v:mousepressed(x, y, button) + end + +end + +--[[--------------------------------------------------------- + - func: mousereleased(x, y, button) + - desc: called when the player releases a mouse button +--]]--------------------------------------------------------- +function newobject:mousereleased(x, y, button) + + local state = loveframes.state + local selfstate = self.state + + if state ~= selfstate then + return + end + + local visible = self.visible + + if not visible then + return + end + + for k, v in ipairs(self.internals) do + v:mousereleased(x, y, button) + end + + for k, v in ipairs(self.children) do + v:mousereleased(x, y, button) + end + +end + +function newobject:AddNode(text) + + local node = loveframes.objects["treenode"]:new() + node.parent = self + node.tree = self + node.text = text + node.staticx = 0 + node.staticy = self.itemheight + table.insert(self.children, node) + return node + +end + +--[[--------------------------------------------------------- + - func: GetVerticalScrollBody() + - desc: gets the object's vertical scroll body +--]]--------------------------------------------------------- +function newobject:GetVerticalScrollBody() + + local vbar = self.vbar + local internals = self.internals + local item = false + + if vbar then + for k, v in ipairs(internals) do + if v.type == "scrollbody" and v.bartype == "vertical" then + item = v + end + end + end + + return item + +end + +--[[--------------------------------------------------------- + - func: GetHorizontalScrollBody() + - desc: gets the object's horizontal scroll body +--]]--------------------------------------------------------- +function newobject:GetHorizontalScrollBody() + + local hbar = self.hbar + local internals = self.internals + local item = false + + if hbar then + for k, v in ipairs(internals) do + if v.type == "scrollbody" and v.bartype == "horizontal" then + item = v + end + end + end + + return item + +end \ No newline at end of file diff --git a/skins/Blue/images/tree-node-button-close.png b/skins/Blue/images/tree-node-button-close.png new file mode 100644 index 0000000..7591f55 Binary files /dev/null and b/skins/Blue/images/tree-node-button-close.png differ diff --git a/skins/Blue/images/tree-node-button-open.png b/skins/Blue/images/tree-node-button-open.png new file mode 100644 index 0000000..68b36cc Binary files /dev/null and b/skins/Blue/images/tree-node-button-open.png differ diff --git a/skins/Blue/skin.lua b/skins/Blue/skin.lua index f2b791c..ccf718c 100644 --- a/skins/Blue/skin.lua +++ b/skins/Blue/skin.lua @@ -1756,5 +1756,67 @@ function skin.DrawMenuOption(object) end +function skin.DrawTree(object) + + local skin = object:GetSkin() + local x = object:GetX() + local y = object:GetY() + local width = object:GetWidth() + local height = object:GetHeight() + + love.graphics.setColor(200, 200, 200, 255) + love.graphics.rectangle("fill", x, y, width, height) + +end + +function skin.DrawTreeNode(object) + + local icon = object.icon + local buttonimage = skin.images["tree-node-button-open.png"] + local width = 0 + local x = object.x + local leftpadding = 15 * object.level + + if object.level > 0 then + leftpadding = leftpadding + buttonimage:getWidth() + 5 + else + leftpadding = buttonimage:getWidth() + 5 + end + + if icon then + local iconwidth = icon:getWidth() + width = width + iconwidth + loveframes.basicfont:getWidth(object.text) + leftpadding + love.graphics.setColor(255, 255, 255, 255) + love.graphics.draw(icon, x + leftpadding, object.y) + love.graphics.setFont(loveframes.basicfont) + love.graphics.setColor(0, 0, 0, 255) + love.graphics.print(object.text, x + leftpadding + 2 + iconwidth, object.y + 2) + end + + object:SetWidth(width + 5) + +end + +function skin.DrawTreeNodeButton(object) + + local leftpadding = 15 * object.parent.level + local image + + if object.parent.open then + image = skin.images["tree-node-button-close.png"] + else + image = skin.images["tree-node-button-open.png"] + end + + image:setFilter("nearest", "nearest") + + love.graphics.setColor(255, 255, 255, 255) + love.graphics.draw(image, object.x, object.y) + + object:SetPos(2 + leftpadding, 3) + object:SetSize(image:getWidth(), image:getHeight()) + +end + -- register the skin loveframes.skins.Register(skin) \ No newline at end of file