feat: window borders

This commit is contained in:
2024-05-22 04:55:45 +02:00
parent 19314e00ea
commit 157d892498
5 changed files with 63 additions and 21 deletions

View File

@@ -3,7 +3,7 @@
A practical application runner written in Rust. Inspired by [dmenu](https://tools.suckless.org/dmenu/) A practical application runner written in Rust. Inspired by [dmenu](https://tools.suckless.org/dmenu/)
### Features ### Features
- theming (colors, font family, font size, line spacing) - theming (colors, font family, font size, line spacing, window border)
- custom row count - custom row count
- prompt message - prompt message
- open menu on a specific display - open menu on a specific display

View File

@@ -1,8 +1,8 @@
use clap::Parser; use clap::Parser;
use crate::config::{ use crate::config::{
BACKGROUND_COLOR, BACKGROUND_COLOR_ACTIVE, FONT_COLOR, FONT_COLOR_ACTIVE, FONT_POINT_SIZE, BACKGROUND_COLOR, BACKGROUND_COLOR_ACTIVE, BORDER_COLOR, BORDER_SIZE, FONT_COLOR,
LINE_SPACING, MAX_ITEM_DISPLAY_COUNT, FONT_COLOR_ACTIVE, FONT_POINT_SIZE, LINE_SPACING, MAX_ITEM_DISPLAY_COUNT,
}; };
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
@@ -20,6 +20,12 @@ pub struct Arguments {
#[arg(long, help = "The font color of the active item", default_value_t = String::from(FONT_COLOR_ACTIVE))] #[arg(long, help = "The font color of the active item", default_value_t = String::from(FONT_COLOR_ACTIVE))]
pub font_color_active: String, pub font_color_active: String,
#[arg(long, help = "The window border color", default_value_t = String::from(BORDER_COLOR))]
pub border_color: String,
#[arg(long, help = "The window border size in pixels", default_value_t = BORDER_SIZE)]
pub border_size: u8,
#[arg(long, help = "The default background color", default_value_t = String::from(BACKGROUND_COLOR))] #[arg(long, help = "The default background color", default_value_t = String::from(BACKGROUND_COLOR))]
pub background_color: String, pub background_color: String,

View File

@@ -9,9 +9,14 @@ pub const FONT_COLOR_ACTIVE: &str = "#1e1e2e";
pub const BACKGROUND_COLOR: &str = "#1e1e2e"; pub const BACKGROUND_COLOR: &str = "#1e1e2e";
pub const BACKGROUND_COLOR_ACTIVE: &str = "#89b4fa"; pub const BACKGROUND_COLOR_ACTIVE: &str = "#89b4fa";
pub const BORDER_SIZE: u8 = 1;
pub const BORDER_COLOR: &str = "#585b70";
pub struct RunnerMenuSettings { pub struct RunnerMenuSettings {
pub font_color: String, pub font_color: String,
pub font_color_active: String, pub font_color_active: String,
pub border_color: String,
pub border_size: u8,
pub background_color: String, pub background_color: String,
pub background_color_active: String, pub background_color_active: String,
pub rows: u16, pub rows: u16,

View File

@@ -27,6 +27,8 @@ fn main() -> Result<(), Box<dyn Error>> {
font: args.font, font: args.font,
font_color: args.font_color, font_color: args.font_color,
font_color_active: args.font_color_active, font_color_active: args.font_color_active,
border_color: args.border_color,
border_size: args.border_size,
background_color: args.background_color, background_color: args.background_color,
background_color_active: args.background_color_active, background_color_active: args.background_color_active,
rows: args.rows, rows: args.rows,

View File

@@ -5,7 +5,7 @@ use sdl2::{
event::Event, event::Event,
keyboard::{Keycode, Mod}, keyboard::{Keycode, Mod},
rect::Rect, rect::Rect,
render::Canvas, render::{Canvas, WindowCanvas},
ttf, ttf,
video::Window, video::Window,
Sdl, Sdl,
@@ -36,7 +36,7 @@ impl Runner {
let font_path: String; let font_path: String;
let (window_width, window_height): (u32, u32); let (window_width, window_height): (u32, u32);
window_width = 480; window_width = 480 + (settings.border_size * 2) as u32;
{ {
font_path = get_font_path(match settings.font { font_path = get_font_path(match settings.font {
@@ -52,7 +52,8 @@ impl Runner {
window_height = (PADDING window_height = (PADDING
+ ((font.height() as u16 + settings.line_spacing) * (1 + settings.rows)) + ((font.height() as u16 + settings.line_spacing) * (1 + settings.rows))
- settings.line_spacing.div_euclid(2) - settings.line_spacing.div_euclid(2)
+ PADDING) + PADDING
+ (settings.border_size * 2) as u16)
.into(); .into();
} }
@@ -125,6 +126,8 @@ impl Runner {
let font_color = color_from_hex(&self.settings.font_color).unwrap(); let font_color = color_from_hex(&self.settings.font_color).unwrap();
let font_color_active = color_from_hex(&self.settings.font_color_active).unwrap(); let font_color_active = color_from_hex(&self.settings.font_color_active).unwrap();
let border_color = color_from_hex(&self.settings.border_color).unwrap();
let font = self let font = self
.ttf .ttf
.load_font(&self.font_path, self.settings.font_size) .load_font(&self.font_path, self.settings.font_size)
@@ -137,6 +140,8 @@ impl Runner {
'run: loop { 'run: loop {
self.canvas.set_draw_color(background_color); self.canvas.set_draw_color(background_color);
self.canvas.clear(); self.canvas.clear();
self.canvas.set_draw_color(border_color);
draw_borders(self.settings.border_size, self.window_size, &mut self.canvas);
for event in event_pump.poll_iter() { for event in event_pump.poll_iter() {
match event { match event {
@@ -222,8 +227,10 @@ impl Runner {
} }
} }
let mut cursor_offset_x = PADDING; let mut cursor_offset_x = PADDING + self.settings.border_size as u16;
let input_position_y: u16 = (PADDING + self.settings.line_spacing.div_ceil(4)).into(); let input_position_y: u16 = (PADDING + self.settings.border_size as u16 - 1
+ self.settings.line_spacing.div_ceil(4))
.into();
if !self.input.is_empty() || !self.prompt.is_empty() { if !self.input.is_empty() || !self.prompt.is_empty() {
let surface = font let surface = font
@@ -232,7 +239,7 @@ impl Runner {
.expect("Error rendering text"); .expect("Error rendering text");
let rect = Rect::new( let rect = Rect::new(
PADDING.into(), (PADDING + self.settings.border_size as u16).into(),
input_position_y.into(), input_position_y.into(),
surface.width(), surface.width(),
surface.height(), surface.height(),
@@ -247,15 +254,17 @@ impl Runner {
let _ = self.canvas.copy(&texture, None, Some(rect)); let _ = self.canvas.copy(&texture, None, Some(rect));
} }
let cursor_rect = Rect::new( if self.canvas.window().has_input_focus() {
cursor_offset_x.into(), let cursor_rect = Rect::new(
input_position_y.into(), cursor_offset_x.into(),
3, input_position_y.into(),
font.height() as u32, 3,
); font.height() as u32,
);
self.canvas.set_draw_color(background_color_active); self.canvas.set_draw_color(background_color_active);
let _ = self.canvas.fill_rect(cursor_rect); let _ = self.canvas.fill_rect(cursor_rect);
}
// try to keep the selection centered // try to keep the selection centered
let executables_len: u16 = filtered_executables.len() as u16; let executables_len: u16 = filtered_executables.len() as u16;
@@ -270,7 +279,8 @@ impl Runner {
let mut display_count: u16 = 0; let mut display_count: u16 = 0;
for i in start..end { for i in start..end {
let offset = PADDING * 2 let offset = self.settings.border_size as u16
+ PADDING * 2
+ (font.height() as u16 + self.settings.line_spacing) * (display_count + 1); + (font.height() as u16 + self.settings.line_spacing) * (display_count + 1);
let surface = font let surface = font
@@ -283,16 +293,16 @@ impl Runner {
.expect("Error rendering text"); .expect("Error rendering text");
let rect = Rect::new( let rect = Rect::new(
PADDING.into(), (self.settings.border_size as u16 + PADDING).into(),
offset.into(), offset.into(),
surface.width(), surface.width(),
surface.height(), surface.height(),
); );
let background_rect = Rect::new( let background_rect = Rect::new(
0, self.settings.border_size.into(),
(offset - half_line_spacing).into(), (offset - half_line_spacing).into(),
self.window_size.0, self.window_size.0 - (self.settings.border_size as u32) * 2,
(surface.height() + self.settings.line_spacing as u32).into(), (surface.height() + self.settings.line_spacing as u32).into(),
); );
@@ -340,3 +350,22 @@ fn filter_executables(
filtered_executables.sort_by(|a, b| b.starts_with(input).cmp(&a.starts_with(input))); filtered_executables.sort_by(|a, b| b.starts_with(input).cmp(&a.starts_with(input)));
} }
fn draw_borders(border_size: u8, window_size: (u32, u32), canvas: &mut WindowCanvas) {
if border_size > 0 {
let _ = canvas.fill_rect(Rect::new(0, 0, window_size.0, border_size.into()));
let _ = canvas.fill_rect(Rect::new(
(window_size.0 - border_size as u32) as i32,
0,
border_size.into(),
window_size.1,
));
let _ = canvas.fill_rect(Rect::new(
0,
(window_size.1 - border_size as u32) as i32,
window_size.0,
border_size.into(),
));
let _ = canvas.fill_rect(Rect::new(0, 0, border_size.into(), window_size.1));
}
}