Configurable font support

Use fontconfig to load fonts. Fonts can be added to the `fonts` map in
the config, and referenced from individual widgets' configurations for
customizability.

Fonts default to values "mono" and "sans" if nothing is set.
This commit is contained in:
Hilmar Gústafsson
2020-06-14 17:01:42 +02:00
committed by Kenny Levinsen
parent 1a62696662
commit 48985c470a
26 changed files with 396 additions and 14128 deletions
+12 -4
View File
@@ -1,6 +1,9 @@
use crate::color::Color;
use crate::widget::WaitContext;
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
use crate::{
fonts::FontRef,
widgets::bar_widget::{BarWidget, BarWidgetImpl},
};
use alsa::mixer::{Mixer, Selem, SelemChannelId, SelemId};
@@ -34,15 +37,20 @@ pub struct Alsa {
}
impl Alsa {
pub fn new(font_size: f32, length: u32) -> ::std::io::Result<Box<BarWidget>> {
pub fn new(font: FontRef, font_size: f32, length: u32) -> ::std::io::Result<Box<BarWidget>> {
let mixer = Mixer::new(CARD_NAME, true)
.map_err(|err| alsa_error_to_io_error("Failed to create ALSA mixer", &err))?;
let mixer = Self { mixer };
mixer.get_master_volume()?; // probing
Ok(BarWidget::new_simple(font_size, length, Box::new(mixer)))
Ok(BarWidget::new_simple(
font,
font_size,
length,
Box::new(mixer),
))
}
#[inline]
pub fn get_master<'a>(&'a self) -> ::std::io::Result<Selem<'a>> {
pub fn get_master(&self) -> ::std::io::Result<Selem> {
let master_id = SelemId::new(SELEM_NAME, SELEM_ID);
match self.mixer.find_selem(&master_id) {
Some(master) => Ok(master),
+6 -2
View File
@@ -1,7 +1,10 @@
use crate::cmd::Cmd;
use crate::color::Color;
use crate::widget::WaitContext;
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
use crate::{
fonts::FontRef,
widgets::bar_widget::{BarWidget, BarWidgetImpl},
};
use std::cell::RefCell;
use std::collections::HashMap;
@@ -484,11 +487,12 @@ pub struct PulseAudio {
impl PulseAudio {
pub fn new(
font: FontRef,
font_size: f32,
length: u32,
sender: Sender<Cmd>,
) -> Result<Box<BarWidget>, ::std::io::Error> {
BarWidget::new(font_size, length, move |dirty| {
BarWidget::new(font, font_size, length, move |dirty| {
let device = PulseAudioSoundDevice::new(move || {
*dirty.lock().unwrap() = true;
sender.send(Cmd::Draw).unwrap();
+16 -3
View File
@@ -1,6 +1,9 @@
use crate::color::Color;
use crate::widget::WaitContext;
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
use crate::{
fonts::FontRef,
widgets::bar_widget::{BarWidget, BarWidgetImpl},
};
use std::fs;
use std::fs::OpenOptions;
@@ -70,7 +73,12 @@ impl Backlight {
Ok(())
}
pub fn new(path: &str, font_size: f32, length: u32) -> Result<Box<BarWidget>, Error> {
pub fn new<'a>(
path: &str,
font: FontRef<'a>,
font_size: f32,
length: u32,
) -> Result<Box<BarWidget<'a>>, Error> {
let mut dev = Backlight {
device_path: Path::new("/sys/class/backlight").to_path_buf().join(path),
cur_brightness: 0,
@@ -79,7 +87,12 @@ impl Backlight {
dev.update()?;
Ok(BarWidget::new_simple(font_size, length, Box::new(dev)))
Ok(BarWidget::new_simple(
font,
font_size,
length,
Box::new(dev),
))
}
}
+19 -10
View File
@@ -1,6 +1,9 @@
use crate::color::Color;
use crate::draw::{draw_bar, draw_box, Font, ROBOTO_REGULAR};
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, WaitContext, Widget};
use crate::draw::{draw_bar, draw_box, Font};
use crate::{
fonts::FontRef,
widget::{DrawContext, DrawReport, KeyState, ModifiersState, WaitContext, Widget},
};
use std::sync::{Arc, Mutex};
@@ -14,21 +17,22 @@ pub trait BarWidgetImpl {
fn toggle(&mut self);
}
pub struct BarWidget {
pub struct BarWidget<'a> {
bar_impl: Box<dyn BarWidgetImpl + Send>,
font: Font,
font: Font<'a>,
font_size: u32,
length: u32,
dirty: Arc<Mutex<bool>>,
}
impl BarWidget {
impl<'a> BarWidget<'a> {
pub fn new_simple(
font: FontRef,
font_size: f32,
length: u32,
w: Box<dyn BarWidgetImpl + Send>,
) -> Box<BarWidget> {
let mut font = Font::new(&ROBOTO_REGULAR, font_size);
let mut font = Font::new(font, font_size);
font.add_str_to_cache(w.name());
Box::new(BarWidget {
@@ -40,15 +44,20 @@ impl BarWidget {
})
}
pub fn new<F>(font_size: f32, length: u32, f: F) -> Result<Box<BarWidget>, ::std::io::Error>
pub fn new<F>(
font: FontRef<'a>,
font_size: f32,
length: u32,
f: F,
) -> Result<Box<BarWidget>, ::std::io::Error>
where
F: FnOnce(Arc<Mutex<bool>>) -> Result<Box<dyn BarWidgetImpl + Send>, ::std::io::Error>,
F: Send + 'static + Clone,
F: Send + 'a + Clone,
{
let dirty = Arc::new(Mutex::new(true));
let im = f(dirty.clone())?;
let mut font = Font::new(&ROBOTO_REGULAR, font_size);
let mut font = Font::new(font, font_size);
font.add_str_to_cache(im.name());
Ok(Box::new(BarWidget {
@@ -61,7 +70,7 @@ impl BarWidget {
}
}
impl Widget for BarWidget {
impl<'a> Widget for BarWidget<'a> {
fn wait(&mut self, ctx: &mut WaitContext) {
self.bar_impl.wait(ctx);
}
+6 -2
View File
@@ -1,7 +1,10 @@
use crate::cmd::Cmd;
use crate::color::Color;
use crate::widget::WaitContext;
use crate::widgets::bar_widget::{BarWidget, BarWidgetImpl};
use crate::{
fonts::FontRef,
widgets::bar_widget::{BarWidget, BarWidgetImpl},
};
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
@@ -161,11 +164,12 @@ impl UpowerBattery {
}
pub fn new(
font: FontRef,
font_size: f32,
length: u32,
sender: Sender<Cmd>,
) -> Result<Box<BarWidget>, ::std::io::Error> {
BarWidget::new(font_size, length, move |dirty| {
BarWidget::new(font, font_size, length, move |dirty| {
let d = UpowerBattery::from_device(dirty, sender, "DisplayDevice")?;
Ok(Box::new(d))
})
+24 -15
View File
@@ -1,23 +1,26 @@
use crate::buffer::Buffer;
use crate::color::Color;
use crate::draw::{Font, DEJAVUSANS_MONO, ROBOTO_REGULAR};
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, WaitContext, Widget};
use crate::draw::Font;
use crate::{
fonts::FontRef,
widget::{DrawContext, DrawReport, KeyState, ModifiersState, WaitContext, Widget},
};
use chrono::{Datelike, NaiveDate, NaiveDateTime};
pub struct Calendar {
pub struct Calendar<'a> {
cur_date: NaiveDate,
dirty: bool,
offset: f64,
sections: u32,
font_size: u32,
calendar_cache: Font,
month_cache: Font,
year_cache: Font,
day_cache: Font,
calendar_cache: Font<'a>,
month_cache: Font<'a>,
year_cache: Font<'a>,
day_cache: Font<'a>,
}
impl Calendar {
impl<'a> Calendar<'a> {
fn draw_month(
&self,
buf: &mut Buffer,
@@ -152,15 +155,21 @@ impl Calendar {
}
}
impl Calendar {
pub fn new(time: NaiveDateTime, font_size: f32, sections: u32) -> Box<Calendar> {
let mut calendar_cache = Font::new(&DEJAVUSANS_MONO, font_size * 2.0);
impl<'a> Calendar<'a> {
pub fn new(
time: NaiveDateTime,
font_primary: FontRef<'a>,
font_secondary: FontRef<'a>,
font_size: f32,
sections: u32,
) -> Box<Calendar<'a>> {
let mut calendar_cache = Font::new(font_secondary, font_size * 2.0);
calendar_cache.add_str_to_cache("0123456789");
let mut month_cache = Font::new(&ROBOTO_REGULAR, font_size * 4.0);
let mut month_cache = Font::new(font_primary, font_size * 4.0);
month_cache.add_str_to_cache("JanuryFebMchApilJgstSmOoNvD");
let mut year_cache = Font::new(&DEJAVUSANS_MONO, font_size * 1.5);
let mut year_cache = Font::new(font_primary, font_size * 1.5);
year_cache.add_str_to_cache("-0123456789");
let mut day_cache = Font::new(&DEJAVUSANS_MONO, font_size);
let mut day_cache = Font::new(font_primary, font_size);
day_cache.add_str_to_cache("MONTUEWDHFRISA");
Box::new(Calendar {
cur_date: time.date(),
@@ -176,7 +185,7 @@ impl Calendar {
}
}
impl Widget for Calendar {
impl<'a> Widget for Calendar<'a> {
fn wait(&mut self, _: &mut WaitContext) {}
fn enter(&mut self) {}
fn leave(&mut self) {}
+11 -8
View File
@@ -1,18 +1,21 @@
use crate::color::Color;
use crate::draw::{Font, ROBOTO_REGULAR};
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, WaitContext, Widget};
use crate::draw::Font;
use crate::{
fonts::FontRef,
widget::{DrawContext, DrawReport, KeyState, ModifiersState, WaitContext, Widget},
};
use chrono::{Duration, NaiveDateTime, Timelike};
pub struct Clock {
pub struct Clock<'a> {
cur_time: NaiveDateTime,
clock_cache: Font,
clock_cache: Font<'a>,
size: f32,
}
impl Clock {
pub fn new(time: NaiveDateTime, size: f32) -> Box<Clock> {
let mut clock_cache = Font::new(&ROBOTO_REGULAR, size);
impl<'a> Clock<'a> {
pub fn new(time: NaiveDateTime, font: FontRef, size: f32) -> Box<Clock> {
let mut clock_cache = Font::new(font, size);
clock_cache.add_str_to_cache("0123456789:");
Box::new(Clock {
@@ -23,7 +26,7 @@ impl Clock {
}
}
impl Widget for Clock {
impl<'a> Widget for Clock<'a> {
fn wait(&mut self, ctx: &mut WaitContext) {
let target = (self.cur_time + Duration::seconds(60))
.with_second(0)
+11 -8
View File
@@ -1,18 +1,21 @@
use crate::color::Color;
use crate::draw::{Font, ROBOTO_REGULAR};
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, WaitContext, Widget};
use crate::draw::Font;
use crate::{
fonts::FontRef,
widget::{DrawContext, DrawReport, KeyState, ModifiersState, WaitContext, Widget},
};
use chrono::{Datelike, NaiveDateTime};
pub struct Date {
pub struct Date<'a> {
cur_time: NaiveDateTime,
date_cache: Font,
date_cache: Font<'a>,
size: f32,
}
impl Date {
pub fn new(time: NaiveDateTime, size: f32) -> Box<Date> {
let mut date_cache = Font::new(&ROBOTO_REGULAR, size);
impl<'a> Date<'a> {
pub fn new(time: NaiveDateTime, font: FontRef, size: f32) -> Box<Date> {
let mut date_cache = Font::new(font, size);
date_cache
.add_str_to_cache("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,/ ");
@@ -24,7 +27,7 @@ impl Date {
}
}
impl Widget for Date {
impl<'a> Widget for Date<'a> {
fn wait(&mut self, _: &mut WaitContext) {}
fn enter(&mut self) {}
fn leave(&mut self) {}
+11 -7
View File
@@ -2,8 +2,11 @@ use crate::buffer::Buffer;
use crate::cmd::Cmd;
use crate::color::Color;
use crate::desktop::{load_desktop_files, Desktop};
use crate::draw::{Font, ROBOTO_REGULAR};
use crate::widget::{DrawContext, DrawReport, KeyState, ModifiersState, WaitContext, Widget};
use crate::draw::Font;
use crate::{
fonts::FontRef,
widget::{DrawContext, DrawReport, KeyState, ModifiersState, WaitContext, Widget},
};
use std::cell::RefCell;
use std::cmp::Ordering;
@@ -14,7 +17,7 @@ use std::sync::mpsc::Sender;
use fuzzy_matcher::skim::{fuzzy_indices, fuzzy_match};
use smithay_client_toolkit::keyboard::keysyms;
pub struct Launcher {
pub struct Launcher<'a> {
options: Vec<Desktop>,
term_opener: String,
app_opener: String,
@@ -23,15 +26,16 @@ pub struct Launcher {
input: String,
result: Option<String>,
offset: usize,
font: RefCell<Font>,
font: RefCell<Font<'a>>,
font_size: u32,
length: u32,
dirty: bool,
tx: Sender<Cmd>,
}
impl Launcher {
impl<'a> Launcher<'a> {
pub fn new(
font: FontRef,
font_size: f32,
length: u32,
listener: Sender<Cmd>,
@@ -48,7 +52,7 @@ impl Launcher {
input: "".to_string(),
result: None,
offset: 0,
font: RefCell::new(Font::new(&ROBOTO_REGULAR, font_size)),
font: RefCell::new(Font::new(font, font_size)),
font_size: font_size as u32,
length,
dirty: true,
@@ -244,7 +248,7 @@ impl Matcher {
}
}
impl Widget for Launcher {
impl<'a> Widget for Launcher<'a> {
fn wait(&mut self, _: &mut WaitContext) {}
fn enter(&mut self) {}
fn leave(&mut self) {