lite-xl/data/core/nagview.lua

149 lines
4.2 KiB
Lua

local core = require "core"
local config = require "core.config"
local common = require "core.common"
local View = require "core.view"
local style = require "core.style"
local BORDER_WIDTH = common.round(2 * SCALE)
local BORDER_PADDING = common.round(5 * SCALE)
local noop = function() end
local NagView = View:extend()
function NagView:new()
NagView.super.new(self)
self.size.y = 0
self.force_focus = false
self.title = "Warning"
self.message = ""
self.options = {}
self.submit = noop
end
function NagView:get_title()
return self.title
end
function NagView:each_option()
return coroutine.wrap(function()
for i = #self.options, 1, -1 do
coroutine.yield(i, self.options[i])
end
end)
end
function NagView:get_options_height()
local max = 0
for _, opt in ipairs(self.options) do
local lh = style.font:get_height(opt.text)
if lh > max then max = lh end
end
return max
end
function NagView:get_line_height()
local maxlh = math.max(style.font:get_height(self.message), self:get_options_height())
return 2 * BORDER_WIDTH + 2 * BORDER_PADDING + maxlh + 2 * style.padding.y
end
function NagView:update()
NagView.super.update(self)
local dest = core.active_view == self and self:get_line_height() or 0
self:move_towards(self.size, "y", dest)
end
function NagView:draw_overlay()
local ox, oy = self:get_content_offset()
oy = oy + self.size.y
local w, h = core.root_view.size.x, core.root_view.size.y - oy
core.root_view:defer_draw(function()
renderer.draw_rect(ox, oy, w, h, style.nagbar_dim)
end)
end
function NagView:each_visible_option()
return coroutine.wrap(function()
local halfh = math.floor(self.size.y / 2)
local ox, oy = self:get_content_offset()
ox = ox + self.size.x - style.padding.x
for i, opt in self:each_option() do
local lw, lh = opt.font:get_width(opt.text), opt.font:get_height(opt.text)
local bw, bh = (lw + 2 * BORDER_WIDTH + 2 * BORDER_PADDING), (lh + 2 * BORDER_WIDTH + 2 * BORDER_PADDING)
local halfbh = math.floor(bh / 2)
local bx, by = math.max(0, ox - bw), math.max(0, oy + halfh - halfbh)
local fw, fh = bw - 2 * BORDER_WIDTH, bh - 2 * BORDER_WIDTH
local fx, fy = bx + BORDER_WIDTH, by + BORDER_WIDTH
coroutine.yield(i, opt, bx,by,bw,bh, fx,fy,fw,fh)
ox = ox - bw - style.padding.x
end
end)
end
function NagView:on_mouse_moved(mx, my, ...)
NagView.super.on_mouse_moved(self, mx, my, ...)
local selected = false
for i, _, x,y,w,h in self:each_visible_option() do
if mx >= x and my >= y and mx < x + w and my < y + h then
self.selected = i
selected = true
break
end
end
if not selected then self.selected = nil end
end
function NagView:on_mouse_pressed(...)
if not NagView.super.on_mouse_pressed(self, ...) and self.selected then
self.force_focus = false
core.set_active_view(core.last_active_view)
self.submit(self.options[self.selected])
end
end
function NagView:draw()
if self.size.y <= 0 then return end
self:draw_overlay()
self:draw_background(style.nagbar)
-- draw message
local ox, oy = self:get_content_offset()
common.draw_text(style.font, style.nagbar_text, self.message, "left", ox + style.padding.x, oy, self.size.x, self.size.y)
-- draw buttons
for i, opt, bx,by,bw,bh, fx,fy,fw,fh in self:each_visible_option() do
local fill = i == self.selected and style.nagbar_text or style.nagbar
local text_color = i == self.selected and style.nagbar or style.nagbar_text
renderer.draw_rect(bx,by,bw,bh, style.nagbar_text)
if i ~= self.selected then
renderer.draw_rect(fx,fy,fw,fh, fill)
end
common.draw_text(opt.font, text_color, opt.text, "center", fx,fy,fw,fh)
end
end
function NagView:show(title, message, options, on_select, on_cancel)
self.title = title or "Warning"
self.message = message or "Empty?"
self.options = options or {}
if on_cancel then table.insert(options, { key = "cancel", font = style.icon_font, text = "C" }) end
self.force_focus = true
self.submit = function(item)
self.submit = noop -- reset the submit function
if item.key == "cancel" and on_cancel then
on_cancel()
elseif on_select then
on_select(item)
end
end
core.set_active_view(self)
end
return NagView