support new element on dmenu

This commit is contained in:
Alexander Mohr 2025-04-25 21:02:47 +02:00
parent 67a77e49f2
commit 1525803ccc
2 changed files with 52 additions and 17 deletions

View file

@ -101,10 +101,14 @@ impl<T: Clone> AsRef<MenuItem<T>> for MenuItem<T> {
/// # Errors /// # Errors
/// ///
/// Will return Err when the channel between the UI and this is broken /// Will return Err when the channel between the UI and this is broken
pub fn show<T, P>(config: Config, item_provider: P) -> Result<MenuItem<T>, anyhow::Error> pub fn show<T, P>(
config: Config,
item_provider: P,
new_on_empty: bool,
) -> Result<MenuItem<T>, anyhow::Error>
where where
T: Clone + 'static + std::marker::Send, T: Clone + 'static + Send,
P: ItemProvider<T> + 'static + Clone + std::marker::Send, P: ItemProvider<T> + 'static + Clone + Send,
{ {
log::debug!("Starting GUI"); log::debug!("Starting GUI");
if let Some(ref css) = config.style { if let Some(ref css) = config.style {
@ -124,7 +128,7 @@ where
let (sender, receiver) = channel::bounded(1); let (sender, receiver) = channel::bounded(1);
app.connect_activate(move |app| { app.connect_activate(move |app| {
build_ui(&config, item_provider.clone(), &sender, app); build_ui(&config, item_provider.clone(), &sender, app, new_on_empty);
}); });
let gtk_args: [&str; 0] = []; let gtk_args: [&str; 0] = [];
@ -137,9 +141,10 @@ fn build_ui<T, P>(
item_provider: P, item_provider: P,
sender: &Sender<Result<MenuItem<T>, anyhow::Error>>, sender: &Sender<Result<MenuItem<T>, anyhow::Error>>,
app: &Application, app: &Application,
new_on_empty: bool,
) where ) where
T: Clone + 'static + std::marker::Send, T: Clone + 'static + Send,
P: ItemProvider<T> + 'static + std::marker::Send, P: ItemProvider<T> + 'static + Send,
{ {
let start = Instant::now(); let start = Instant::now();
@ -173,6 +178,7 @@ fn build_ui<T, P>(
ArcMenuMap::clone(&list_items), ArcMenuMap::clone(&list_items),
config.clone(), config.clone(),
item_provider, item_provider,
new_on_empty,
); );
log::debug!("keyboard ready after {:?}", start.elapsed()); log::debug!("keyboard ready after {:?}", start.elapsed());
@ -333,6 +339,7 @@ fn setup_key_event_handler<T: Clone + 'static + Send>(
list_items: Arc<Mutex<HashMap<FlowBoxChild, MenuItem<T>>>>, list_items: Arc<Mutex<HashMap<FlowBoxChild, MenuItem<T>>>>,
config: Config, config: Config,
item_provider: ArcProvider<T>, item_provider: ArcProvider<T>,
new_on_empty: bool,
) { ) {
let key_controller = EventControllerKey::new(); let key_controller = EventControllerKey::new();
@ -349,6 +356,7 @@ fn setup_key_event_handler<T: Clone + 'static + Send>(
&item_provider, &item_provider,
&window_clone, &window_clone,
key_value, key_value,
new_on_empty,
) )
}); });
@ -366,6 +374,7 @@ fn handle_key_press<T: Clone + 'static>(
item_provider: &ArcProvider<T>, item_provider: &ArcProvider<T>,
window_clone: &ApplicationWindow, window_clone: &ApplicationWindow,
keyboard_key: Key, keyboard_key: Key,
new_on_empty: bool,
) -> Propagation { ) -> Propagation {
let update_view = |query: &String, items: &mut Vec<MenuItem<T>>| { let update_view = |query: &String, items: &mut Vec<MenuItem<T>>| {
set_menu_visibility_for_search(query, items, config); set_menu_visibility_for_search(query, items, config);
@ -394,6 +403,7 @@ fn handle_key_press<T: Clone + 'static>(
close_gui(app.clone(), window_clone.clone(), config); close_gui(app.clone(), window_clone.clone(), config);
} }
Key::Return => { Key::Return => {
let query = search_entry.text().to_string();
if let Err(e) = handle_selected_item( if let Err(e) = handle_selected_item(
sender, sender,
app.clone(), app.clone(),
@ -401,6 +411,8 @@ fn handle_key_press<T: Clone + 'static>(
config, config,
inner_box, inner_box,
list_items, list_items,
new_on_empty,
Some(&query),
) { ) {
log::error!("{e}"); log::error!("{e}");
} }
@ -610,15 +622,14 @@ fn animate_window<Func>(
let rounded_width = current_width.round() as i32; let rounded_width = current_width.round() as i32;
let rounded_height = current_height.round() as i32; let rounded_height = current_height.round() as i32;
window.set_width_request(rounded_width); if t >= 1.0 || rounded_height > target_height || rounded_width > target_width {
window.set_height_request(rounded_height);
if t >= 1.0 {
window.set_width_request(target_width); window.set_width_request(target_width);
window.set_height_request(target_height); window.set_height_request(target_height);
on_done_func(); on_done_func();
ControlFlow::Break ControlFlow::Break
} else { } else {
window.set_width_request(rounded_width);
window.set_height_request(rounded_height);
ControlFlow::Continue ControlFlow::Continue
} }
}); });
@ -635,6 +646,8 @@ fn handle_selected_item<T>(
config: &Config, config: &Config,
inner_box: &FlowBox, inner_box: &FlowBox,
lock_arc: &ArcMenuMap<T>, lock_arc: &ArcMenuMap<T>,
new_on_empty: bool,
query: Option<&str>,
) -> Result<(), String> ) -> Result<(), String>
where where
T: Clone, T: Clone,
@ -650,7 +663,28 @@ where
close_gui(app, window, config); close_gui(app, window, config);
return Ok(()); return Ok(());
} }
Err("selected item cannot be resolved".to_owned())
if new_on_empty {
let item = MenuItem {
label: query.unwrap_or("").to_owned(),
icon_path: None,
action: None,
sub_elements: Vec::new(),
working_dir: None,
initial_sort_score: 0,
search_sort_score: 0.0,
data: None,
visible: true,
};
if let Err(e) = sender.send(Ok(item.clone())) {
log::error!("failed to send message {e}");
}
close_gui(app, window, config);
Ok(())
} else {
Err("selected item cannot be resolved".to_owned())
}
} }
fn add_menu_item<T: Clone + 'static>( fn add_menu_item<T: Clone + 'static>(
@ -737,7 +771,6 @@ fn create_menu_row<T: Clone + 'static>(
window: ApplicationWindow, window: ApplicationWindow,
inner_box: FlowBox, inner_box: FlowBox,
) -> Widget { ) -> Widget {
let start = Instant::now();
let row = ListBoxRow::new(); let row = ListBoxRow::new();
row.set_hexpand(true); row.set_hexpand(true);
row.set_halign(Align::Fill); row.set_halign(Align::Fill);
@ -755,6 +788,8 @@ fn create_menu_row<T: Clone + 'static>(
&config_clone, &config_clone,
&inner_box, &inner_box,
&lock_arc, &lock_arc,
false,
None,
) { ) {
log::error!("{e}"); log::error!("{e}");
} }

