127 lines
3 KiB
Rust
127 lines
3 KiB
Rust
pub mod color;
|
|
pub mod font;
|
|
|
|
use color::ColorPair;
|
|
use font::FontExt;
|
|
use pango::{prelude::FontExt as _, Font, Language, SCALE};
|
|
use wmenu_rs::Menu as WMenu;
|
|
|
|
struct Config {
|
|
pub bottom: bool,
|
|
pub padding: usize,
|
|
pub lines: i32,
|
|
pub font: String,
|
|
pub font_size: u8,
|
|
pub normal_color: ColorPair,
|
|
pub prompt_color: ColorPair,
|
|
pub selection_color: ColorPair,
|
|
}
|
|
|
|
impl Config {
|
|
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();
|
|
let metrics = font.metrics(Some(&Language::default()));
|
|
|
|
metrics.height() / SCALE
|
|
}
|
|
|
|
fn apply(self, wmenu: &mut WMenu) {
|
|
let font_string = self.font_string();
|
|
let font_height = self.font_height(&font_string);
|
|
let line_height = font_height + 2;
|
|
|
|
let mut height = line_height;
|
|
|
|
if self.lines > 0 {
|
|
height = height + height * self.lines;
|
|
}
|
|
|
|
wmenu
|
|
.height(height)
|
|
.bottom(self.bottom)
|
|
.padding(self.padding.try_into().unwrap())
|
|
.lines(self.lines.try_into().unwrap())
|
|
.line_height(line_height)
|
|
.font(&font_string)
|
|
.normal_bg(self.normal_color.bg.into())
|
|
.normal_fg(self.normal_color.fg.into())
|
|
.prompt_bg(self.prompt_color.bg.into())
|
|
.prompt_fg(self.prompt_color.fg.into())
|
|
.selection_bg(self.selection_color.bg.into())
|
|
.selection_fg(self.selection_color.fg.into());
|
|
}
|
|
}
|
|
|
|
impl Default for Config {
|
|
fn default() -> Self {
|
|
Self {
|
|
bottom: false,
|
|
lines: 0,
|
|
padding: 16,
|
|
font: "monospace".to_string(),
|
|
font_size: 12,
|
|
normal_color: (0x222222ff, 0xbbbbbbffu32).into(),
|
|
prompt_color: (0x005577ff, 0xeeeeeeffu32).into(),
|
|
selection_color: (0x005577ff, 0x227799ffu32).into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
struct Menu {
|
|
wmenu: WMenu,
|
|
}
|
|
|
|
impl Menu {
|
|
pub fn new(config: Config) -> Self {
|
|
let mut wmenu = WMenu::new();
|
|
config.apply(&mut wmenu);
|
|
Self { wmenu }
|
|
}
|
|
|
|
pub fn inner(&self) -> &WMenu {
|
|
&self.wmenu
|
|
}
|
|
|
|
pub fn inner_mut(&mut self) -> &mut WMenu {
|
|
&mut self.wmenu
|
|
}
|
|
|
|
pub fn add_item(&mut self, item: &str) -> &mut Menu {
|
|
self.inner_mut().add_item(item);
|
|
self
|
|
}
|
|
|
|
pub fn add_items(&mut self, items: &[&str]) -> &mut Menu {
|
|
self.inner_mut().add_items(items);
|
|
self
|
|
}
|
|
}
|
|
|
|
impl Default for Menu {
|
|
fn default() -> Self {
|
|
Self::new(Config::default())
|
|
}
|
|
}
|
|
|
|
impl From<Menu> for WMenu {
|
|
fn from(value: Menu) -> Self {
|
|
value.wmenu
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::{Config, Menu};
|
|
|
|
#[test]
|
|
fn it_works() {
|
|
let mut menu = Menu::new(Config::default());
|
|
menu.add_items(&["rowern", "sybil", "vex"]);
|
|
let result = menu.inner_mut().run();
|
|
println!("{result:?}");
|
|
}
|
|
}
|