Skip to content

Commit

Permalink
Merge pull request #58 from squidowl/feat/custom-font
Browse files Browse the repository at this point in the history
Allow custom font
  • Loading branch information
tarkah authored Jun 27, 2023
2 parents e1be243 + 16de0bf commit 1eae22f
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 26 deletions.
9 changes: 9 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ servers:
# Channels to join upon connecting to the server
channels:
- "##rust"

# Font settings
font:
# Specify the monospaced font family to use
# - Default is Iosevka Term and provided by this application
family: Iosevka Term
# Specify the font size
# - Default is 13
size: 13

# Settings applied by default to new buffers
new_buffer:
Expand Down
8 changes: 8 additions & 0 deletions data/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,19 @@ pub struct Config {
#[serde(default)]
pub palette: Palette,
pub servers: server::Map,
#[serde(default)]
pub font: Font,
/// Default settings when creating a new buffer
#[serde(default)]
pub new_buffer: buffer::Settings,
}

#[derive(Debug, Clone, Default, Deserialize)]
pub struct Font {
pub family: Option<String>,
pub size: Option<u8>,
}

impl Config {
pub fn config_dir() -> PathBuf {
let dir = environment::config_dir().join("halloy");
Expand Down
64 changes: 52 additions & 12 deletions src/font.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,61 @@
use std::sync::OnceLock;

use data::Config;

use iced::font::{self, Error};
use iced::{Command, Font};
use iced::Command;

pub const MONO: Font = Font {
pub static MONO: Font = Font::new(false);
pub static MONO_BOLD: Font = Font::new(true);
pub const ICON: iced::Font = iced::Font {
monospaced: true,
..Font::with_name("Iosevka Term")
..iced::Font::with_name("bootstrap-icons")
};

pub const MONO_BOLD: Font = Font {
monospaced: true,
weight: font::Weight::Bold,
..Font::with_name("Iosevka Term")
};
#[derive(Debug, Clone)]
pub struct Font {
bold: bool,
inner: OnceLock<iced::Font>,
}

pub const ICON: Font = Font {
monospaced: true,
..Font::with_name("bootstrap-icons")
};
impl Font {
const fn new(bold: bool) -> Self {
Self {
bold,
inner: OnceLock::new(),
}
}

fn set(&self, name: String) {
let name = Box::leak(name.into_boxed_str());
let weight = if self.bold {
font::Weight::Bold
} else {
font::Weight::Normal
};

let _ = self.inner.set(iced::Font {
monospaced: true,
weight,
..iced::Font::with_name(name)
});
}
}

impl From<Font> for iced::Font {
fn from(value: Font) -> Self {
value.inner.get().copied().expect("font is set on startup")
}
}

pub fn set(config: Option<&Config>) {
let family = config
.and_then(|config| config.font.family.clone())
.unwrap_or_else(|| String::from("Iosevka Term"));

MONO.set(family.clone());
MONO_BOLD.set(family);
}

pub fn load() -> Command<Result<(), Error>> {
Command::batch(vec![
Expand Down
43 changes: 31 additions & 12 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,13 @@ pub fn main() -> iced::Result {
data::environment::formatted_version()
);

if let Err(error) = Halloy::run(settings()) {
let config_load = Config::load();

// DANGER ZONE - font must be set using config
// before we do any iced related stuff w/ it
font::set(config_load.as_ref().ok());

if let Err(error) = Halloy::run(settings(config_load)) {
log::error!("{}", error.to_string());
Err(error)
} else {
Expand All @@ -72,15 +78,26 @@ fn window_settings() -> iced::window::Settings {
}
}

fn settings() -> iced::Settings<()> {
fn settings(
config_load: Result<Config, config::Error>,
) -> iced::Settings<Result<Config, config::Error>> {
let default_text_size = config_load
.as_ref()
.ok()
.and_then(|config| config.font.size)
.map(f32::from)
.unwrap_or(theme::TEXT_SIZE);

iced::Settings {
default_font: font::MONO,
default_text_size: theme::TEXT_SIZE,
default_font: font::MONO.clone().into(),
default_text_size,
window: iced::window::Settings {
..window_settings()
},
exit_on_close_request: false,
..Default::default()
flags: config_load,
id: None,
antialiasing: false,
}
}

Expand All @@ -92,7 +109,9 @@ struct Halloy {
}

impl Halloy {
pub fn load_from_state() -> (Halloy, Command<Message>) {
pub fn load_from_state(
config_load: Result<Config, config::Error>,
) -> (Halloy, Command<Message>) {
let load_dashboard = |config| match data::Dashboard::load() {
Ok(dashboard) => screen::Dashboard::restore(dashboard),
Err(error) => {
Expand All @@ -104,7 +123,7 @@ impl Halloy {
}
};

let (screen, config, command) = match Config::load() {
let (screen, config, command) = match config_load {
Ok(config) => {
let (screen, command) = load_dashboard(&config);

Expand Down Expand Up @@ -160,10 +179,10 @@ impl Application for Halloy {
type Executor = executor::Default;
type Message = Message;
type Theme = theme::Theme;
type Flags = ();
type Flags = Result<Config, config::Error>;

fn new(_flags: ()) -> (Halloy, Command<Self::Message>) {
let (halloy, command) = Halloy::load_from_state();
fn new(config_load: Self::Flags) -> (Halloy, Command<Self::Message>) {
let (halloy, command) = Halloy::load_from_state(config_load);

(
halloy,
Expand Down Expand Up @@ -199,7 +218,7 @@ impl Application for Halloy {
if let Some(event) = help.update(message) {
match event {
help::Event::RefreshConfiguration => {
let (halloy, command) = Halloy::load_from_state();
let (halloy, command) = Halloy::load_from_state(Config::load());
*self = halloy;

return command;
Expand All @@ -217,7 +236,7 @@ impl Application for Halloy {
if let Some(event) = welcome.update(message) {
match event {
welcome::Event::RefreshConfiguration => {
let (halloy, command) = Halloy::load_from_state();
let (halloy, command) = Halloy::load_from_state(Config::load());
*self = halloy;

return command;
Expand Down
2 changes: 1 addition & 1 deletion src/screen/help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl Help {
.spacing(1)
.push(icon::error().size(45))
.push(vertical_space(10))
.push(text("Error reading configuration file").font(font::MONO_BOLD))
.push(text("Error reading configuration file").font(font::MONO_BOLD.clone()))
.push(vertical_space(3))
.push(text(self.error.to_string()).style(theme::Text::Error))
.push(vertical_space(10))
Expand Down
2 changes: 1 addition & 1 deletion src/screen/welcome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl Welcome {
.spacing(1)
.push(image(format!("{}/assets/logo.png", env!("CARGO_MANIFEST_DIR"))).width(150))
.push(vertical_space(10))
.push(text("Welcome to Halloy!").font(font::MONO_BOLD))
.push(text("Welcome to Halloy!").font(font::MONO_BOLD.clone()))
.push(vertical_space(4))
.push(text(
"No configuration file found. Please follow the steps below to proceed",
Expand Down
2 changes: 2 additions & 0 deletions src/theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use iced::{application, Background, Color};

use crate::widget::selectable_text;

// TODO: If we use non-standard font sizes, we should consider
// Config.font.size since it's user configurable
pub const TEXT_SIZE: f32 = 13.0;
pub const ICON_SIZE: f32 = 12.0;

Expand Down

0 comments on commit 1eae22f

Please sign in to comment.