diff --git a/src/application/data.rs b/src/application/data.rs index 0ee8286..419787c 100644 --- a/src/application/data.rs +++ b/src/application/data.rs @@ -12,7 +12,6 @@ use crate::{ }, simulator::Plot }; - use serde::{Serialize, Deserialize}; #[derive(Clone, Serialize, Deserialize)] @@ -57,6 +56,7 @@ pub struct ApplicationData { modules: HashMap, plots: Vec, current_plot: usize, + file: Option, selection: Selection } @@ -72,15 +72,19 @@ impl Default for ApplicationData { impl ApplicationData { pub fn new() -> Self { - Self { + let mut data = Self { modules: HashMap::new(), plots: vec![Plot::new()], current_plot: 0usize, + file: None, selection: Selection::None - } + }; + + builtin::register(&mut data); + data } - pub fn from_json

(path: P) -> Result + pub fn build

(path: P) -> Result where P: AsRef { let f = File::open(path); diff --git a/src/application/mod.rs b/src/application/mod.rs index 1ce66fe..bc7e00b 100644 --- a/src/application/mod.rs +++ b/src/application/mod.rs @@ -15,11 +15,10 @@ impl Default for Application { impl Application { pub fn new() -> Self { - gio::resources_register_include!("logicrs.gresource") - .expect("Failed to register resources."); + gio::resources_register_include!("logicrs.gresource").expect("Failed to register resources."); glib::Object::new(&[ ("application-id", &"com.spydr06.logicrs"), - ("flags", &gio::ApplicationFlags::empty()), + ("flags", &gio::ApplicationFlags::HANDLES_OPEN), ]) .unwrap() } diff --git a/src/application/template.rs b/src/application/template.rs index e8dbb71..09c0fbf 100644 --- a/src/application/template.rs +++ b/src/application/template.rs @@ -5,33 +5,23 @@ use gtk::{ prelude::{ApplicationImpl, GtkApplicationImpl}, widget::WidgetImpl, }, + gio::{File, prelude::FileExt}, gdk::Display, CssProvider, StyleContext, STYLE_PROVIDER_PRIORITY_APPLICATION }; +use super::data::ApplicationData; use crate::ui::main_window::MainWindow; -use std::cell::RefCell; #[derive(Debug, Default)] pub struct ApplicationTemplate { - window: RefCell>, } impl ApplicationTemplate { const CSS_RESOURCE: &'static str = "/style/style.css"; -} - -#[glib::object_subclass] -impl ObjectSubclass for ApplicationTemplate { - const NAME: &'static str = "Application"; - type Type = super::Application; - type ParentType = adw::Application; -} -impl ObjectImpl for ApplicationTemplate {} -impl ApplicationImpl for ApplicationTemplate { - fn activate(&self, application: &Self::Type) { + fn create_window(&self, application: &super::Application) { StyleManager::default().set_color_scheme(ColorScheme::ForceDark); let provider = CssProvider::new(); @@ -47,7 +37,37 @@ impl ApplicationImpl for ApplicationTemplate { // build the application window and UI let window = MainWindow::new(application); window.show(); - *self.window.borrow_mut() = Some(window); + } +} + +#[glib::object_subclass] +impl ObjectSubclass for ApplicationTemplate { + const NAME: &'static str = "Application"; + type Type = super::Application; + type ParentType = adw::Application; +} + +impl ObjectImpl for ApplicationTemplate {} +impl ApplicationImpl for ApplicationTemplate { + fn activate(&self, application: &Self::Type) { + self.create_window(application); + } + + fn open(&self, application: &Self::Type, files: &[File], _hint: &str) { + assert!(files.len() != 0); + + let file = &files[0]; + if file.path().is_none() { + crate::die("File path is None"); + } + + let data = ApplicationData::build(file.path().unwrap()); + if let Err(err) = data { + crate::die(err.as_str()); + } + + crate::APPLICATION_DATA.with(|d| d.replace(data.unwrap())); + self.create_window(application); } } impl GtkApplicationImpl for ApplicationTemplate {} diff --git a/src/main.rs b/src/main.rs index a44f2d5..e4b4b63 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,10 +17,6 @@ std::thread_local! { } fn init_new() { - APPLICATION_DATA.with(|data| { - modules::builtin::register(&mut *data.borrow_mut()); - }); - APPLICATION_DATA.with(|d| { let mut data = d.borrow_mut(); @@ -52,8 +48,11 @@ fn init_new() { } fn main() -> std::io::Result<()> { - init_new(); - let application = Application::new(); std::process::exit(application.run()); } + +pub fn die<'a>(reason: &'a str) -> ! { + eprintln!("Fatal error: `{reason}`"); + std::process::exit(1) +} \ No newline at end of file diff --git a/src/ui/circuit_view.rs b/src/ui/circuit_view.rs index 54d3ea4..5d85fab 100644 --- a/src/ui/circuit_view.rs +++ b/src/ui/circuit_view.rs @@ -138,94 +138,29 @@ impl WidgetImpl for CircuitViewTemplate { } }); - { - let gesture_drag = GestureDrag::builder().button(gdk::ffi::GDK_BUTTON_PRIMARY as u32).build(); - - let area = self.drawing_area.to_owned(); - let renderer = self.renderer().unwrap(); - gesture_drag.connect_drag_begin(move |gesture, x, y| { - gesture.set_state(gtk::EventSequenceState::Claimed); - crate::APPLICATION_DATA.with(|data| { - let mut data = data.borrow_mut(); - let scale = renderer.borrow().scale(); - let position = ((x / scale) as i32, (y / scale) as i32); - - data.unhighlight(); - - match data.current_plot().get_block_at(position) { - Some(index) => { - if let Some(block) = data.current_plot_mut().get_block_mut(index) { - block.set_start_pos(block.position()); - block.set_highlighted(true); - } - data.set_selection(Selection::Single(index)); - } - _ => { - data.set_selection(Selection::Area(position, position)); - } - } - - area.queue_draw(); - }); - }); - - let area = self.drawing_area.to_owned(); - let renderer = self.renderer().unwrap(); - gesture_drag.connect_drag_update(move |gesture, x, y| { - gesture.set_state(gtk::EventSequenceState::Claimed); - crate::APPLICATION_DATA.with(|data| { - let mut data = data.borrow_mut(); - let scale = renderer.borrow().scale(); - let position = ((x / scale) as i32, (y / scale) as i32); - - match data.selection().clone() { - Selection::Single(index) => { - let block = data.current_plot_mut().get_block_mut(index).unwrap(); - let (start_x, start_y) = block.start_pos(); - block.set_position((start_x + position.0, start_y + position.1)); - area.queue_draw(); - } - Selection::Area(area_start, _) => { - data.set_selection(Selection::Area(area_start, (area_start.0 + position.0, area_start.1 + position.1))); - area.queue_draw(); - } - _ => () - } - }); - }); - - let area = self.drawing_area.to_owned(); - let renderer = self.renderer().unwrap(); - gesture_drag.connect_drag_end(move |gesture, x, y| { - gesture.set_state(gtk::EventSequenceState::Claimed); - if x == 0. && y == 0. { - return; - } + let gesture_drag = GestureDrag::builder().button(gdk::ffi::GDK_BUTTON_PRIMARY as u32).build(); + let area = self.drawing_area.to_owned(); + let renderer = self.renderer().unwrap(); + gesture_drag.connect_drag_begin(move |gesture, x, y| { + gesture.set_state(gtk::EventSequenceState::Claimed); + drag_begin(&area, renderer.borrow().scale(), x, y) + }); - crate::APPLICATION_DATA.with(|data| { - let mut data = data.borrow_mut(); - let scale = renderer.borrow().scale(); - let position = ((x / scale) as i32, (y / scale) as i32); - - match data.selection().clone() { - Selection::Single(index) => { - let block = data.current_plot_mut().get_block_mut(index).unwrap(); - let (start_x, start_y) = block.start_pos(); - block.set_position((start_x + position.0, start_y + position.1)); - }, - Selection::Area(_, _) => { - data.highlight_area(); - data.set_selection(Selection::None); - } - _ => {} - } - - area.queue_draw() - }); - }); - - self.drawing_area.add_controller(&gesture_drag); - } + let area = self.drawing_area.to_owned(); + let renderer = self.renderer().unwrap(); + gesture_drag.connect_drag_update(move |gesture, x, y| { + gesture.set_state(gtk::EventSequenceState::Claimed); + drag_update(&area, renderer.borrow().scale(), x, y) + }); + + let area = self.drawing_area.to_owned(); + let renderer = self.renderer().unwrap(); + gesture_drag.connect_drag_end(move |gesture, x, y| { + gesture.set_state(gtk::EventSequenceState::Claimed); + drag_end(&area, renderer.borrow().scale(), x, y) + }); + + self.drawing_area.add_controller(&gesture_drag); } fn unrealize(&self, widget: &Self::Type) { @@ -233,4 +168,74 @@ impl WidgetImpl for CircuitViewTemplate { } } -impl BoxImpl for CircuitViewTemplate {} \ No newline at end of file +impl BoxImpl for CircuitViewTemplate {} + +fn drag_begin(area: &DrawingArea, scale: f64, x: f64, y: f64) { + crate::APPLICATION_DATA.with(|data| { + let mut data = data.borrow_mut(); + let position = ((x / scale) as i32, (y / scale) as i32); + + data.unhighlight(); + + match data.current_plot().get_block_at(position) { + Some(index) => { + if let Some(block) = data.current_plot_mut().get_block_mut(index) { + block.set_start_pos(block.position()); + block.set_highlighted(true); + } + data.set_selection(Selection::Single(index)); + } + _ => { + data.set_selection(Selection::Area(position, position)); + } + } + + area.queue_draw(); + }); +} + +fn drag_update(area: &DrawingArea, scale: f64, x: f64, y: f64) { + crate::APPLICATION_DATA.with(|data| { + let mut data = data.borrow_mut(); + let position = ((x / scale) as i32, (y / scale) as i32); + + match data.selection().clone() { + Selection::Single(index) => { + let block = data.current_plot_mut().get_block_mut(index).unwrap(); + let (start_x, start_y) = block.start_pos(); + block.set_position((start_x + position.0, start_y + position.1)); + area.queue_draw(); + } + Selection::Area(area_start, _) => { + data.set_selection(Selection::Area(area_start, (area_start.0 + position.0, area_start.1 + position.1))); + area.queue_draw(); + } + _ => () + } + }); +} + +fn drag_end(area: &DrawingArea, scale: f64, x: f64, y: f64) { + if x == 0. && y == 0. { + return; + } + + crate::APPLICATION_DATA.with(|data| { + let mut data = data.borrow_mut(); + let position = ((x / scale) as i32, (y / scale) as i32); + + match data.selection().clone() { + Selection::Single(index) => { + let block = data.current_plot_mut().get_block_mut(index).unwrap(); + let (start_x, start_y) = block.start_pos(); + block.set_position((start_x + position.0, start_y + position.1)); + }, + Selection::Area(_, _) => { + data.highlight_area(); + } + _ => {} + } + + area.queue_draw() + }); +} \ No newline at end of file