diff --git a/src/main.rs b/src/main.rs index f8695ea..f2a272a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,6 +37,7 @@ struct Ui { page_indicator: gtk4::Label, drawing_area: gtk4::DrawingArea, drawing_context: Context, + document_canvas: Option, } struct DocumentCanvas { @@ -66,14 +67,21 @@ fn toggle_fullscreen(ui: &Ui) { } } -fn update_page_status(ui: &Ui, doc: &DocumentCanvas) { - let page_status: String = format!("{} / {}", doc.current_page_number, doc.num_pages); - let page_status_s: &str = &page_status[..]; - ui.page_indicator.set_label(page_status_s); +fn update_page_status(ui: &Ui) { + let page_status = match &ui.document_canvas { + Some(doc) => format!("{} / {}", doc.current_page_number, doc.num_pages), + None => "No document loaded!".to_string(), + }; + ui.page_indicator.set_label(page_status.as_str()); ui.drawing_area.queue_draw(); } -fn process_touch(ui: &Ui, doc: &mut DocumentCanvas, x: f64, y: f64) { +fn process_touch(ui: &mut Ui, x: f64, y: f64) { + if ui.document_canvas.is_none() { + return; + } + + let doc = ui.document_canvas.as_mut().unwrap(); let center = ui.drawing_area.width() / 2; if y < (ui.drawing_area.height() / 5) as f64 { toggle_fullscreen(ui); @@ -82,10 +90,15 @@ fn process_touch(ui: &Ui, doc: &mut DocumentCanvas, x: f64, y: f64) { } else if x < center as f64 && doc.current_page_number > 1 { doc.current_page_number -= 1; } - update_page_status(ui, doc); + update_page_status(ui); } -fn draw(ui: &Ui, document_canvas: &DocumentCanvas, area: &DrawingArea, context: &Context) { +fn draw(ui: &Ui, area: &DrawingArea, context: &Context) { + if ui.document_canvas.is_none() { + return; + } + let document_canvas = ui.document_canvas.as_ref().unwrap(); + context.set_source_rgba(1.0, 1.0, 1.0, 1.0); context.paint().unwrap(); context.fill().expect("uh oh"); @@ -127,43 +140,31 @@ fn draw(ui: &Ui, document_canvas: &DocumentCanvas, area: &DrawingArea, context: fn load_document(file: &PathBuf, ui: Rc>) { println!("Loading file..."); - // let first_child = app_wrapper.first_child().unwrap(); - // let last_child = app_wrapper.last_child().unwrap(); - // if &first_child != &last_child { - // app_wrapper.remove(&first_child); - // } - - // app_wrapper.prepend(&ui.borrow().drawing_area); - - // let old_indicator = ui.borrow().bottom_bar.last_child(); - // if old_indicator.is_some() { - // ui.borrow().bottom_bar.remove(&old_indicator.unwrap()); - // } - // ui.borrow().bottom_bar.append(&ui.borrow().page_indicator); - // TODO: catch errors let uri = format!("file://{}", file.to_str().unwrap()); let document_canvas = DocumentCanvas::new(poppler::Document::from_file(&uri, None).unwrap()); - let document_canvas = Rc::new(RefCell::new(document_canvas)); + ui.borrow_mut().document_canvas = Some(document_canvas); - update_page_status(&ui.borrow(), &document_canvas.borrow()); + update_page_status(&ui.borrow()); +} - let click = gtk4::GestureClick::new(); - click.set_button(0); - click.connect_pressed( - glib::clone!(@weak ui, @strong document_canvas => @default-panic, move |_, _, x, y| { - process_touch(&ui.borrow(), &mut document_canvas.borrow_mut(), x, y); - }), - ); - - // TODO: opening new file keeps the old controller - ui.borrow().drawing_area.add_controller(click); - - ui.borrow().drawing_area.set_draw_func( - glib::clone!(@weak ui, @weak document_canvas => move |area, context, _, _| { - draw(&ui.borrow(), &document_canvas.borrow(), area, context); - }), - ); +fn choose_file(ui: Rc>, window: &ApplicationWindow) { + let filechooser = gtk4::FileChooserDialog::builder() + .title("Choose a PDF...") + .action(gtk4::FileChooserAction::Open) + .modal(true) + .build(); + filechooser.add_button("_Cancel", gtk4::ResponseType::Cancel); + filechooser.add_button("_Open", gtk4::ResponseType::Accept); + filechooser.set_transient_for(Some(window)); + filechooser.connect_response(move |d, response| { + if response == gtk4::ResponseType::Accept { + let path = d.file().unwrap().path().unwrap(); + load_document(&path, Rc::clone(&ui)); + } + d.destroy(); + }); + filechooser.show() } fn build_ui(app: &Application, cli: &Cli) { @@ -180,9 +181,10 @@ fn build_ui(app: &Application, cli: &Cli) { let ui = Ui { bottom_bar: gtk4::Box::builder().hexpand_set(true).build(), header_bar: gtk4::HeaderBar::builder().build(), - page_indicator: gtk4::Label::builder().label("Counting...").build(), + page_indicator: gtk4::Label::builder().build(), drawing_area: DrawingArea::builder().hexpand(true).vexpand(true).build(), drawing_context: ctx, + document_canvas: None, }; let ui = Rc::new(RefCell::new(ui)); @@ -191,42 +193,40 @@ fn build_ui(app: &Application, cli: &Cli) { app_wrapper.append(&ui.borrow().bottom_bar); ui.borrow().bottom_bar.append(&ui.borrow().page_indicator); + let click = gtk4::GestureClick::new(); + click.set_button(0); + click.connect_pressed(glib::clone!(@weak ui => @default-panic, move |_, _, x, y| { + process_touch(&mut ui.borrow_mut(), x, y); + })); + + ui.borrow().drawing_area.add_controller(click); + + ui.borrow() + .drawing_area + .set_draw_func(glib::clone!(@weak ui => move |area, context, _, _| { + draw(&ui.borrow(), area, context); + })); + let window = ApplicationWindow::builder() .application(app) .title("Music Reader") .child(&app_wrapper) .maximized(true) .build(); - window.set_titlebar(Some(&ui.borrow().header_bar)); + let window = Rc::new(RefCell::new(window)); - let load_doc = move |file: &PathBuf| { - load_document(file, Rc::clone(&ui)); - }; + window.borrow().set_titlebar(Some(&ui.borrow().header_bar)); match cli.file.as_ref() { - Some(file) => load_doc(file), + Some(file) => load_document(file, Rc::clone(&ui)), None => {} } open_file_button.connect_clicked( - glib::clone!(@weak window, @strong load_doc => @default-panic, move |_button| { - let filechooser = gtk4::FileChooserDialog::builder() - .title("Choose a PDF...") - .action(gtk4::FileChooserAction::Open) - .modal(true) - .build(); - filechooser.add_button("_Cancel", gtk4::ResponseType::Cancel); - filechooser.add_button("_Open", gtk4::ResponseType::Accept); - filechooser.set_transient_for(Some(&window)); - filechooser.connect_response(glib::clone!(@strong load_doc => @default-panic, move |d, response| { - if response == gtk4::ResponseType::Accept { - let path = d.file().unwrap().path().unwrap(); - load_doc(&path); - } - d.destroy(); - })); - filechooser.show() + glib::clone!(@strong window => @default-panic, move |_button| { + choose_file(Rc::clone(&ui), &window.borrow()); }), ); - window.present(); + + window.borrow().present(); }