Implement working search bar

This commit is contained in:
Julian Mutter 2024-01-22 21:11:51 +01:00
parent e47c9afe33
commit e4543ac66e
3 changed files with 100 additions and 30 deletions

View File

@ -6,17 +6,16 @@ use std::{env, path::PathBuf, process};
use gtk::prelude::*;
use mcdu::McduModel;
use relm4::prelude::*;
use sheet_listing::SheetListingModel;
use sheet_listing::{SheetListingInput, SheetListingModel};
struct AppModel {
text: String,
mcdu: Controller<McduModel>,
sheet_listing: Controller<SheetListingModel>,
}
#[derive(Debug)]
enum AppInput {
McduInput(char),
SearchStarted(String),
SheetPressed(PathBuf),
}
@ -44,17 +43,7 @@ impl SimpleComponent for AppModel {
// set_hscrollbar_policy: PolicyType::Never,
},
},
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
set_valign: gtk::Align::Center,
model.mcdu.widget(),
#[name = "label"]
gtk::Label {
#[watch]
set_label: &model.text,
set_margin_all: 5,
}
},
model.mcdu.widget(),
}
}
}
@ -69,7 +58,7 @@ impl SimpleComponent for AppModel {
let mcdu = McduModel::builder()
.launch(())
.forward(sender.input_sender(), |response| match response {
mcdu::McduOutput::ButtonPress(c) => AppInput::McduInput(c),
mcdu::McduOutput::SearchStarted(query) => AppInput::SearchStarted(query),
});
let sheet_listing =
@ -82,7 +71,6 @@ impl SimpleComponent for AppModel {
});
let model = AppModel {
text: String::from("Text: "),
mcdu,
sheet_listing,
};
@ -94,8 +82,8 @@ impl SimpleComponent for AppModel {
fn update(&mut self, message: Self::Input, _sender: ComponentSender<Self>) {
match message {
AppInput::McduInput(c) => self.text.push(c),
AppInput::SheetPressed(sheet) => opener::open(sheet).unwrap(),
AppInput::SearchStarted(query) => self.sheet_listing.emit(SheetListingInput { query }),
}
}
}

View File

@ -1,24 +1,57 @@
use relm4::gtk::{glib, prelude::*};
use relm4::{gtk, ComponentParts, ComponentSender, SimpleComponent};
pub struct McduModel;
pub struct McduModel {
query: String,
query_changed_by_mcdu_keys: bool,
}
impl McduModel {
fn new() -> Self {
McduModel {
query: String::new(),
query_changed_by_mcdu_keys: false,
}
}
}
#[derive(Debug)]
pub enum McduOutput {
SearchStarted(String),
}
#[derive(Debug)]
pub enum KeyboardEvent {
ButtonPress(char),
SearchStarted(String),
QueryChanged(String),
}
#[relm4::component(pub)]
impl SimpleComponent for McduModel {
type Init = ();
type Input = ();
type Input = KeyboardEvent;
type Output = McduOutput;
view! {
#[root]
gtk::Grid {
set_column_spacing: 5,
set_row_spacing: 5,
gtk::Box {
set_orientation: gtk::Orientation::Vertical,
set_valign: gtk::Align::Center,
gtk::SearchEntry {
set_margin_bottom: 10,
#[block_signal(change_handler, search_handler)]
#[track = "model.query_changed_by_mcdu_keys"]
set_text: &model.query,
connect_changed[sender] => move |search_entry| sender.input(KeyboardEvent::QueryChanged(search_entry.text().to_string())) @change_handler,
connect_search_changed[sender] => move |search_entry| sender.input(KeyboardEvent::SearchStarted(search_entry.text().to_string())) @search_handler,
},
#[name = "keyboard"]
gtk::Grid {
set_column_spacing: 5,
set_row_spacing: 5,
}
}
}
@ -27,6 +60,9 @@ impl SimpleComponent for McduModel {
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
let model = McduModel::new();
let widgets = view_output!();
let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
let mcdu_width = 6;
@ -34,17 +70,33 @@ impl SimpleComponent for McduModel {
let button = gtk::Button::default();
button.set_label(&c.to_string());
button.connect_clicked(glib::clone!(@strong sender => move |_| {
sender.output(McduOutput::ButtonPress(c)).unwrap();
sender.input(KeyboardEvent::ButtonPress(c));
}));
let column = i % mcdu_width;
let row = (i - column) / mcdu_width;
root.attach(&button, column as i32, row as i32, 1, 1);
widgets
.keyboard
.attach(&button, column as i32, row as i32, 1, 1);
}
let model = McduModel;
let widgets = view_output!();
ComponentParts { model, widgets }
}
fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {
self.query_changed_by_mcdu_keys = false;
match message {
KeyboardEvent::ButtonPress(c) => {
// println!("Button press: {}", c);
self.query_changed_by_mcdu_keys = true;
self.query.push(c);
}
KeyboardEvent::SearchStarted(s) => {
// println!("Started search: {}", s);
sender.output(McduOutput::SearchStarted(s)).unwrap();
}
KeyboardEvent::QueryChanged(query) => self.query = query,
}
}
}

View File

@ -9,11 +9,13 @@ use walkdir::WalkDir;
pub struct SheetModel {
path: PathBuf,
visible: bool,
}
#[derive(Debug)]
pub enum SheetModelInput {
OnClicked,
SearchChanged(String),
}
#[derive(Debug)]
@ -30,6 +32,8 @@ impl SimpleComponent for SheetModel {
view! {
#[root]
gtk::Box {
#[watch]
set_visible: model.visible,
set_orientation: gtk::Orientation::Vertical,
append = &gtk::Button {
set_label: &format!("{}", model.path.file_name().unwrap().to_string_lossy()),
@ -45,7 +49,10 @@ impl SimpleComponent for SheetModel {
root: &Self::Root,
sender: ComponentSender<Self>,
) -> ComponentParts<Self> {
let model = SheetModel { path };
let model = SheetModel {
path,
visible: true,
};
let widgets = view_output!();
ComponentParts { model, widgets }
}
@ -55,18 +62,33 @@ impl SimpleComponent for SheetModel {
SheetModelInput::OnClicked => sender
.output(SheetPressedMessage::SheetPressed(self.path.clone()))
.unwrap(),
SheetModelInput::SearchChanged(query) => {
self.visible = self
.path
.file_name()
.unwrap()
.to_string_lossy()
.to_lowercase()
.contains(&query.to_lowercase());
}
}
}
}
pub struct SheetListingModel {
_sheet_models: Vec<Controller<SheetModel>>,
query: String,
sheet_models: Vec<Controller<SheetModel>>,
}
#[derive(Debug)]
pub struct SheetListingInput {
pub query: String,
}
#[relm4::component(pub)]
impl SimpleComponent for SheetListingModel {
type Init = PathBuf;
type Input = ();
type Input = SheetListingInput;
type Output = SheetPressedMessage;
view! {
@ -102,9 +124,17 @@ impl SimpleComponent for SheetListingModel {
}
let model = SheetListingModel {
_sheet_models: sheet_models,
query: String::new(),
sheet_models: sheet_models,
};
let widgets = view_output!();
ComponentParts { model, widgets }
}
fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {
self.query = message.query;
for model in self.sheet_models.iter() {
model.emit(SheetModelInput::SearchChanged(self.query.clone()));
}
}
}