diff --git a/README.md b/README.md index 689ceab..5dd52df 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ layerrule = blur, worf because worf is build on GTK4 instead of GTK3 there will be differences in the look and feel. * Configuration files are not 100% compatible, Worf is using toml files instead, for most part this only means strings have to be quoted * Color files are not supported +* `line_wrap` is now called `line-wrap` ## Dropped arguments * `mode`, use show diff --git a/src/lib/config.rs b/src/lib/config.rs index c837734..876318e 100644 --- a/src/lib/config.rs +++ b/src/lib/config.rs @@ -51,6 +51,13 @@ pub enum Animation { ExpandHorizontal, } +#[derive(Clone, Debug, Serialize, Deserialize)] +pub enum WrapMode { + None, + Word, + Inherit, +} + #[derive(Clone, Debug, Serialize, Deserialize)] pub enum Mode { /// searches `$PATH` for executables and allows them to be run by selecting them. @@ -90,7 +97,22 @@ impl FromStr for Mode { "math" => Ok(Mode::Math), "auto" => Ok(Mode::Auto), _ => Err(ArgsError::InvalidParameter( - format!("{s} is not a valid argument show this, see help for details").to_owned(), + format!("{s} is not a valid argument, see help for details").to_owned(), + )), + } + } +} + +impl FromStr for WrapMode { + type Err = ArgsError; + + fn from_str(s: &str) -> Result { + match s { + "none" => Ok(WrapMode::None), + "word" => Ok(WrapMode::Word), + "inherit" => Ok(WrapMode::Inherit), + _ => Err(ArgsError::InvalidParameter( + format!("{s} is not a valid argument, see help for details").to_owned(), )), } } @@ -215,19 +237,23 @@ pub struct Config { #[clap(long = "orientation")] pub orientation: Option, + /// Horizontal alignment #[serde(default = "default_halign")] #[clap(long = "halign")] pub halign: Option, + /// Alignment of content #[serde(default = "default_content_halign")] #[clap(long = "content-halign")] pub content_halign: Option, + /// Vertical alignment #[clap(long = "valign")] pub valign: Option, pub filter_rate: Option, + /// Defines the image size in pixels #[serde(default = "default_image_size")] #[clap(long = "image-size")] pub image_size: Option, @@ -249,7 +275,6 @@ pub struct Config { // todo re-add this // #[serde(flatten)] // pub key_custom: Option>, - pub line_wrap: Option, pub global_coords: Option, pub hide_search: Option, pub dynamic_lines: Option, @@ -268,17 +293,16 @@ pub struct Config { #[clap(long = "row-box-orientation")] pub row_bow_orientation: Option, - /// Set to to true to wrap text after a given amount of chars - #[serde(default = "default_text_wrap")] - #[clap(long = "text-wrap")] - pub text_wrap: Option, - - /// Defines after how many chars a line is broken over. - /// Only cuts at spaces. - #[serde(default = "default_text_wrap_length")] - #[clap(long = "text-wrap-length")] - pub text_wrap_length: Option, - + // /// Set to to true to wrap text after a given amount of chars + // #[serde(default = "default_text_wrap")] + // #[clap(long = "text-wrap")] + // pub text_wrap: Option, + // + // /// Defines after how many chars a line is broken over. + // /// Only cuts at spaces. + // #[serde(default = "default_text_wrap_length")] + // #[clap(long = "text-wrap-length")] + // pub text_wrap_length: Option, /// Defines the animation when the window is show. /// Defaults to Expand #[serde(default = "default_show_animation")] @@ -303,6 +327,10 @@ pub struct Config { #[serde(default = "default_hide_animation_time")] #[clap(long = "hide-animation-time")] pub hide_animation_time: Option, + + #[serde(default = "default_line_wrap")] + #[clap(long = "line-wrap")] + pub line_wrap: Option, } impl Default for Config { @@ -359,7 +387,7 @@ impl Default for Config { key_hide_search: None, key_copy: None, //key_custom: None, - line_wrap: None, + line_wrap: default_line_wrap(), global_coords: None, hide_search: None, dynamic_lines: None, @@ -369,8 +397,6 @@ impl Default for Config { pre_display_exec: None, fuzzy_min_score: default_fuzzy_min_score(), row_bow_orientation: default_row_box_orientation(), - text_wrap: default_text_wrap(), - text_wrap_length: default_text_wrap_length(), show_animation: default_show_animation(), show_animation_time: default_show_animation_time(), hide_animation: default_hide_animation(), @@ -449,6 +475,13 @@ pub fn default_normal_window() -> bool { false } +// allowed because option is needed for serde macro +#[allow(clippy::unnecessary_wraps)] +#[must_use] +pub fn default_line_wrap() -> Option { + Some(WrapMode::Word) +} + // TODO // GtkOrientation orientation = config_get_mnemonic(config, "orientation", "vertical", 2, "vertical", "horizontal"); // outer_orientation = config_get_mnemonic(cstoonfig, "orientation", "vertical", 2, "horizontal", "vertical"); @@ -588,20 +621,6 @@ pub fn default_image_size() -> Option { Some(32) } -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_text_wrap_length() -> Option { - Some(15) -} - -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_text_wrap() -> Option { - Some(false) -} - #[must_use] pub fn parse_args() -> Config { Config::parse() diff --git a/src/lib/gui.rs b/src/lib/gui.rs index 15cdae1..f52ab74 100644 --- a/src/lib/gui.rs +++ b/src/lib/gui.rs @@ -15,16 +15,13 @@ use gtk4::prelude::{ ApplicationExt, ApplicationExtManual, BoxExt, EditableExt, FlowBoxChildExt, GestureSingleExt, GtkWindowExt, ListBoxRowExt, NativeExt, WidgetExt, }; -use gtk4::{ - Align, EventControllerKey, Expander, FlowBox, FlowBoxChild, GestureClick, Image, Label, - ListBox, ListBoxRow, Ordering, PolicyType, ScrolledWindow, SearchEntry, Widget, gdk, -}; +use gtk4::{Align, EventControllerKey, Expander, FlowBox, FlowBoxChild, GestureClick, Image, Label, ListBox, ListBoxRow, Ordering, PolicyType, ScrolledWindow, SearchEntry, Widget, gdk, NaturalWrapMode}; use gtk4::{Application, ApplicationWindow, CssProvider, Orientation}; use gtk4_layer_shell::{Edge, KeyboardMode, LayerShell}; use log; use crate::config; -use crate::config::{Animation, Config, MatchMethod}; +use crate::config::{Animation, Config, MatchMethod, WrapMode}; type ArcMenuMap = Arc>>>; type ArcProvider = Arc>>; @@ -44,6 +41,16 @@ impl From for Orientation { } } +impl From<&WrapMode> for NaturalWrapMode { + fn from(value: &WrapMode) -> Self { + match value { + WrapMode::None => {NaturalWrapMode::None}, + WrapMode::Word => {NaturalWrapMode::Word}, + WrapMode::Inherit => {NaturalWrapMode::Inherit}, + } + } +} + impl From for Align { fn from(align: config::Align) -> Self { match align { @@ -808,14 +815,14 @@ fn create_menu_row( row_box.append(&image); } - // todo make max length configurable - let text = if config.text_wrap.is_some_and(|x| x) { - &wrap_text(&menu_item.label, config.text_wrap_length) + let label = Label::new(Some(menu_item.label.as_str())); + let wrap_mode : NaturalWrapMode = if let Some(config_wrap) = &config.line_wrap { + config_wrap.into() } else { - menu_item.label.as_str() + NaturalWrapMode::Word }; - let label = Label::new(Some(text)); + label.set_natural_wrap_mode(wrap_mode); label.set_hexpand(true); label.set_widget_name("label"); label.set_wrap(true); @@ -955,25 +962,3 @@ pub fn sort_menu_items_alphabetically_honor_initial_score( } } } - -fn wrap_text(text: &str, line_length: Option) -> String { - let mut result = String::new(); - let mut line = String::new(); - let len = line_length.unwrap_or(text.len()); - - for word in text.split_whitespace() { - if line.len() + word.len() + 1 > len && !line.is_empty() { - result.push_str(line.trim_end()); - result.push('\n'); - line.clear(); - } - line.push_str(word); - line.push(' '); - } - - if !line.is_empty() { - result.push_str(line.trim_end()); - } - - result -}