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
60
src/font.rs
60
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;
|
use pangocairo::FontMap;
|
||||||
|
|
||||||
pub trait FontExt {
|
pub struct Font {
|
||||||
fn load_from_string(value: &str) -> Option<Font> {
|
font: PangoFont,
|
||||||
let fontmap = FontMap::default();
|
language: Language,
|
||||||
let context = fontmap.create_context();
|
}
|
||||||
let desc = FontDescription::from_string(value);
|
|
||||||
fontmap.load_font(&context, &desc)
|
impl Font {
|
||||||
|
pub fn new(font: PangoFont) -> Self {
|
||||||
|
Self {
|
||||||
|
font,
|
||||||
|
language: Language::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontExt for pango::Font {}
|
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(&font_str);
|
||||||
|
fontmap.load_font(&context, &desc).map(Font::new)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 color;
|
||||||
pub mod font;
|
pub mod font;
|
||||||
|
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
use color::ColorPair;
|
use color::ColorPair;
|
||||||
use font::FontExt;
|
use font::Font;
|
||||||
use pango::{prelude::FontExt as _, Font, Language, SCALE};
|
|
||||||
use wmenu_rs::{Menu as WMenu, MenuError};
|
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 struct Config {
|
||||||
pub bottom: bool,
|
pub bottom: bool,
|
||||||
pub padding: usize,
|
pub padding: usize,
|
||||||
pub lines: i32,
|
pub lines: i32,
|
||||||
pub font: String,
|
pub font_family: String,
|
||||||
pub font_size: u8,
|
pub font_size: usize,
|
||||||
|
pub language: Option<String>,
|
||||||
pub normal_color: ColorPair,
|
pub normal_color: ColorPair,
|
||||||
pub prompt_color: ColorPair,
|
pub prompt_color: ColorPair,
|
||||||
pub selection_color: ColorPair,
|
pub selection_color: ColorPair,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
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) {
|
fn apply(self, wmenu: &mut WMenu) {
|
||||||
let font_string = self.font_string();
|
let font =
|
||||||
let font_height = self.font_height(&font_string);
|
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 line_height = font_height + 2;
|
||||||
|
|
||||||
let mut height = line_height;
|
let height = if self.lines > 0 {
|
||||||
|
line_height + line_height * self.lines
|
||||||
// FIXME: ugly
|
} else {
|
||||||
if self.lines > 0 {
|
line_height
|
||||||
height = height + height * self.lines;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
wmenu
|
wmenu
|
||||||
.height(height)
|
.height(height)
|
||||||
|
@ -50,7 +60,7 @@ impl Config {
|
||||||
.padding(self.padding.try_into().unwrap())
|
.padding(self.padding.try_into().unwrap())
|
||||||
.lines(self.lines.try_into().unwrap())
|
.lines(self.lines.try_into().unwrap())
|
||||||
.line_height(line_height)
|
.line_height(line_height)
|
||||||
.font(&font_string)
|
.font(&font.to_string())
|
||||||
.normal_bg(self.normal_color.bg.into())
|
.normal_bg(self.normal_color.bg.into())
|
||||||
.normal_fg(self.normal_color.fg.into())
|
.normal_fg(self.normal_color.fg.into())
|
||||||
.prompt_bg(self.prompt_color.bg.into())
|
.prompt_bg(self.prompt_color.bg.into())
|
||||||
|
@ -66,8 +76,9 @@ impl Default for Config {
|
||||||
bottom: false,
|
bottom: false,
|
||||||
lines: 0,
|
lines: 0,
|
||||||
padding: 16,
|
padding: 16,
|
||||||
font: "monospace".to_string(),
|
font_family: "monospace".to_string(),
|
||||||
font_size: 12,
|
font_size: 12,
|
||||||
|
language: None,
|
||||||
normal_color: (0x222222ff, 0xbbbbbbffu32).into(),
|
normal_color: (0x222222ff, 0xbbbbbbffu32).into(),
|
||||||
prompt_color: (0x005577ff, 0xeeeeeeffu32).into(),
|
prompt_color: (0x005577ff, 0xeeeeeeffu32).into(),
|
||||||
selection_color: (0x005577ff, 0x227799ffu32).into(),
|
selection_color: (0x005577ff, 0x227799ffu32).into(),
|
||||||
|
@ -104,9 +115,8 @@ impl Menu {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: wrap MenuError with new error type
|
pub fn run(&self) -> Result<String, Error> {
|
||||||
pub fn run(&self) -> Result<String, MenuError> {
|
Ok(self.inner().run()?)
|
||||||
self.inner().run()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue