192 lines
4.6 KiB
Lua
192 lines
4.6 KiB
Lua
local core = require "core"
|
|
local common = require "core.common"
|
|
local style = require "core.style"
|
|
local View = require "core.view"
|
|
|
|
|
|
local function lines(text)
|
|
if text == "" then return 0 end
|
|
local l = 1
|
|
for _ in string.gmatch(text, "\n") do
|
|
l = l + 1
|
|
end
|
|
return l
|
|
end
|
|
|
|
|
|
local item_height_result = {}
|
|
|
|
|
|
local function get_item_height(item)
|
|
local h = item_height_result[item]
|
|
if not h then
|
|
h = {}
|
|
local l = 1 + lines(item.text) + lines(item.info or "")
|
|
h.normal = style.font:get_height() + style.padding.y
|
|
h.expanded = l * style.font:get_height() + style.padding.y
|
|
h.current = h.normal
|
|
h.target = h.current
|
|
item_height_result[item] = h
|
|
end
|
|
return h
|
|
end
|
|
|
|
|
|
local LogView = View:extend()
|
|
|
|
LogView.context = "session"
|
|
|
|
function LogView:new()
|
|
LogView.super.new(self)
|
|
self.last_item = core.log_items[#core.log_items]
|
|
self.expanding = {}
|
|
self.scrollable = true
|
|
self.yoffset = 0
|
|
end
|
|
|
|
|
|
function LogView:get_name()
|
|
return "Log"
|
|
end
|
|
|
|
|
|
local function is_expanded(item)
|
|
local item_height = get_item_height(item)
|
|
return item_height.target == item_height.expanded
|
|
end
|
|
|
|
|
|
function LogView:expand_item(item)
|
|
item = get_item_height(item)
|
|
item.target = item.target == item.expanded and item.normal or item.expanded
|
|
table.insert(self.expanding, item)
|
|
end
|
|
|
|
|
|
function LogView:each_item()
|
|
local x, y = self:get_content_offset()
|
|
y = y + style.padding.y + self.yoffset
|
|
return coroutine.wrap(function()
|
|
for i = #core.log_items, 1, -1 do
|
|
local item = core.log_items[i]
|
|
local h = get_item_height(item).current
|
|
coroutine.yield(i, item, x, y, self.size.x, h)
|
|
y = y + h
|
|
end
|
|
end)
|
|
end
|
|
|
|
|
|
function LogView:on_mouse_moved(px, py, ...)
|
|
LogView.super.on_mouse_moved(self, px, py, ...)
|
|
local hovered = false
|
|
for _, item, x, y, w, h in self:each_item() do
|
|
if px >= x and py >= y and px < x + w and py < y + h then
|
|
hovered = true
|
|
self.hovered_item = item
|
|
break
|
|
end
|
|
end
|
|
if not hovered then self.hovered_item = nil end
|
|
end
|
|
|
|
|
|
function LogView:on_mouse_pressed(button, mx, my, clicks)
|
|
if LogView.super.on_mouse_pressed(self, button, mx, my, clicks) then return end
|
|
if self.hovered_item then
|
|
self:expand_item(self.hovered_item)
|
|
end
|
|
end
|
|
|
|
|
|
function LogView:update()
|
|
local item = core.log_items[#core.log_items]
|
|
if self.last_item ~= item then
|
|
self.last_item = item
|
|
self.scroll.to.y = 0
|
|
self.yoffset = -(style.font:get_height() + style.padding.y)
|
|
end
|
|
|
|
local expanding = self.expanding[1]
|
|
if expanding then
|
|
self:move_towards(expanding, "current", expanding.target)
|
|
if expanding.current == expanding.target then
|
|
table.remove(self.expanding, 1)
|
|
end
|
|
end
|
|
|
|
self:move_towards("yoffset", 0)
|
|
|
|
LogView.super.update(self)
|
|
end
|
|
|
|
|
|
local function draw_text_multiline(font, text, x, y, color)
|
|
local th = font:get_height()
|
|
local resx, resy = x, y
|
|
for line in text:gmatch("[^\n]+") do
|
|
resy = y
|
|
resx = renderer.draw_text(style.font, line, x, y, color)
|
|
y = y + th
|
|
end
|
|
return resx, resy
|
|
end
|
|
|
|
|
|
local function draw_text_elipsis(font, color, text, x, y, w, h, elipsis_style)
|
|
elipsis_style = elipsis_style or "end"
|
|
local c = font:get_width("_")
|
|
local approxc = math.floor(w / c)
|
|
if #text > approxc then
|
|
if elipsis_style == "end" then
|
|
text = string.sub(text, 1, approxc - 3) .. "..."
|
|
elseif elipsis_style == "middle" then
|
|
local mid = math.floor(#text / 2)
|
|
text = string.sub(text, 1, mid - 3) .. "..." .. string.sub(text, mid)
|
|
end
|
|
end
|
|
return common.draw_text(font, color, text, "left", x, y, w, h)
|
|
end
|
|
|
|
|
|
function LogView:draw()
|
|
self:draw_background(style.background)
|
|
|
|
local th = style.font:get_height()
|
|
local lh = th + style.padding.y -- for one line
|
|
for _, item, x, y, w, h in self:each_item() do
|
|
core.push_clip_rect(x, y, w, h)
|
|
x = x + style.padding.x
|
|
|
|
local time = os.date(nil, item.time)
|
|
x = common.draw_text(style.font, style.dim, time, "left", x, y, w, lh)
|
|
x = x + style.padding.x
|
|
|
|
x = common.draw_text(style.code_font, style.dim, is_expanded(item) and "-" or "+", "left", x, y, w, lh)
|
|
x = x + style.padding.x
|
|
w = w - (x - self:get_content_offset())
|
|
|
|
if is_expanded(item) then
|
|
y = y + common.round(style.padding.y / 2)
|
|
draw_text_multiline(style.font, item.text, x, y, style.text)
|
|
y = y + th
|
|
|
|
local at = "at " .. common.home_encode(item.at)
|
|
draw_text_elipsis(style.font, style.dim, at, x, y, w, lh, "middle")
|
|
y = y + th
|
|
|
|
if item.info then
|
|
draw_text_multiline(style.font, item.info, x, y, style.dim)
|
|
end
|
|
else
|
|
draw_text_elipsis(style.font, style.text, item.text, x, y, w, lh)
|
|
y = y + th
|
|
end
|
|
|
|
core.pop_clip_rect()
|
|
end
|
|
end
|
|
|
|
|
|
return LogView
|