The logview is now less cluttered. The filename and stack trace (if any) is hidden by default. The user can click on the log entry to expand it.
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
|