feat: improve font handling, add wrapper error type
This commit is contained in:
parent
27b7b25814
commit
3e656671d9
2 changed files with 91 additions and 37 deletions
56
src/font.rs
56
src/font.rs
|
@ -1,13 +1,57 @@
|
|||
use pango::{prelude::FontMapExt, Font, FontDescription};
|
||||
use std::fmt::Display;
|
||||
|
||||
use pango::{
|
||||
prelude::{FontExt, FontMapExt},
|
||||
Font as PangoFont, FontDescription, Language, SCALE,
|
||||
};
|
||||
use pangocairo::FontMap;
|
||||
|
||||
pub trait FontExt {
|
||||
fn load_from_string(value: &str) -> Option<Font> {
|
||||
pub struct Font {
|
||||
font: PangoFont,
|
||||
language: Language,
|
||||
}
|
||||
|
||||
impl Font {
|
||||
pub fn new(font: PangoFont) -> Self {
|
||||
Self {
|
||||
font,
|
||||
language: Language::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_language(self, language: Language) -> Self {
|
||||
Self { language, ..self }
|
||||
}
|
||||
|
||||
pub fn family(&self) -> String {
|
||||
self.font.describe().family().unwrap().to_string()
|
||||
}
|
||||
|
||||
pub fn size(&self) -> i32 {
|
||||
self.font.describe().size() / SCALE
|
||||
}
|
||||
|
||||
pub fn height(&self) -> i32 {
|
||||
self.font.metrics(Some(&self.language)).height() / SCALE
|
||||
}
|
||||
|
||||
pub fn load_from_string(family: &str, size: usize) -> Option<Font> {
|
||||
let font_str = format!("{family} {size}");
|
||||
let fontmap = FontMap::default();
|
||||
let context = fontmap.create_context();
|
||||
let desc = FontDescription::from_string(value);
|
||||
fontmap.load_font(&context, &desc)
|
||||
let desc = FontDescription::from_string(&font_str);
|
||||
fontmap.load_font(&context, &desc).map(Font::new)
|
||||
}
|
||||
}
|
||||
|
||||
impl FontExt for pango::Font {}
|
||||
impl Default for Font {
|
||||
fn default() -> Self {
|
||||
Font::load_from_string("monospace", 10).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Font {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "\"{}\" {}", self.family(), self.size())
|
||||
}
|
||||
}
|
||||
|
|
72
src/lib.rs
72
src/lib.rs
|
@ -1,48 +1,58 @@
|
|||
pub mod color;
|
||||
pub mod font;
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
use color::ColorPair;
|
||||
use font::FontExt;
|
||||
use pango::{prelude::FontExt as _, Font, Language, SCALE};
|
||||
use font::Font;
|
||||
use wmenu_rs::{Menu as WMenu, MenuError};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
WMenu(MenuError),
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Error::WMenu(menu_error) => write!(f, "{menu_error}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
impl From<MenuError> for Error {
|
||||
fn from(value: MenuError) -> Self {
|
||||
Self::WMenu(value)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Config {
|
||||
pub bottom: bool,
|
||||
pub padding: usize,
|
||||
pub lines: i32,
|
||||
pub font: String,
|
||||
pub font_size: u8,
|
||||
pub font_family: String,
|
||||
pub font_size: usize,
|
||||
pub language: Option<String>,
|
||||
pub normal_color: ColorPair,
|
||||
pub prompt_color: ColorPair,
|
||||
pub selection_color: ColorPair,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
// TODO: add font struct to handle these methods
|
||||
fn font_string(&self) -> String {
|
||||
format!("{} {}", self.font, self.font_size)
|
||||
}
|
||||
|
||||
fn font_height(&self, font: &str) -> i32 {
|
||||
let font = Font::load_from_string(font).unwrap();
|
||||
// TODO: let user pick language
|
||||
let metrics = font.metrics(Some(&Language::default()));
|
||||
|
||||
metrics.height() / SCALE
|
||||
}
|
||||
|
||||
// TODO: add ability to override height/line_height
|
||||
fn apply(self, wmenu: &mut WMenu) {
|
||||
let font_string = self.font_string();
|
||||
let font_height = self.font_height(&font_string);
|
||||
let font =
|
||||
Font::load_from_string(self.font_family.as_str(), self.font_size).unwrap_or_default();
|
||||
|
||||
let font_height = font.height();
|
||||
let line_height = font_height + 2;
|
||||
|
||||
let mut height = line_height;
|
||||
|
||||
// FIXME: ugly
|
||||
if self.lines > 0 {
|
||||
height = height + height * self.lines;
|
||||
}
|
||||
let height = if self.lines > 0 {
|
||||
line_height + line_height * self.lines
|
||||
} else {
|
||||
line_height
|
||||
};
|
||||
|
||||
wmenu
|
||||
.height(height)
|
||||
|
@ -50,7 +60,7 @@ impl Config {
|
|||
.padding(self.padding.try_into().unwrap())
|
||||
.lines(self.lines.try_into().unwrap())
|
||||
.line_height(line_height)
|
||||
.font(&font_string)
|
||||
.font(&font.to_string())
|
||||
.normal_bg(self.normal_color.bg.into())
|
||||
.normal_fg(self.normal_color.fg.into())
|
||||
.prompt_bg(self.prompt_color.bg.into())
|
||||
|
@ -66,8 +76,9 @@ impl Default for Config {
|
|||
bottom: false,
|
||||
lines: 0,
|
||||
padding: 16,
|
||||
font: "monospace".to_string(),
|
||||
font_family: "monospace".to_string(),
|
||||
font_size: 12,
|
||||
language: None,
|
||||
normal_color: (0x222222ff, 0xbbbbbbffu32).into(),
|
||||
prompt_color: (0x005577ff, 0xeeeeeeffu32).into(),
|
||||
selection_color: (0x005577ff, 0x227799ffu32).into(),
|
||||
|
@ -104,9 +115,8 @@ impl Menu {
|
|||
self
|
||||
}
|
||||
|
||||
// TODO: wrap MenuError with new error type
|
||||
pub fn run(&self) -> Result<String, MenuError> {
|
||||
self.inner().run()
|
||||
pub fn run(&self) -> Result<String, Error> {
|
||||
Ok(self.inner().run()?)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue