dotfiles/.config/lite-xl/libraries/widget/fontdialog.lua

335 lines
9.2 KiB
Lua

--
-- Font Dialog Widget.
-- @copyright Jefferson Gonzalez
-- @license MIT
--
local core = require "core"
local style = require "core.style"
local Button = require "libraries.widget.button"
local CheckBox = require "libraries.widget.checkbox"
local NumberBox = require "libraries.widget.numberbox"
local Dialog = require "libraries.widget.dialog"
local Label = require "libraries.widget.label"
local Line = require "libraries.widget.line"
local SelectBox = require "libraries.widget.selectbox"
local MessageBox = require "libraries.widget.messagebox"
local Fonts = require "libraries.widget.fonts"
---@class widget.fontdialog.fontoptions : renderer.fontoptions
---@field size number
---@class widget.fontdialog : widget.dialog
---@field super widget.dialog
---@field fontdata widget.fontslist.font
---@field preview widget.label
---@field font_size widget.numberbox
---@field choose widget.button
---@field choose_mono widget.button
---@field line widget.line
---@field antialiasing widget.selectbox
---@field hinting widget.selectbox
---@field bold widget.checkbox
---@field italic widget.checkbox
---@field underline widget.checkbox
---@field smoothing widget.checkbox
---@field strikethrough widget.checkbox
---@field save widget.button
---@field cancel widget.button
local FontDialog = Dialog:extend()
---Constructor
---@param font? widget.fontslist.font
---@param options? widget.fontdialog.fontoptions
function FontDialog:new(font, options)
FontDialog.super.new(self, "Font Selector")
self.selected = nil
local this = self
self.type_name = "widget.fontdialog"
self.preview = Label(self.panel, "No Font Selected")
self.preview.border.width = 1
self.preview.clickable = true
self.preview:set_size(100, 100)
function self.preview:on_mouse_enter(...)
Label.super.on_mouse_enter(self, ...)
self.border.color = style.caret
end
function self.preview:on_mouse_leave(...)
Label.super.on_mouse_leave(self, ...)
self.border.color = style.text
end
self.font_size = NumberBox(self.panel, 15, 5)
function self.font_size:on_change()
this:update_preview()
end
self.choose = Button(self.panel, "All")
self.choose:set_icon("D")
self.choose:set_tooltip("Choose a Font")
function self.choose:on_click()
Fonts.show_picker(function(name, path)
local fontdata = {name = name, path = path}
this:set_font(fontdata)
this:update_preview()
end, false)
core.status_view:remove_tooltip()
end
self.choose_mono = Button(self.panel, "Mono")
self.choose_mono:set_icon("D")
self.choose_mono:set_tooltip("Choose a Monospace Font")
function self.choose_mono:on_click()
Fonts.show_picker(function(name, path)
local fontdata = {name = name, path = path}
this:set_font(fontdata)
this:update_preview()
end, true)
core.status_view:remove_tooltip()
end
self.line = Line(self.panel)
self.antialiasing = SelectBox(self.panel, "antialiasing")
self.antialiasing:add_option("None", "none")
self.antialiasing:add_option("Grayscale", "grayscale")
self.antialiasing:add_option("Subpixel", "subpixel")
function self.antialiasing:on_selected()
this:update_preview()
end
self.hinting = SelectBox(self.panel, "hinting")
self.hinting:add_option("None", "none")
self.hinting:add_option("Slight", "slight")
self.hinting:add_option("full", "full")
function self.hinting:on_selected()
this:update_preview()
end
self.bold = CheckBox(self.panel, "Bold")
function self.bold:on_checked()
this:update_preview()
end
self.italic = CheckBox(self.panel, "Italic")
function self.italic:on_checked()
this:update_preview()
end
self.underline = CheckBox(self.panel, "Underline")
function self.underline:on_checked()
this:update_preview()
end
self.smoothing = CheckBox(self.panel, "Smooth")
function self.smoothing:on_checked()
this:update_preview()
end
self.strikethrough = CheckBox(self.panel, "Strike")
function self.strikethrough:on_checked()
this:update_preview()
end
self.save = Button(self.panel, "Save")
self.save:set_icon("S")
function self.save:on_click()
if this.fontdata and this.fontdata.name then
this:on_save(this:get_font(), this:get_options())
this:on_close()
else
MessageBox.error("No font selected", "Please select a font")
end
end
self.cancel = Button(self.panel, "Cancel")
self.cancel:set_icon("C")
function self.cancel:on_click()
this:on_close()
end
if font then
self:set_font(font)
if not options then
self:update_preview()
end
end
if options then
self:set_options(options)
end
end
function FontDialog:update_preview()
local options = self:get_options()
if self.fontdata and self.fontdata.path then
self.preview.font = renderer.font.load(
self.fontdata.path, options.size * SCALE, options
)
if self.fontdata.name then
self.preview:set_label(self.fontdata.name)
end
else
self.preview.font = renderer.font.load(
DATADIR .. "/fonts/FiraSans-Regular.ttf",
options.size * SCALE,
options
)
end
collectgarbage "step"
end
---@param font widget.fontslist.font
function FontDialog:set_font(font)
self.fontdata = font
if self.fontdata.name then
self.preview:set_label(self.fontdata.name)
end
end
---@return widget.fontslist.font
function FontDialog:get_font()
return self.fontdata
end
---@param options widget.fontdialog.fontoptions
function FontDialog:set_options(options)
if options.size then
self.font_size:set_value(tonumber(options.size) or 15)
end
if options.antialiasing then
if options.antialiasing == "none" then
self.antialiasing:set_selected(1)
elseif options.antialiasing == "grayscale" then
self.antialiasing:set_selected(2)
elseif options.antialiasing == "subpixel" then
self.antialiasing:set_selected(3)
end
end
if options.hinting then
if options.hinting == "none" then
self.hinting:set_selected(1)
elseif options.hinting == "slight"then
self.hinting:set_selected(2)
elseif options.hinting == "full" then
self.hinting:set_selected(3)
end
end
if options.bold ~= nil then
self.bold:set_checked(options.bold)
end
if options.italic ~= nil then
self.italic:set_checked(options.italic)
end
if options.underline ~= nil then
self.underline:set_checked(options.underline)
end
if options.smoothing ~= nil then
self.smoothing:set_checked(options.smoothing)
end
if options.strikethrough ~= nil then
self.strikethrough:set_checked(options.strikethrough)
end
end
---@return widget.fontdialog.fontoptions
function FontDialog:get_options()
return {
size = self.font_size:get_value(),
antialiasing = self.antialiasing:get_selected_data() or "none",
hinting = self.hinting:get_selected_data() or "none",
bold = self.bold:is_checked(),
italic = self.italic:is_checked(),
underline = self.underline:is_checked(),
smoothing = self.smoothing:is_checked(),
strikethrough = self.strikethrough:is_checked()
}
end
---Called when the user clicks on save
---@param font widget.fontslist.font
---@param options widget.fontdialog.fontoptions
function FontDialog:on_save(font, options) end
function FontDialog:update()
if not FontDialog.super.update(self) then return false end
self.preview:set_position(style.padding.x/2, style.padding.y/2)
self.font_size:set_position(
style.padding.x/2,
self.preview:get_bottom() + style.padding.y
)
self.choose:set_position(
self.font_size:get_right() + (style.padding.x/2),
self.preview:get_bottom() + style.padding.y
)
self.choose_mono:set_position(
self.choose:get_right() + (style.padding.x/2),
self.preview:get_bottom() + style.padding.y
)
self.line:set_position(
0,
self.font_size:get_bottom() + style.padding.y
)
self.antialiasing:set_position(
style.padding.x/2,
self.line:get_bottom() + style.padding.y
)
self.hinting:set_position(
self.antialiasing:get_right() + (style.padding.x/2),
self.line:get_bottom() + style.padding.y
)
self.bold:set_position(
style.padding.x/2,
self.hinting:get_bottom() + style.padding.y
)
self.italic:set_position(
self.bold:get_right() + style.padding.x,
self.hinting:get_bottom() + style.padding.y
)
self.underline:set_position(
self.italic:get_right() + style.padding.x,
self.hinting:get_bottom() + style.padding.y
)
self.smoothing:set_position(
self.underline:get_right() + style.padding.x,
self.hinting:get_bottom() + style.padding.y
)
self.strikethrough:set_position(
self.smoothing:get_right() + style.padding.x,
self.hinting:get_bottom() + style.padding.y
)
self.save:set_position(
style.padding.x/2,
self.underline:get_bottom() + style.padding.y
)
self.cancel:set_position(
self.save:get_right() + style.padding.x,
self.underline:get_bottom() + style.padding.y
)
self.panel.size.x = self.panel:get_real_width() + style.padding.x
self.panel.size.y = self.panel:get_real_height()
self.size.x = self:get_real_width() - (style.padding.x / 2)
self.size.y = self:get_real_height() + (style.padding.y / 2)
self.line:set_width(self.size.x - style.padding.x)
self.preview:set_size(self.size.x - style.padding.x)
return true
end
return FontDialog