Skip to content

Commit

Permalink
Add file operations
Browse files Browse the repository at this point in the history
  • Loading branch information
Azorlogh committed Jun 8, 2020
1 parent 5f48f0b commit f964fc1
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 40 deletions.
65 changes: 34 additions & 31 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ authors = ["Azorlogh <bott.alix@gmail.com>"]
edition = "2018"

[dependencies]
druid = "0.6.0"
# druid = "0.6.0"
druid = { git = "https://github.com/xi-editor/druid" }
cpal = "0.11.0"
meval = "0.2.0"
derive_more = "0.99.7"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Layout markers can be added by right clicking the cursor bar.

## TODO

- File operations
- Improve UI
- Selection
- Display errors on invalid input
- Control note volume
Expand Down
5 changes: 5 additions & 0 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ use druid::Selector;
use generational_arena::Index;

// general
pub const PROJECT_NEW: Selector = Selector::new("project-new");
pub const PROJECT_SAVE: Selector = Selector::new("project-save");
pub const PROJECT_OPEN: Selector = Selector::new("project-open");
pub const PROJECT_SAVE_AS: Selector = Selector::new("project-save-as");

pub const HISTORY_SAVE: Selector = Selector::new("history-save");
pub const HISTORY_UNDO: Selector = Selector::new("history-undo");
pub const HISTORY_REDO: Selector = Selector::new("history-redo");
Expand Down
7 changes: 3 additions & 4 deletions src/data/sheet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,10 @@ impl Sheet {
self.notes.get_mut(id)
}