View file

@ -489,7 +489,7 @@ pub fn d_run(config: &Config) -> Result<(), ModeError> {
let mut cache = provider.cache.clone(); let mut cache = provider.cache.clone();
// todo ues a arc instead of cloning the config // todo ues a arc instead of cloning the config
let selection_result = gui::show(config.clone(), provider); let selection_result = gui::show(config.clone(), provider, false);
match selection_result { match selection_result {
Ok(s) => update_drun_cache_and_run(cache_path, &mut cache, s)?, Ok(s) => update_drun_cache_and_run(cache_path, &mut cache, s)?,
Err(_) => { Err(_) => {
@ -510,7 +510,7 @@ pub fn auto(config: &Config) -> Result<(), ModeError> {
let mut cache = provider.drun.cache.clone(); let mut cache = provider.drun.cache.clone();
// todo ues a arc instead of cloning the config // todo ues a arc instead of cloning the config
let selection_result = gui::show(config.clone(), provider); let selection_result = gui::show(config.clone(), provider, false);
match selection_result { match selection_result {
Ok(selection_result) => { Ok(selection_result) => {
@ -544,7 +544,7 @@ pub fn file(config: &Config) -> Result<(), ModeError> {
let provider = FileItemProvider::new(String::new()); let provider = FileItemProvider::new(String::new());
// todo ues a arc instead of cloning the config // todo ues a arc instead of cloning the config
let selection_result = gui::show(config.clone(), provider); let selection_result = gui::show(config.clone(), provider, false);
match selection_result { match selection_result {
Ok(s) => { Ok(s) => {
if let Some(action) = s.action { if let Some(action) = s.action {
@ -563,7 +563,7 @@ pub fn math(config: &Config) {
let provider = MathProvider::new(String::new); let provider = MathProvider::new(String::new);
// todo ues a arc instead of cloning the config // todo ues a arc instead of cloning the config
let selection_result = gui::show(config.clone(), provider); let selection_result = gui::show(config.clone(), provider, false);
match selection_result { match selection_result {
Ok(_) => {} Ok(_) => {}
Err(_) => { Err(_) => {
@ -578,7 +578,7 @@ pub fn math(config: &Config) {
pub fn dmenu(config: &Config) -> Result<(), ModeError> { pub fn dmenu(config: &Config) -> Result<(), ModeError> {
let provider = DMenuProvider::new()?; let provider = DMenuProvider::new()?;
let selection_result = gui::show(config.clone(), provider); let selection_result = gui::show(config.clone(), provider, true);
match selection_result { match selection_result {
Ok(s) => { Ok(s) => {
println!("{}", s.label); println!("{}", s.label);