188 lines
5.3 KiB
Lua
188 lines
5.3 KiB
Lua
-- This file is part of SUIT, copyright (c) 2016 Matthias Richter
|
|
|
|
local BASE = (...):match('(.-)[^%.]+$')
|
|
|
|
local theme = {}
|
|
theme.cornerRadius = 4
|
|
|
|
theme.color = {
|
|
normal = {bg = { 0.25, 0.25, 0.25}, fg = {0.73,0.73,0.73}},
|
|
hovered = {bg = { 0.19,0.6,0.73}, fg = {1,1,1}},
|
|
active = {bg = {1,0.6, 0}, fg = {1,1,1}}
|
|
}
|
|
|
|
|
|
-- HELPER
|
|
function theme.getColorForState(opt)
|
|
local s = opt.state or "normal"
|
|
return (opt.color and opt.color[opt.state]) or theme.color[s]
|
|
end
|
|
|
|
function theme.drawBox(x,y,w,h, colors, cornerRadius, outline, scale)
|
|
colors = colors or theme.getColorForState(opt)
|
|
cornerRadius = (cornerRadius or theme.cornerRadius)
|
|
w = math.max(cornerRadius/2, w)
|
|
if h < cornerRadius/2 then
|
|
y,h = y - (cornerRadius - h), cornerRadius/2
|
|
end
|
|
|
|
-- by default, scale will operate about the center of the box. meaning it grows
|
|
-- out/in in all directions
|
|
if scale and scale ~= 1.0 then
|
|
local baseW, baseH = w, h
|
|
w = w * scale
|
|
h = h * scale
|
|
x = x - (w - baseW) / 2
|
|
y = y - (h - baseH) / 2
|
|
cornerRadius = cornerRadius * scale
|
|
end
|
|
|
|
love.graphics.setColor(colors.bg)
|
|
love.graphics.rectangle('fill', x,y, w,h, cornerRadius)
|
|
if outline ~= nil then
|
|
love.graphics.setColor(colors.fg)
|
|
love.graphics.setLineWidth(outline)
|
|
love.graphics.rectangle('line', x,y, w,h, cornerRadius)
|
|
end
|
|
end
|
|
|
|
function theme.getVerticalOffsetForAlign(valign, font, h)
|
|
if valign == "top" then
|
|
return 0
|
|
elseif valign == "bottom" then
|
|
return h - font:getHeight()
|
|
end
|
|
-- else: "middle"
|
|
return (h - font:getHeight()) / 2
|
|
end
|
|
|
|
-- WIDGET VIEWS
|
|
function theme.Label(text, opt, x,y,w,h)
|
|
y = y + theme.getVerticalOffsetForAlign(opt.valign, opt.font, h)
|
|
|
|
love.graphics.setColor((opt.color and opt.color.normal or {}).fg or theme.color.normal.fg)
|
|
love.graphics.setFont(opt.font)
|
|
love.graphics.printf(text, x+2, y, w-4, opt.align or "center")
|
|
end
|
|
|
|
function theme.Button(text, opt, x,y,w,h)
|
|
local c = theme.getColorForState(opt)
|
|
local scale = opt.scale or 1.0
|
|
|
|
theme.drawBox(x,y,w,h, c, opt.cornerRadius, opt.outline, scale)
|
|
love.graphics.setColor(c.fg)
|
|
love.graphics.setFont(opt.font)
|
|
|
|
-- ensure text remains aligned regardless of scale
|
|
local align = opt.align or "center"
|
|
local textX = x
|
|
local textY = y
|
|
local textW = w
|
|
if scale ~= 1.0 then
|
|
-- For center alignment, shift x so the scaled text stays centered
|
|
if align == "center" then
|
|
textX = x + (w - w * scale) / 2
|
|
elseif align == "right" then
|
|
textX = x + (w - w * scale)
|
|
end
|
|
end
|
|
|
|
y = y + theme.getVerticalOffsetForAlign(opt.valign, opt.font, h)
|
|
love.graphics.printf(text, textX+2, textY, textW-4,
|
|
align,
|
|
0,
|
|
scale,
|
|
scale
|
|
)
|
|
end
|
|
|
|
function theme.Checkbox(chk, opt, x,y,w,h)
|
|
local c = theme.getColorForState(opt)
|
|
local th = opt.font:getHeight()
|
|
|
|
theme.drawBox(x+h/10,y+h/10,h*.8,h*.8, c, opt.cornerRadius)
|
|
love.graphics.setColor(c.fg)
|
|
if chk.checked then
|
|
love.graphics.setLineStyle('smooth')
|
|
love.graphics.setLineWidth(5)
|
|
love.graphics.setLineJoin("bevel")
|
|
love.graphics.line(x+h*.2,y+h*.55, x+h*.45,y+h*.75, x+h*.8,y+h*.2)
|
|
end
|
|
|
|
if chk.text then
|
|
love.graphics.setFont(opt.font)
|
|
y = y + theme.getVerticalOffsetForAlign(opt.valign, opt.font, h)
|
|
love.graphics.printf(chk.text, x + h, y, w - h, opt.align or "left")
|
|
end
|
|
end
|
|
|
|
function theme.Slider(fraction, opt, x,y,w,h)
|
|
local xb, yb, wb, hb -- size of the progress bar
|
|
local r = math.min(w,h) / 2.1
|
|
if opt.vertical then
|
|
x, w = x + w*.25, w*.5
|
|
xb, yb, wb, hb = x, y+h*(1-fraction), w, h*fraction
|
|
else
|
|
y, h = y + h*.25, h*.5
|
|
xb, yb, wb, hb = x,y, w*fraction, h
|
|
end
|
|
|
|
local c = theme.getColorForState(opt)
|
|
theme.drawBox(x,y,w,h, c, opt.cornerRadius)
|
|
theme.drawBox(xb,yb,wb,hb, {bg=c.fg}, opt.cornerRadius)
|
|
|
|
if opt.state ~= nil and opt.state ~= "normal" then
|
|
love.graphics.setColor((opt.color and opt.color.active or {}).fg or theme.color.active.fg)
|
|
if opt.vertical then
|
|
love.graphics.circle('fill', x+wb/2, yb, r)
|
|
else
|
|
love.graphics.circle('fill', x+wb, yb+hb/2, r)
|
|
end
|
|
end
|
|
end
|
|
|
|
function theme.Input(input, opt, x,y,w,h)
|
|
local utf8 = require 'utf8'
|
|
theme.drawBox(x,y,w,h, (opt.color and opt.color.normal) or theme.color.normal, opt.cornerRadius)
|
|
x = x + 3
|
|
w = w - 6
|
|
|
|
local th = opt.font:getHeight()
|
|
|
|
-- set scissors
|
|
local sx, sy, sw, sh = love.graphics.getScissor()
|
|
love.graphics.setScissor(x-1,y,w+2,h)
|
|
x = x - input.text_draw_offset
|
|
|
|
-- text
|
|
love.graphics.setColor((opt.color and opt.color.normal and opt.color.normal.fg) or theme.color.normal.fg)
|
|
love.graphics.setFont(opt.font)
|
|
love.graphics.print(input.text, x, y+(h-th)/2)
|
|
|
|
-- candidate text
|
|
local tw = opt.font:getWidth(input.text)
|
|
local ctw = opt.font:getWidth(input.candidate_text.text)
|
|
love.graphics.setColor((opt.color and opt.color.normal and opt.color.normal.fg) or theme.color.normal.fg)
|
|
love.graphics.print(input.candidate_text.text, x + tw, y+(h-th)/2)
|
|
|
|
-- candidate text rectangle box
|
|
love.graphics.rectangle("line", x + tw, y+(h-th)/2, ctw, th)
|
|
|
|
-- cursor
|
|
if opt.hasKeyboardFocus and (love.timer.getTime() % 1) > .5 then
|
|
local ct = input.candidate_text;
|
|
local ss = ct.text:sub(1, utf8.offset(ct.text, ct.start))
|
|
local ws = opt.font:getWidth(ss)
|
|
if ct.start == 0 then ws = 0 end
|
|
|
|
love.graphics.setLineWidth(1)
|
|
love.graphics.setLineStyle('rough')
|
|
love.graphics.line(x + opt.cursor_pos + ws, y + (h-th)/2,
|
|
x + opt.cursor_pos + ws, y + (h+th)/2)
|
|
end
|
|
|
|
-- reset scissor
|
|
love.graphics.setScissor(sx,sy,sw,sh)
|
|
end
|
|
|
|
return theme
|