Merge remote-tracking branch 'origin/border-less-window'

This commit is contained in:
Francesco Abbate
2021-04-21 08:42:57 +02:00
28 changed files with 496 additions and 25 deletions
+2
View File
@@ -28,6 +28,8 @@ command.add(nil, {
["core:toggle-fullscreen"] = function()
fullscreen = not fullscreen
system.set_window_mode(fullscreen and "fullscreen" or "normal")
core.show_title_bar(not fullscreen)
core.title_view:configure_hit_test(not fullscreen)
end,
["core:reload-module"] = function()
+1
View File
@@ -22,6 +22,7 @@ config.transitions = true
config.animation_rate = 1.0
config.blink_period = 0.8
config.draw_whitespace = false
config.borderless = true
-- Disable plugin loading setting to false the config entry
-- of the same name.
+86 -6
View File
@@ -6,6 +6,7 @@ local command
local keymap
local RootView
local StatusView
local TitleView
local CommandView
local NagView
local DocView
@@ -358,6 +359,7 @@ function core.init()
keymap = require "core.keymap"
RootView = require "core.rootview"
StatusView = require "core.statusview"
TitleView = require "core.titleview"
CommandView = require "core.commandview"
NagView = require "core.nagview"
DocView = require "core.docview"
@@ -402,6 +404,7 @@ function core.init()
core.clip_rect_stack = {{ 0,0,0,0 }}
core.log_items = {}
core.docs = {}
core.window_mode = "normal"
core.threads = setmetatable({}, { __mode = "k" })
core.blink_start = system.get_time()
core.blink_timer = core.blink_start
@@ -432,9 +435,12 @@ function core.init()
core.command_view = CommandView()
core.status_view = StatusView()
core.nag_view = NagView()
core.title_view = TitleView()
local cur_node = core.root_view.root_node
cur_node.is_primary_node = true
cur_node:split("up", core.title_view, {y = true})
cur_node = cur_node.b
cur_node:split("up", core.nag_view, {y = true})
cur_node = cur_node.b
cur_node = cur_node:split("down", core.command_view, {y = true})
@@ -443,7 +449,7 @@ function core.init()
core.project_scan_thread_id = core.add_thread(project_scan_thread)
command.add_defaults()
local got_user_error = not core.load_user_directory()
local got_plugin_error = not core.load_plugins()
local plugins_success, plugins_refuse_list = core.load_plugins()
do
local pdir, pname = project_dir_abs:match("(.*)[/\\\\](.*)")
@@ -459,9 +465,35 @@ function core.init()
core.error(delayed_error)
end
if got_plugin_error or got_user_error or got_project_error then
if not plugins_success or got_user_error or got_project_error then
command.perform("core:open-log")
end
system.set_window_bordered(not config.borderless)
core.title_view:configure_hit_test(config.borderless)
core.title_view.visible = config.borderless
if #plugins_refuse_list.userdir.plugins > 0 or #plugins_refuse_list.datadir.plugins > 0 then
local opt = {
{ font = style.font, text = "Exit", default_no = true },
{ font = style.font, text = "Continue" , default_yes = true }
}
local msg = {}
for _, entry in pairs(plugins_refuse_list) do
if #entry.plugins > 0 then
msg[#msg + 1] = string.format("Plugins from directory \"%s\":\n%s", common.home_encode(entry.dir), table.concat(entry.plugins, "\n"))
end
end
core.nag_view:show(
"Refused Plugins",
string.format(
"Some plugins are not loaded due to version mismatch.\n\n%s.\n\n" ..
"Please download a recent version from https://github.com/franko/lite-plugins.",
table.concat(msg, ".\n\n")),
opt, function(item)
if item.text == "Exit" then os.exit(1) end
end)
end
end
@@ -554,14 +586,53 @@ function core.restart()
end
local function version_components(version)
local a, b, c = version:match('(%d+)%.(%d+)%.(%d+)')
if a then
return tonumber(a), tonumber(b), tonumber(c)
end
a, b = version:match('(%d+)%.(%d+)')
if a then
return tonumber(a), tonumber(b)
end
end
local function check_plugin_version(filename)
local f = io.open(filename, "r")
if not f then return false end
local version_match = false
for line in f:lines() do
local version = line:match('%-%-%s*lite%-xl%s*(%d+%.%d+)%s*$')
if not version then break end
local ver_major, ver_minor = version_components(version)
local ref_major, ref_minor = version_components(VERSION)
version_match = (ver_major == ref_major and ver_minor == ref_minor)
break
end
f:close()
return version_match
end
function core.load_plugins()
local no_errors = true
local refused_list = {
userdir = {dir = USERDIR, plugins = {}},
datadir = {dir = DATADIR, plugins = {}},
}
for _, root_dir in ipairs {USERDIR, DATADIR} do
local plugin_dir = root_dir .. "/plugins"
local files = system.list_dir(plugin_dir)
for _, filename in ipairs(files or {}) do
local basename = filename:match("(.-)%.lua$") or filename
if config[basename] ~= false then
local version_match = check_plugin_version(plugin_dir .. '/' .. filename)
if not version_match then
core.log_quiet("Version mismatch for plugin %q from %s", basename, plugin_dir)
local ls = refused_list[root_dir == USERDIR and 'userdir' or 'datadir'].plugins
ls[#ls + 1] = filename
end
if version_match and config[basename] ~= false then
local modname = "plugins." .. basename
local ok = core.try(require, modname)
if ok then core.log_quiet("Loaded plugin %q from %s", basename, plugin_dir) end
@@ -571,7 +642,7 @@ function core.load_plugins()
end
end
end
return no_errors
return no_errors, refused_list
end
@@ -624,6 +695,11 @@ function core.set_active_view(view)
end
function core.show_title_bar(show)
core.title_view.visible = show
end
function core.add_thread(f, weak_ref)
local key = weak_ref or #core.threads + 1
local fn = function() return core.try(f) end
@@ -741,6 +817,10 @@ function core.on_event(type, ...)
core.root_view:on_mouse_released(...)
elseif type == "mousewheel" then
core.root_view:on_mouse_wheel(...)
elseif type == "resized" then
core.window_mode = system.get_window_mode()
elseif type == "minimized" or type == "maximized" or type == "restored" then
core.window_mode = type == "restored" and "normal" or type
elseif type == "filedropped" then
local filename, mx, my = ...
local info = system.get_file_info(filename)
@@ -769,7 +849,7 @@ local function get_title_filename(view)
end
local function compose_window_title(title)
function core.compose_window_title(title)
return title == "" and "Lite XL" or title .. " - Lite XL"
end
@@ -818,7 +898,7 @@ function core.step()
-- update window title
local current_title = get_title_filename(core.active_view)
if current_title ~= core.window_title then
system.set_window_title(compose_window_title(current_title))
system.set_window_title(core.compose_window_title(current_title))
core.window_title = current_title
end
+44 -15
View File
@@ -1,6 +1,7 @@
local core = require "core"
local command = require "core.command"
local common = require "core.common"
local config = require "core.config"
local View = require "core.view"
local style = require "core.style"
@@ -23,24 +24,33 @@ function NagView:get_title()
return self.title
end
function NagView:get_options_line_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
-- The two methods below are duplicated from DocView
function NagView:get_line_height()
return math.floor(style.font:get_height() * config.line_height)
end
function NagView:get_line_height()
return self.max_lh + 2 * BORDER_WIDTH + 2 * style.padding.y
function NagView:get_line_text_y_offset()
local lh = self:get_line_height()
local th = style.font:get_height()
return (lh - th) / 2
end
-- Buttons height without padding
function NagView:get_buttons_height()
local lh = style.font:get_height()
local bt_padding = lh / 2
return lh + 2 * BORDER_WIDTH + 2 * bt_padding
end
function NagView:get_target_height()
return self.target_height + 2 * style.padding.y
end
function NagView:update()
NagView.super.update(self)
if core.active_view == self and self.title then
self:move_towards(self.size, "y", self:get_line_height())
self:move_towards(self.size, "y", self:get_target_height())
self:move_towards(self, "underline_progress", 1)
else
self:move_towards(self.size, "y", 0)
@@ -68,10 +78,10 @@ function NagView:each_option()
return coroutine.wrap(function()
if not self.options then return end
local opt, bw,bh,ox,oy
bh = self.max_lh + 2 * BORDER_WIDTH + style.padding.y
bh = self:get_buttons_height()
ox,oy = self:get_content_offset()
ox = ox + self.size.x
oy = oy + (self.size.y / 2) - (bh / 2)
oy = oy + self.size.y - bh - style.padding.y
for i = #self.options, 1, -1 do
opt = self.options[i]
@@ -112,6 +122,7 @@ function NagView:on_text_input(text)
end
end
function NagView:draw()
if self.size.y <= 0 or not self.title then return end
@@ -129,7 +140,13 @@ function NagView:draw()
end
-- draw message
common.draw_text(style.font, style.nagbar_text, self.message, "left", ox, oy, self.size.x, self.size.y)
local lh = style.font:get_height() * config.line_height
oy = oy + style.padding.y + (self.target_height - self:get_message_height()) / 2
for msg_line in self.message:gmatch("(.-)\n") do
local ty = oy + self:get_line_text_y_offset()
renderer.draw_text(style.font, msg_line, ox, ty, style.nagbar_text)
oy = oy + lh
end
-- draw buttons
for i, opt, bx,by,bw,bh in self:each_option() do
@@ -159,14 +176,26 @@ local function findindex(tbl, prop)
end
end
function NagView:get_message_height()
local h = 0
for str in string.gmatch(self.message, "(.-)\n") do
h = h + style.font:get_height() * config.line_height
end
return h
end
function NagView:next()
local opts = table.remove(self.queue, 1) or {}
self.title = opts.title
self.message = opts.message
self.message = opts.message and opts.message .. "\n"
self.options = opts.options
self.on_selected = opts.on_selected
if self.message and self.options then
self.max_lh = math.max(style.font:get_height(self.message), self:get_options_line_height())
local message_height = self:get_message_height()
-- self.target_height is the nagview height needed to display the message and
-- the buttons, excluding the top and bottom padding space.
self.target_height = math.max(message_height, self:get_buttons_height())
self:change_hovered(findindex(self.options, "default_yes"))
end
self.force_focus = self.message ~= nil
+119
View File
@@ -0,0 +1,119 @@
local core = require "core"
local common = require "core.common"
local style = require "core.style"
local View = require "core.view"
local restore_command = {
symbol = "w", action = function() system.set_window_mode("normal") end
}
local maximize_command = {
symbol = "W", action = function() system.set_window_mode("maximized") end
}
local title_commands = {
{symbol = "_", action = function() system.set_window_mode("minimized") end},
maximize_command,
{symbol = "X", action = function() core.quit() end},
}
local TitleView = View:extend()
local function title_view_height()
return style.font:get_height() + style.padding.y * 2
end
function TitleView:new()
TitleView.super.new(self)
self.visible = true
end
function TitleView:configure_hit_test(borderless)
if borderless then
local title_height = title_view_height()
local icon_w = style.icon_font:get_width("_")
local icon_spacing = icon_w
local controls_width = (icon_w + icon_spacing) * #title_commands + icon_spacing
system.set_window_hit_test(title_height, controls_width, icon_spacing)
-- core.hit_test_title_height = title_height
else
system.set_window_hit_test()
end
end
function TitleView:update()
self.size.y = self.visible and title_view_height() or 0
title_commands[2] = core.window_mode == "maximized" and restore_command or maximize_command
TitleView.super.update(self)
end
function TitleView:draw_window_title()
local h = style.font:get_height()
local ox, oy = self:get_content_offset()
local color = style.text
local x, y = ox + style.padding.x, oy + style.padding.y
x = common.draw_text(style.icon_font, color, "M ", nil, x, y, 0, h)
local title = core.compose_window_title(core.window_title)
common.draw_text(style.font, color, title, nil, x, y, 0, h)
end
function TitleView:each_control_item()
local icon_h, icon_w = style.icon_font:get_height(), style.icon_font:get_width("_")
local icon_spacing = icon_w
local ox, oy = self:get_content_offset()
ox = ox + self.size.x
local i, n = 0, #title_commands
local iter = function()
i = i + 1
if i <= n then
local dx = - (icon_w + icon_spacing) * (n - i + 1)
local dy = style.padding.y
return title_commands[i], ox + dx, oy + dy, icon_w, icon_h
end
end
return iter
end
function TitleView:draw_window_controls()
for item, x, y, w, h in self:each_control_item() do
local color = item == self.hovered_item and style.text or style.dim
common.draw_text(style.icon_font, color, item.symbol, nil, x, y, 0, h)
end
end
function TitleView:on_mouse_pressed(button, x, y, clicks)
local caught = TitleView.super.on_mouse_pressed(self, button, x, y, clicks)
if caught then return end
core.set_active_view(core.last_active_view)
if self.hovered_item then
self.hovered_item.action()
end
end
function TitleView:on_mouse_moved(px, py, ...)
if self.size.y == 0 then return end
TitleView.super.on_mouse_moved(self, px, py, ...)
self.hovered_item = nil
local x_min, x_max, y_min, y_max = self.size.x, 0, self.size.y, 0
for item, x, y, w, h in self:each_control_item() do
x_min, x_max = math.min(x, x_min), math.max(x + w, x_max)
y_min, y_max = y, y + h
if px > x and py > y and px <= x + w and py <= y + h then
self.hovered_item = item
return
end
end
end
function TitleView:draw()
self:draw_background(style.background2)
self:draw_window_title()
self:draw_window_controls()
end
return TitleView