|
-- The MIT License (MIT) |
|
-- |
|
-- Copyright © 2021 Jens Hofschröer |
|
-- |
|
-- 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. |
|
-- |
|
utf8 = require("utf8") |
|
|
|
local buttonCounter = 0 |
|
|
|
Button = { |
|
basefont = love.graphics.getFont(), |
|
useChars = false, |
|
bgcol={0.5,0.5,.66}, |
|
hicol={0.55,0.55,.726}, |
|
locol={0.45,0.45,.594} |
|
} |
|
|
|
local function inShape(x,y,left,top,width,height) |
|
return x>left and x<left+width and y>top and y<top+height |
|
end |
|
|
|
Button.drawAll = function(buttons) |
|
for i=1,#buttons do |
|
if buttons[i].visible ~= false then |
|
buttons[i]:draw() |
|
end |
|
end |
|
end |
|
|
|
Button.findAction = function(x,y,buttons) |
|
for i,button in ipairs(buttons) do |
|
if button.enabled and inShape(x,y,unpack(button:getBounds())) then |
|
return { |
|
name="btn_"..button.name, |
|
action=button.action |
|
} |
|
end |
|
end |
|
return { |
|
name="none", |
|
action=function() end |
|
} |
|
end |
|
|
|
function Button:new(title, action, posx, posy, alignment) |
|
local b={} |
|
setmetatable(b, self) |
|
self.__index = self |
|
|
|
buttonCounter=buttonCounter+1 |
|
|
|
if title ~= nil then |
|
local f = self.basefont |
|
|
|
b.name = 'btn'..buttonCounter |
|
b.title = love.graphics.newText(f, title) |
|
b.enabled = true |
|
b.btnAction = action or function() end |
|
b.action = function() |
|
b.btnAction(b) |
|
end |
|
b.posx = math.floor(posx or 0) |
|
b.posy = math.floor(posy or 0) |
|
b.width = b.title:getWidth()+16 |
|
b.height = b.title:getHeight()+8 |
|
b.tx = (b.width-b.title:getWidth())/2 |
|
b.ty = (b.height-b.title:getHeight())/2 |
|
|
|
Button.updateAlignment(b, alignment) |
|
end |
|
return b |
|
end |
|
|
|
function Button:getBounds() |
|
return { |
|
self.posx,self.posy, |
|
self.width,self.height |
|
} |
|
end |
|
|
|
function Button:setLocation(x,y,alignment) |
|
self.posx = math.floor(x) |
|
self.posy = math.floor(y) |
|
self:updateAlignment(alignment) |
|
end |
|
|
|
function Button:updateAlignment(alignment) |
|
|
|
if alignment~=nil then |
|
if alignment=="BL" then |
|
self.posy = self.posy - self.height |
|
elseif alignment=="BR" then |
|
self.posx = self.posx - self.width |
|
self.posy = self.posy - self.height |
|
elseif alignment=="TR" then |
|
self.posx = self.posx - self.width |
|
end |
|
end |
|
|
|
print("button @"..self.posx.."x"..self.posy.." with "..self.width.."x"..self.height) |
|
end |
|
|
|
function Button:checkAction(x,y) |
|
if self.action ~= nil |
|
and x>self.posx and x<self.width |
|
and y>self.posy and y<self.height then |
|
self.action(self) |
|
end |
|
end |
|
|
|
Button.drawShadowText = function(text,x,y,enabled) |
|
-- love.graphics.rectangle("line", self.title, self.posx, self.posy, self.width, self.height) |
|
if enabled == true then |
|
local r,g,b=love.graphics.getColor() |
|
love.graphics.setColor(0,0,0) |
|
love.graphics.draw(text, x+1, y+1) |
|
love.graphics.setColor(r,g,b) |
|
love.graphics.draw(text, x, y) |
|
else |
|
love.graphics.setColor(.66,.66,.66) |
|
love.graphics.draw(text, x, y) |
|
end |
|
end |
|
|
|
function Button:draw() |
|
self:drawRect(false) |
|
end |
|
|
|
function Button:drawRect(pressed) |
|
local px=0 |
|
local py=0 |
|
if pressed== true then |
|
px=-1 |
|
py=-1 |
|
end |
|
love.graphics.push() |
|
love.graphics.setColor(self.bgcol) |
|
love.graphics.rectangle("fill", self.posx, self.posy, self.width, self.height) |
|
if pressed==true then love.graphics.setColor(self.locol) else love.graphics.setColor(self.hicol) end |
|
love.graphics.line(self.posx, self.posy, self.posx+self.width, self.posy) |
|
love.graphics.line(self.posx, self.posy, self.posx, self.posy+self.height) |
|
if pressed==true then love.graphics.setColor(self.hicol) else love.graphics.setColor(self.locol) end |
|
love.graphics.line(self.posx+self.width, self.posy+self.height, self.posx+self.width, self.posy) |
|
love.graphics.line(self.posx+self.width, self.posy+self.height, self.posx, self.posy+self.height) |
|
|
|
love.graphics.setColor(1,1,1) |
|
Button.drawShadowText(self.title, px+self.posx+self.tx, py+self.posy+self.ty, self.enabled) |
|
love.graphics.pop() |
|
end |
|
|
|
Selectable=Button:new() |
|
function Selectable:new(title, action, posx, posy, alignment) |
|
local btn = Button.new(self,title, function(context) |
|
context:setChecked(not context.selected) |
|
action(context) |
|
end, posx, posy, alignment) |
|
btn.selected = false |
|
return btn |
|
end |
|
function Selectable:setChecked(checked) |
|
self.selected = checked |
|
print("changed to "..tostring(self.selected)) |
|
end |
|
function Selectable:draw() |
|
self:drawRect(self.selected) |
|
end |
|
|
|
|
|
Checkbox=Selectable:new() |
|
function Checkbox:new(...) |
|
local c = Selectable.new(self, ...) |
|
if self.useChars then |
|
c.checkedText = love.graphics.newText(Button.basefont, utf8.char(9746)) |
|
c.uncheckedText = love.graphics.newText(Button.basefont, utf8.char(9744)) |
|
c.width = c.width + c.uncheckedText:getWidth()+4 |
|
elseif c.title ~= nil then |
|
c.width = c.width + c.title:getHeight()+4 |
|
end |
|
return c |
|
end |
|
function Checkbox:draw() |
|
love.graphics.push() |
|
local dx |
|
if self.useChars then |
|
local t = self.uncheckedText |
|
if self.selected then t = self.checkedText end |
|
Button.drawShadowText(t, self.posx+self.tx, self.posy+self.ty, self.enabled) |
|
dx = t:getWidth() |
|
else |
|
dx = self.title:getHeight() |
|
love.graphics.rectangle("line", self.posx+self.tx,self.posy+self.ty,dx,dx) |
|
if self.selected then |
|
love.graphics.line(self.posx+self.tx,self.posy+self.ty,self.posx+self.tx+dx,self.posy+self.ty+dx) |
|
love.graphics.line(self.posx+self.tx,self.posy+self.ty+dx,self.posx+self.tx+dx,self.posy+self.ty) |
|
end |
|
end |
|
Button.drawShadowText(self.title, dx+4+self.posx+self.tx, self.posy+self.ty, self.enabled) |
|
love.graphics.pop() |
|
end |
|
|
|
Radiobutton=Selectable:new() |
|
function Radiobutton:new(...) |
|
local c = Selectable.new(self, ...) |
|
if self.useChars then |
|
c.checkedText = love.graphics.newText(Button.basefont, utf8.char(9673)) |
|
c.uncheckedText = love.graphics.newText(Button.basefont, utf8.char(9675)) |
|
c.width = c.width + c.uncheckedText:getWidth()+4 |
|
elseif c.title ~= nil then |
|
c.width = c.width + c.title:getHeight()+4 |
|
end |
|
c.group = {} |
|
return c |
|
end |
|
function Radiobutton:setGroup(group) |
|
self.group = group |
|
end |
|
function Radiobutton:setChecked(checked) |
|
print(tostring(self.title)..":"..tostring(checked).."/"..tostring(self.selected)) |
|
if checked==true and self.selected == false then |
|
for i,btn in ipairs(self.group) do |
|
if btn ~= self then |
|
btn.selected = false |
|
btn:setChecked(false) |
|
end |
|
end |
|
self.selected = checked |
|
end |
|
end |
|
function Radiobutton:draw() |
|
love.graphics.push() |
|
local dx |
|
if self.useChars then |
|
local t = self.uncheckedText |
|
if self.selected then t = self.checkedText end |
|
Button.drawShadowText(t, self.posx+self.tx, self.posy+self.ty, self.enabled) |
|
dx=t:getWidth() |
|
else |
|
dx = self.title:getHeight() |
|
love.graphics.circle("line", self.posx+self.tx+dx/2,self.posy+self.ty+dx/2,dx/2) |
|
if self.selected then |
|
love.graphics.circle("fill", self.posx+self.tx+dx/2,self.posy+self.ty+dx/2,dx/4) |
|
end |
|
end |
|
Button.drawShadowText(self.title, dx+4+self.posx+self.tx, self.posy+self.ty, self.enabled) |
|
love.graphics.pop() |
|
end |