// get closest note to point in board coordinates
pub fn get_note_at(&self, pos: Point, note_height: f64) -> Option<Index> {
let mut closest = (None, f64::INFINITY);
for (index, note) in &self.notes {
let dist = (pos.y - self.get_freq(note.pitch).log2()).abs();
let dist = (pos.y - self.get_y(note.pitch)).abs();
if note.start < pos.x && pos.x < note.start + note.length && dist < note_height / 2.0 && dist <= closest.1 {
closest = (Some(index), dist);
}
Expand All @@ -54,7 +53,7 @@ impl Sheet {
for (index, note) in &self.notes {
if note.start < pos.x
&& note.start + note.length > pos.x
&& (pos.y - self.get_freq(note.pitch).log2()).abs() < note_height / 2.0
&& (pos.y - self.get_y(note.pitch)).abs() < note_height / 2.0
{
out.push(index);
}
Expand Down Expand Up @@ -122,7 +121,7 @@ impl Sheet {
pub fn remove_notes_along(&mut self, line: Line, note_height: f64) {
let mut notes = self.notes.clone();
notes.retain(|_, note| {
let b_freq = self.get_freq(note.pitch).log2(); // freq in board coordinates
let b_freq = self.get_y(note.pitch);
let rect = Rect::from_points(
Point::new(note.start, b_freq - note_height / 2.0),
Point::new(note.start + note.length, b_freq + note_height / 2.0),
Expand Down
69 changes: 68 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#![feature(tau_constant)]

use druid::{AppDelegate, AppLauncher, Command, DelegateCtx, Env, LocalizedString, Size, Target, WindowDesc, WindowId};
use druid::commands as sys_cmds;
use druid::{
AppDelegate, AppLauncher, Command, DelegateCtx, Env, FileDialogOptions, FileSpec, LocalizedString, Size, Target,
WindowDesc, WindowId,
};
use std::fs;
use std::rc::Rc;
use std::sync::mpsc::*;

Expand Down Expand Up @@ -112,6 +117,68 @@ impl AppDelegate<State> for Delegate {
ctx.submit_command(commands::REDRAW, Target::Global);
false
}
_ if cmd.is(commands::PROJECT_NEW) => {
let mut state = State::new();
state.main_window = data.main_window.clone();
*data = state;
false
}
_ if cmd.is(commands::PROJECT_OPEN) => {
ctx.submit_command(
Command::new(
sys_cmds::SHOW_OPEN_PANEL,
FileDialogOptions::new().allowed_types(vec![FileSpec::new("Xenoroll Project", &["xrp"])]),
),
Target::Window(*data.main_window.clone().unwrap()),
);
false
}
_ if cmd.is(commands::PROJECT_SAVE_AS) => {
ctx.submit_command(
Command::new(
sys_cmds::SHOW_SAVE_PANEL,
FileDialogOptions::new().allowed_types(vec![FileSpec::new("Xenoroll Project", &["xrp"])]),
),
Target::Window(*data.main_window.clone().unwrap()),
);
false
}
_ if cmd.is(commands::PROJECT_SAVE) => {
if let Some(path) = data.save_path.clone() {
let project = state::Project::from_editors(&data.editors);
let data = ron::to_string(&project).unwrap();
fs::write(&*path, data).ok();
} else {
let xrp = FileSpec::new("Xenoroll project", &["xrp"]);
ctx.submit_command(
Command::new(
sys_cmds::SHOW_SAVE_PANEL,
FileDialogOptions::new().allowed_types(vec![xrp]).default_type(xrp),
),
Target::Window(*data.main_window.clone().unwrap()),
);
}
false
}
_ if cmd.is(sys_cmds::SAVE_FILE) => {
if let Some(file_info) = cmd.get_unchecked(sys_cmds::SAVE_FILE) {
data.save_path = Some(Rc::new(file_info.path().into()));
let project = state::Project::from_editors(&data.editors);
let data = ron::to_string(&project).unwrap();
fs::write(file_info.path(), data).ok();
}
true
}
_ if cmd.is(sys_cmds::OPEN_FILE) => {
let file_info = cmd.get_unchecked(sys_cmds::OPEN_FILE);
if let Ok(project_string) = fs::read_to_string(file_info.path()) {
if let Ok(project) = ron::from_str::<state::Project>(&project_string) {
project.open(&mut data.editors);
ctx.submit_command(commands::REDRAW, Target::Global);
}
}
true
}
_ => true,
};
if project_changed {
Expand Down
10 changes: 10 additions & 0 deletions src/state/editors/sheet_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub struct State {
pub tempo: f64,
pub interval_input: Interval,
pub curr_marker: usize,
pub confirm: ConfirmState,
}
impl Default for State {
fn default() -> State {
Expand All @@ -38,6 +39,7 @@ impl Default for State {
tempo: 172.0,
interval_input: Interval::Ratio(3, 2),
curr_marker: 0,
confirm: ConfirmState::None,
}
}
}
Expand All @@ -47,3 +49,11 @@ pub enum Menu {
File,
Edit,
}

// Temporary
#[derive(Clone, Copy, PartialEq, Data)]
pub enum ConfirmState {
None,
New,
Open,
}
3 changes: 3 additions & 0 deletions src/state/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use druid::{Data, Lens};
use std::path::PathBuf;
use std::{cell::RefCell, rc::Rc};

pub mod editors;
Expand All @@ -12,6 +13,7 @@ pub struct State {
pub main_window: Option<Rc<druid::WindowId>>,
pub editors: editors::State,
pub history: Rc<RefCell<history::History>>,
pub save_path: Option<Rc<PathBuf>>,
}

impl State {
Expand All @@ -22,6 +24,7 @@ impl State {
main_window: None,
editors,
history: Rc::new(RefCell::new(History::new(project))),
save_path: None,
}
}
}
54 changes: 52 additions & 2 deletions src/ui/sheet_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::commands;
use crate::util::{Frame, Frame2};
use crate::widget::{common::*, *};

use crate::state::editors::sheet_editor::{Menu, State};
use crate::state::editors::sheet_editor::*;

const SCROLLBAR_THICKNESS: f64 = 32.0;
const TIMELINE_THICKNESS: f64 = 16.0;
Expand Down Expand Up @@ -42,7 +42,57 @@ pub fn build() -> impl Widget<State> {
|data: &State, _| std::mem::discriminant(&data.open_menu),
|_, data, _| {
Box::new(match data.open_menu {
Menu::File => Flex::row().with_child(Label::new("File placeholder")).with_flex_spacer(1.0),
Menu::File => Flex::row()
.with_child(
Button::new("New")
.on_click(|_, data: &mut State, _| data.confirm = ConfirmState::New)
.fix_width(80.0)
.padding(3.0),
)
.with_child(
Button::new("Open")
.on_click(|_, data: &mut State, _| data.confirm = ConfirmState::Open)
.fix_width(80.0)
.padding(3.0),
)
.with_child(
Button::new("Save")
.on_click(|ctx, _, _| ctx.submit_command(commands::PROJECT_SAVE, None))
.fix_width(80.0)
.padding(3.0),
)
.with_child(
Button::new("Save As")
.on_click(|ctx, _, _| ctx.submit_command(commands::PROJECT_SAVE_AS, None))
.fix_width(80.0)
.padding(3.0),
)
.with_flex_spacer(1.0)
.with_child(ViewSwitcher::new(
|data: &State, _| std::mem::discriminant(&data.confirm),
|_, data, _| match data.confirm {
ConfirmState::None => Flex::row().fix_width(0.0).boxed(),
ConfirmState::New => Flex::row()
.with_child(Label::new("Close this project ?"))
.with_child(
Button::new("❌").on_click(|_, data: &mut State, _| data.confirm = ConfirmState::None),
)
.with_child(
Button::new("✔").on_click(|ctx, _, _| ctx.submit_command(commands::PROJECT_NEW, None)),
)
.boxed(),
ConfirmState::Open => Flex::row()
.with_child(Label::new("Close this project ?"))
.with_child(
Button::new("❌").on_click(|_, data: &mut State, _| data.confirm = ConfirmState::None),
)
.with_child(Button::new("✔").on_click(|ctx, data: &mut State, _| {
data.confirm = ConfirmState::None;
ctx.submit_command(commands::PROJECT_OPEN, None);
}))
.boxed(),
},
)),
Menu::Edit => Flex::row().with_child(Label::new("Edit placeholder")).with_flex_spacer(1.0),
})
},
Expand Down
12 changes: 12 additions & 0 deletions src/widget/sheet_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,18 @@ impl Widget<State> for SheetEditor {
Event::KeyDown(key) if key.mods.ctrl && key.key_code == KeyCode::KeyY => {
ctx.submit_command(commands::HISTORY_REDO, ctx.window_id());
}
Event::KeyDown(key) if key.mods.ctrl && key.key_code == KeyCode::KeyN => {
ctx.submit_command(commands::PROJECT_NEW, ctx.window_id());
}
Event::KeyDown(key) if key.mods.ctrl && key.key_code == KeyCode::KeyO => {
ctx.submit_command(commands::PROJECT_OPEN, ctx.window_id());
}
Event::KeyDown(key) if key.mods.ctrl && key.mods.shift && key.key_code == KeyCode::KeyS => {
ctx.submit_command(commands::PROJECT_SAVE_AS, ctx.window_id());
}
Event::KeyDown(key) if key.mods.ctrl && key.key_code == KeyCode::KeyS => {
ctx.submit_command(commands::PROJECT_SAVE, ctx.window_id());
}
Event::WindowSize(_) => {
ctx.request_layout();
ctx.request_paint();
Expand Down

0 comments on commit f964fc1

Please sign in to comment.