From 872c2d94d6f5603c8881137c640c0069e16627f0 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Wed, 14 May 2025 17:15:27 +0300 Subject: [PATCH] last small wave of 15 errors? --- crates/app/src/api.rs | 73 +++++------ crates/app/src/audio.rs | 6 - crates/app/src/model.rs | 113 ++++++++---------- crates/app/src/view.rs | 2 +- crates/device/src/arranger/arranger_api.rs | 81 ++++++------- crates/device/src/arranger/arranger_model.rs | 38 +++--- crates/device/src/arranger/arranger_select.rs | 13 +- crates/device/src/arranger/arranger_track.rs | 22 +++- crates/device/src/arranger/arranger_tracks.rs | 9 +- crates/device/src/arranger/arranger_view.rs | 11 +- crates/device/src/browser/browser_model.rs | 2 +- 11 files changed, 181 insertions(+), 189 deletions(-) diff --git a/crates/app/src/api.rs b/crates/app/src/api.rs index 10bbefed..90b086a0 100644 --- a/crates/app/src/api.rs +++ b/crates/app/src/api.rs @@ -30,9 +30,9 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm app.toggle_editor(Some(value)); Ok(None) } - fn color (app: &mut App, theme: ItemTheme) -> Perhaps { - Ok(app.set_color(Some(theme)).map(|theme|Self::Color{theme})) - } + //fn color (app: &mut App, theme: ItemTheme) -> Perhaps { + //Ok(app.set_color(Some(theme)).map(|theme|Self::Color{theme})) + //} fn enqueue (app: &mut App, clip: Option>>) -> Perhaps { todo!() } @@ -42,19 +42,18 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm fn zoom (app: &mut App, zoom: usize) -> Perhaps { todo!() } - fn launch (app: &mut App) -> Perhaps { - app.project.launch(); - Ok(None) - } + //fn launch (app: &mut App) -> Perhaps { + //app.project.launch(); + //Ok(None) + //} fn select (app: &mut App, selection: Selection) -> Perhaps { - app.project.select(selection); + *app.project.selection_mut() = selection; if let Some(ref mut editor) = app.editor { - editor.set_clip(match app.project.selected { - Some(Selection::TrackClip { track, scene }) - if let Some(Some(Some(clip))) = app + editor.set_clip(match app.project.selection() { + Selection::TrackClip { track, scene } if let Some(Some(Some(clip))) = app .project - .scenes.get(scene) - .map(|s|s.clips.get(track)) + .scenes.get(*scene) + .map(|s|s.clips.get(*track)) => Some(clip), _ => @@ -79,14 +78,11 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm .transpose()? .flatten()) } - fn arrange (app: &mut App, command: ArrangementCommand) -> Perhaps { - Ok(command.delegate(app, |command|Self::Arrange{command})?) + fn project (app: &mut App, command: ArrangementCommand) -> Perhaps { + Ok(command.delegate(&mut app.project, |command|Self::Project{command})?) } fn clock (app: &mut App, command: ClockCommand) -> Perhaps { - Ok(command.execute(&mut app.clock())?.map(|command|Self::Clock{command})) - } - fn device (app: &mut App, command: DeviceCommand) -> Perhaps { - Ok(command.delegate(app, |command|Self::Device{command})?) + Ok(command.execute(app.clock_mut())?.map(|command|Self::Clock{command})) } fn message (app: &mut App, command: MessageCommand) -> Perhaps { Ok(command.delegate(app, |command|Self::Message{command})?) @@ -106,21 +102,20 @@ handle!(TuiIn: |self: App, input|Ok(if let Some(command) = self.config.keys.comm }) } fn pool (app: &mut App, command: PoolCommand) -> Perhaps { - Ok(if let Some(pool) = app.project.pool.as_mut() { - let undo = command.clone().delegate(pool, |command|AppCommand::Pool{command})?; - // update linked editor after pool action - app.editor.as_mut().map(|editor|match command { - // autoselect: automatically load selected clip in editor - PoolCommand::Select { .. } | - // autocolor: update color in all places simultaneously - PoolCommand::Clip { command: PoolClipCommand::SetColor { .. } } => - editor.set_clip(pool.clip().as_ref()), - _ => {} - }); - undo - } else { - None - }) + let undo = command.clone().delegate( + &mut app.project.pool, + |command|AppCommand::Pool{command} + )?; + // update linked editor after pool action + app.editor.as_mut().map(|editor|match command { + // autoselect: automatically load selected clip in editor + PoolCommand::Select { .. } | + // autocolor: update color in all places simultaneously + PoolCommand::Clip { command: PoolClipCommand::SetColor { .. } } => + editor.set_clip(app.project.pool.clip().as_ref()), + _ => {} + }); + Ok(undo) } } @@ -138,7 +133,7 @@ impl<'state> Context<'state, MidiEditCommand> for App { impl<'state> Context<'state, PoolCommand> for App { fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { - self.project.pool.map(|p|Context::get(p, iter)).flatten() + Context::get(&self.project.pool, iter) } } @@ -148,9 +143,15 @@ impl<'state> Context<'state, SamplerCommand> for App { } } +impl<'state> Context<'state, ArrangementCommand> for App { + fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { + Context::get(&self.project, iter) + } +} + #[tengri_proc::command(App)] impl MessageCommand { fn dismiss (app: &mut App) -> Perhaps { - app.message_dismiss(); + app.dialog = None; Ok(None) } } diff --git a/crates/app/src/audio.rs b/crates/app/src/audio.rs index e12c2b80..dd65d0af 100644 --- a/crates/app/src/audio.rs +++ b/crates/app/src/audio.rs @@ -1,11 +1,5 @@ use crate::*; -impl HasJack for App { - fn jack (&self) -> &Jack { - &self.jack - } -} - audio!( |self: App, client, scope|{ let t0 = self.perf.get_t0(); diff --git a/crates/app/src/model.rs b/crates/app/src/model.rs index 24cdcb4b..c04f1fb3 100644 --- a/crates/app/src/model.rs +++ b/crates/app/src/model.rs @@ -28,12 +28,14 @@ pub struct App { pub color: ItemTheme, } -has!(Option: |self: App|self.project.selection); -has!(Vec: |self: App|self.project.midi_ins); -has!(Vec: |self: App|self.project.midi_outs); -has!(Vec: |self: App|self.project.scenes); -has!(Vec: |self: App|self.project.tracks); -has!(Clock: |self: App|self.project.clock); +has!(Jack: |self: App|self.jack); +has!(Clock: |self: App|self.project.clock); +has!(Selection: |self: App|self.project.selection); +has!(Vec: |self: App|self.project.midi_ins); +has!(Vec: |self: App|self.project.midi_outs); +has!(Vec: |self: App|self.project.scenes); +has!(Vec: |self: App|self.project.tracks); + has_size!(|self: App|&self.size); has_clips!(|self: App|self.project.pool.clips); has_editor!(|self: App|{ @@ -46,24 +48,28 @@ has_editor!(|self: App|{ (5 + (time_len / time_zoom)).min(size.saturating_sub(20)).max(16) }; editor_h = 15; - is_editing = self.editing.load(Relaxed); + is_editing = self.editor.is_some(); }); impl App { - pub fn toggle_dialog (&mut self, dialog: Option) { - self.dialog = if self.dialog == dialog { - None - } else { - dialog - } + pub fn toggle_dialog (&mut self, mut dialog: Option) -> Option { + std::mem::swap(&mut self.dialog, &mut dialog); + dialog } pub fn toggle_editor (&mut self, value: Option) { - self.editing.store(value.unwrap_or_else(||!self.is_editing()), Relaxed); - self.arranger.map(|arranger|if value { - arranger.clip_auto_create(); + //FIXME: self.editing.store(value.unwrap_or_else(||!self.is_editing()), Relaxed); + let value = value.unwrap_or_else(||!self.editor.is_some()); + if value { + self.clip_auto_create(); } else { - arranger.clip_auto_remove(); - }); + self.clip_auto_remove(); + } + } + pub fn browser (&self) -> Option<&Browser> { + self.dialog.as_ref().and_then(|dialog|match dialog { + Dialog::Save(b) | Dialog::Load(b) => Some(b), + _ => None + }) } pub(crate) fn device_pick (&mut self, index: usize) { self.dialog = Some(Dialog::Device(index)); @@ -85,15 +91,14 @@ impl App { todo!(); Ok(()) } - fn device_add_sampler (&mut self, jack: &Jack) -> Usually { - let name = jack.with_client(|c|c.name().to_string()); - let midi = self.track().expect("no active track").sequencer.midi_outs[0].name(); + fn device_add_sampler (&mut self) -> Usually<()> { + let name = self.jack.with_client(|c|c.name().to_string()); + let midi = self.project.track().expect("no active track").sequencer.midi_outs[0].name(); + let track = self.track().expect("no active track"); + let port = format!("{}/Sampler", &track.name); + let connect = PortConnect::exact(format!("{name}:{midi}")); let sampler = if let Ok(sampler) = Sampler::new( - jack, - &format!("{}/Sampler", Has::::get(self).name), - &[PortConnect::exact(format!("{name}:{midi}"))], - &[&[], &[]], - &[&[], &[]] + &self.jack, &port, &[connect], &[&[], &[]], &[&[], &[]] ) { self.dialog = None; Device::Sampler(sampler) @@ -101,22 +106,23 @@ impl App { self.dialog = Some(Dialog::Message(Message::FailedToAddDevice)); return Err("failed to add device".into()) }; - Has::::get_mut(self).expect("no active track").devices.push(sampler); + let track = self.track_mut().expect("no active track"); + track.devices.push(sampler); Ok(()) } // Create new clip in pool when entering empty cell fn clip_auto_create (&mut self) -> Option>> { - if let Some(Selection::TrackClip { track, scene }) = self.get() - && let Some(scene) = Has::>::get_mut(self).get_mut(scene) + if let Selection::TrackClip { track, scene } = *self.selection() + && let Some(scene) = self.project.scenes.get_mut(scene) && let Some(slot) = scene.clips.get_mut(track) && slot.is_none() - && let Some(track) = Has::>::get_mut(self).get_mut(track) + && let Some(track) = self.project.tracks.get_mut(track) { - let (index, mut clip) = self.arranger.pool.add_new_clip(); + let (index, mut clip) = self.project.pool.add_new_clip(); // autocolor: new clip colors from scene and track color let color = track.color.base.mix(scene.color.base, 0.5); clip.write().unwrap().color = ItemColor::random_near(color, 0.2).into(); - if let Some(ref mut editor) = Has::>::get_mut(self) { + if let Some(ref mut editor) = self.editor { editor.set_clip(Some(&clip)); } *slot = Some(clip.clone()); @@ -125,37 +131,24 @@ impl App { None } } -} - -#[cfg(all(feature = "pool", feature = "editor"))] -pub trait AutoRemove: - Has> + - Has> + - Has> + - Has> + - Has> + - Send + Sync -{ // Remove clip from arrangement when exiting empty clip editor fn clip_auto_remove (&mut self) { - if let Some(ref mut pool) = Has::>::get(self) - && let Some(Selection::TrackClip { track, scene }) = self.get() - && let Some(scene) = Has::>::get_mut(self).get_mut(*scene) - && let Some(slot) = scene.clips.get_mut(*track) - && let Some(clip) = slot.as_mut() + if let Selection::TrackClip { track, scene } = *self.selection() + && let Some(scene) = self.project.scenes.get_mut(scene) + && let Some(slot) = scene.clips.get_mut(track) + && let Some(clip) = slot.as_mut() { let mut swapped = None; if clip.read().unwrap().count_midi_messages() == 0 { std::mem::swap(&mut swapped, slot); } if let Some(clip) = swapped { - pool.delete_clip(&clip.read().unwrap()); + self.project.pool.delete_clip(&clip.read().unwrap()); } } } } - /// Various possible dialog overlays #[derive(Clone, Debug)] pub enum Dialog { @@ -197,7 +190,7 @@ impl App { matches!(self.dialog, Some(Dialog::Device(..))) } fn focus_browser (&self) -> bool { - self.browser.is_visible + self.browser().is_some() } fn focus_clip (&self) -> bool { !self.is_editing() && self.selection().is_clip() @@ -212,16 +205,16 @@ impl App { !self.is_editing() && self.selection().is_mix() } fn focus_pool_import (&self) -> bool { - matches!(self.project.pool.as_ref().map(|p|p.mode.as_ref()).flatten(), Some(PoolMode::Import(..))) + matches!(self.project.pool.mode, Some(PoolMode::Import(..))) } fn focus_pool_export (&self) -> bool { - matches!(self.project.pool.as_ref().map(|p|p.mode.as_ref()).flatten(), Some(PoolMode::Export(..))) + matches!(self.project.pool.mode, Some(PoolMode::Export(..))) } fn focus_pool_rename (&self) -> bool { - matches!(self.project.pool.as_ref().map(|p|p.mode.as_ref()).flatten(), Some(PoolMode::Rename(..))) + matches!(self.project.pool.mode, Some(PoolMode::Rename(..))) } fn focus_pool_length (&self) -> bool { - matches!(self.project.pool.as_ref().map(|p|p.mode.as_ref()).flatten(), Some(PoolMode::Length(..))) + matches!(self.project.pool.mode, Some(PoolMode::Length(..))) } fn dialog_device (&self) -> Dialog { Dialog::Device(0) // TODO @@ -239,10 +232,10 @@ impl App { Dialog::Menu } fn dialog_save (&self) -> Dialog { - Dialog::Save + Dialog::Save(Default::default()) } fn dialog_load (&self) -> Dialog { - Dialog::Load + Dialog::Load(Default::default()) } fn dialog_options (&self) -> Dialog { Dialog::Options @@ -251,13 +244,13 @@ impl App { Some((self.editor().as_ref().map(|e|e.get_note_pos()).unwrap() as u8).into()) } fn scene_count (&self) -> usize { - self.scenes.len() + self.scenes().len() } fn scene_selection (&self) -> Option { self.selection().scene() } fn track_count (&self) -> usize { - self.tracks.len() + self.tracks().len() } fn track_selection (&self) -> Option { self.selection().track() @@ -279,7 +272,7 @@ impl App { } fn clip_selection (&self) -> Option>> { match self.selection() { - Selection::TrackClip { track, scene } => self.scenes()[scene].clips[track].clone(), + Selection::TrackClip { track, scene } => self.scenes()[*scene].clips[*track].clone(), _ => None } } diff --git a/crates/app/src/view.rs b/crates/app/src/view.rs index 86886df1..55980e5e 100644 --- a/crates/app/src/view.rs +++ b/crates/app/src/view.rs @@ -17,7 +17,7 @@ impl App { pub fn view_status (&self) -> impl Content + use<'_> { self.update_clock(); let cache = self.view_cache.read().unwrap(); - view_status(self.project.selected.map(|x|x.describe(self.tracks(), self.scenes())), + view_status(Some(self.project.selection.describe(self.tracks(), self.scenes())), cache.sr.view.clone(), cache.buf.view.clone(), cache.lat.view.clone()) } pub fn view_transport (&self) -> impl Content + use<'_> { diff --git a/crates/device/src/arranger/arranger_api.rs b/crates/device/src/arranger/arranger_api.rs index 44d9fdd8..daa31c67 100644 --- a/crates/device/src/arranger/arranger_api.rs +++ b/crates/device/src/arranger/arranger_api.rs @@ -6,27 +6,28 @@ impl Arrangement { fn _todo_arc_str_stub_ (&self) -> Arc { todo!() } fn _todo_item_theme_stub (&self) -> ItemTheme { todo!() } fn _todo_opt_item_theme_stub (&self) -> Option { todo!() } - fn _todo_opt_selection_ (&self) -> Option { todo!() } + fn select_nothing (&self) -> Selection { + Selection::Nothing + } } #[tengri_proc::command(Arrangement)] impl ArrangementCommand { /// Set the selection - fn select (arranger: &mut Arrangement, s: Option) -> Perhaps { - arranger.selected = s; + fn select (arranger: &mut Arrangement, s: Selection) -> Perhaps { + *arranger.selection_mut() = s; Ok(None) } /// Launch a clip or scene fn launch (arranger: &mut Arrangement) -> Perhaps { - use Selection::*; - match arranger.selected { - Some(Track(t)) => { + match *arranger.selection() { + Selection::Track(t) => { arranger.tracks[t].sequencer.enqueue_next(None) }, - Some(TrackClip { track, scene }) => { + Selection::TrackClip { track, scene } => { arranger.tracks[track].sequencer.enqueue_next(arranger.scenes[scene].clips[track].as_ref()) }, - Some(Scene(s)) => { + Selection::Scene(s) => { for t in 0..arranger.tracks.len() { arranger.tracks[t].sequencer.enqueue_next(arranger.scenes[s].clips[t].as_ref()) } @@ -37,49 +38,44 @@ impl ArrangementCommand { } /// Set the color of the selected entity fn set_color (arranger: &mut Arrangement, palette: Option) -> Perhaps { - use Selection::*; - let palette = palette.unwrap_or_else(||ItemTheme::random()); - Ok(Some(Self::SetColor { palette: match arranger.selected { - Some(Mix) => { - let old = arranger.color; - arranger.color = palette; - Some(old) + let mut palette = palette.unwrap_or_else(||ItemTheme::random()); + let selection = *arranger.selection(); + Ok(Some(Self::SetColor { palette: Some(match selection { + Selection::Mix => { + std::mem::swap(&mut palette, &mut arranger.color); + palette }, - Some(Scene(s)) => { - let old = arranger.scenes[s].color; - arranger.scenes[s].color = palette; - Some(old) + Selection::Scene(s) => { + std::mem::swap(&mut palette, &mut arranger.scenes[s].color); + palette } - Some(Track(t)) => { - let old = arranger.tracks[t].color; - arranger.tracks[t].color = palette; - Some(old) + Selection::Track(t) => { + std::mem::swap(&mut palette, &mut arranger.tracks[t].color); + palette } - Some(TrackClip { track, scene }) => { + Selection::TrackClip { track, scene } => { if let Some(ref clip) = arranger.scenes[scene].clips[track] { let mut clip = clip.write().unwrap(); - let old = clip.color; - clip.color = palette; - Some(old) + std::mem::swap(&mut palette, &mut clip.color); + palette } else { - None + return Ok(None) } }, _ => todo!() - } })) + }) })) } - fn track (arranger: &mut Arrangement, track: TrackCommand) -> Perhaps { todo!("delegate") } fn track_add (arranger: &mut Arrangement) -> Perhaps { let index = arranger.track_add(None, None, &[], &[])?.0; - arranger.selected = match arranger.selected { - Some(Selection::Track(_)) => - Some(Selection::Track(index)), - Some(Selection::TrackClip { track, scene }) => - Some(Selection::TrackClip { track: index, scene }), - _ => arranger.selected + *arranger.selection_mut() = match arranger.selection() { + Selection::Track(_) => Selection::Track(index), + Selection::TrackClip { track, scene } => Selection::TrackClip { + track: index, scene: *scene + }, + _ => *arranger.selection() }; Ok(Some(Self::TrackDelete { index })) } @@ -135,12 +131,13 @@ impl ArrangementCommand { } fn scene_add (arranger: &mut Arrangement) -> Perhaps { let index = arranger.scene_add(None, None)?.0; - arranger.selected = match arranger.selected { - Some(Selection::Scene(_)) => - Some(Selection::Scene(index)), - Some(Selection::TrackClip { track, scene }) => - Some(Selection::TrackClip { track, scene: index }), - _ => arranger.selected + *arranger.selection_mut() = match arranger.selection() { + Selection::Scene(_) => Selection::Scene(index), + Selection::TrackClip { track, scene } => Selection::TrackClip { + track: *track, + scene: index + }, + _ => *arranger.selection() }; Ok(None) // TODO } diff --git a/crates/device/src/arranger/arranger_model.rs b/crates/device/src/arranger/arranger_model.rs index 2fa8556c..a1d680fc 100644 --- a/crates/device/src/arranger/arranger_model.rs +++ b/crates/device/src/arranger/arranger_model.rs @@ -33,7 +33,7 @@ pub struct Arrangement { /// Scroll offset of scenes pub scene_scroll: usize, /// Selected UI element - pub selected: Option, + pub selection: Selection, /// Contains a render of the project arrangement, redrawn on update. /// TODO rename to "render_cache" or smth pub arranger: Arc>, @@ -43,13 +43,13 @@ pub struct Arrangement { pub pool: Pool, } -has!(Option: |self: Arrangement|self.selected); -has!(Vec: |self: Arrangement|self.midi_ins); -has!(Vec: |self: Arrangement|self.midi_outs); -has!(Vec: |self: Arrangement|self.scenes); -has!(Vec: |self: Arrangement|self.tracks); -has!(Jack: |self: Arrangement|self.jack); -has!(Clock: |self: Arrangement|self.clock); +has!(Jack: |self: Arrangement|self.jack); +has!(Clock: |self: Arrangement|self.clock); +has!(Selection: |self: Arrangement|self.selection); +has!(Vec: |self: Arrangement|self.midi_ins); +has!(Vec: |self: Arrangement|self.midi_outs); +has!(Vec: |self: Arrangement|self.scenes); +has!(Vec: |self: Arrangement|self.tracks); impl Arrangement { /// Width of display @@ -62,7 +62,7 @@ impl Arrangement { } /// Width taken by all tracks. pub fn w_tracks (&self) -> u16 { - self.tracks_with_sizes(&self.selected, None).last() + self.tracks_with_sizes(&self.selection(), None).last() .map(|(_, _, _, x)|x as u16).unwrap_or(0) } /// Width available to display tracks. @@ -90,18 +90,12 @@ impl Arrangement { } /// Height taken by all scenes. pub fn h_scenes (&self, is_editing: bool) -> u16 { - let (selected_track, selected_scene) = match Has::>::get(self) { - Some(Selection::Track(t)) => (Some(*t), None), - Some(Selection::Scene(s)) => (None, Some(*s)), - Some(Selection::TrackClip { track, scene }) => (Some(*track), Some(*scene)), - _ => (None, None) - }; self.scenes_with_sizes( is_editing, ArrangerView::H_SCENE, ArrangerView::H_EDITOR, - selected_track, - selected_scene + self.selection().track(), + self.selection().scene(), ) .last() .map(|(_, _, _, y)|y as u16).unwrap_or(0) @@ -121,27 +115,27 @@ impl Arrangement { } /// Get the active track fn get_track (&self) -> Option<&Track> { - let index = self.selection()?.track()?; + let index = self.selection().track()?; Has::>::get(self).get(index) } /// Get a mutable reference to the active track fn get_track_mut (&mut self) -> Option<&mut Track> { - let index = self.selection()?.track()?; + let index = self.selection().track()?; Has::>::get_mut(self).get_mut(index) } /// Get the active scene fn get_scene (&self) -> Option<&Scene> { - let index = self.selection()?.scene()?; + let index = self.selection().scene()?; Has::>::get(self).get(index) } /// Get a mutable reference to the active scene fn get_scene_mut (&mut self) -> Option<&mut Scene> { - let index = self.selection()?.scene()?; + let index = self.selection().scene()?; Has::>::get_mut(self).get_mut(index) } /// Get the active clip fn get_clip (&self) -> Option>> { - self.get_scene()?.clips.get(self.selection()?.track()?)?.clone() + self.get_scene()?.clips.get(self.selection().track()?)?.clone() } /// Put a clip in a slot pub fn clip_put ( diff --git a/crates/device/src/arranger/arranger_select.rs b/crates/device/src/arranger/arranger_select.rs index 856e53eb..db9536ba 100644 --- a/crates/device/src/arranger/arranger_select.rs +++ b/crates/device/src/arranger/arranger_select.rs @@ -1,19 +1,16 @@ use crate::*; -impl>> HasSelection for T {} +impl> HasSelection for T {} -pub trait HasSelection: Has> { - fn selection (&self) -> Option<&Selection> { - self.get().as_ref() +pub trait HasSelection: Has { + fn selection (&self) -> &Selection { + self.get() } - fn selection_mut (&mut self) -> &mut Option { + fn selection_mut (&mut self) -> &mut Selection { self.get_mut() } } -impl Arrangement { -} - /// Represents the current user selection in the arranger #[derive(PartialEq, Clone, Copy, Debug, Default)] pub enum Selection { diff --git a/crates/device/src/arranger/arranger_track.rs b/crates/device/src/arranger/arranger_track.rs index 26449380..20b1157d 100644 --- a/crates/device/src/arranger/arranger_track.rs +++ b/crates/device/src/arranger/arranger_track.rs @@ -149,13 +149,27 @@ impl Track { } } -impl> + Send + Sync> HasTrack for T {} +pub trait HasTrack { + fn track (&self) -> Option<&Track>; + fn track_mut (&mut self) -> Option<&mut Track>; +} -pub trait HasTrack: Has> + Send + Sync { +//impl>> HasTrack for T { + //fn track (&self) -> Option<&Track> { + //self.get().as_ref() + //} + //fn track_mut (&mut self) -> Option<&mut Track> { + //self.get_mut().as_mut() + //} +//} + +impl> + Has> HasTrack for T { fn track (&self) -> Option<&Track> { - Has::>::get(self).as_ref() + let index = Has::::get(self).track()?; + Has::>::get(self).get(index) } fn track_mut (&mut self) -> Option<&mut Track> { - Has::>::get_mut(self).as_mut() + let index = Has::::get(self).track()?; + Has::>::get_mut(self).get_mut(index) } } diff --git a/crates/device/src/arranger/arranger_tracks.rs b/crates/device/src/arranger/arranger_tracks.rs index 56fce892..09a3d273 100644 --- a/crates/device/src/arranger/arranger_tracks.rs +++ b/crates/device/src/arranger/arranger_tracks.rs @@ -47,11 +47,11 @@ pub trait HasTracks: Has> + Send + Sync { /// Iterate over tracks with their corresponding sizes. fn tracks_with_sizes ( &self, - selection: &Option, + selection: &Selection, editor_width: Option ) -> impl TracksSizes<'_> { let mut x = 0; - let active_track = if let Some(width) = editor_width && let Some(selection) = selection { + let active_track = if let Some(width) = editor_width { selection.track() } else { None @@ -74,7 +74,10 @@ impl<'a> ArrangerView<'a> { -> impl TracksSizes<'a> { self.arrangement - .tracks_with_sizes(&self.arrangement.selected, self.is_editing.then_some(20/*FIXME*/)) + .tracks_with_sizes( + &self.arrangement.selection(), + self.is_editing.then_some(20/*FIXME*/) + ) .map_while(move|(t, track, x1, x2)|{ (self.width_mid > x2 as u16).then_some((t, track, x1, x2)) }) diff --git a/crates/device/src/arranger/arranger_view.rs b/crates/device/src/arranger/arranger_view.rs index b05905af..7e5edc22 100644 --- a/crates/device/src/arranger/arranger_view.rs +++ b/crates/device/src/arranger/arranger_view.rs @@ -35,7 +35,6 @@ impl<'a> ArrangerView<'a> { editor: Option<&'a MidiEditor> ) -> Self { let is_editing = editor.is_some(); - let selected = arrangement.selected; let h_tracks_area = arrangement.h_tracks_area(); let h_scenes_area = arrangement.h_scenes_area(); let h_scenes = arrangement.h_scenes(is_editing); @@ -54,7 +53,7 @@ impl<'a> ArrangerView<'a> { outputs_count: arrangement.midi_outs.len(), scenes_height: h_scenes_area, - scene_selected: selected.map(|s|s.scene()).flatten(), + scene_selected: arrangement.selection().scene(), scene_count: arrangement.scenes.len(), scene_last: arrangement.scenes.len().saturating_sub(1), scene_scroll: Fill::y(Fixed::x(1, ScrollbarV { @@ -65,7 +64,7 @@ impl<'a> ArrangerView<'a> { tracks_height: h_tracks_area, track_count: arrangement.tracks.len(), - track_selected: selected.map(|s|s.track()).flatten(), + track_selected: arrangement.selection().track(), track_scroll: Fill::x(Fixed::y(1, ScrollbarH { offset: arrangement.track_scroll, length: h_tracks_area as usize, @@ -160,9 +159,9 @@ impl<'a> ArrangerView<'a> { track_selected, is_editing, .. } = self; - let selection = Has::>::get(self.arrangement); - let selected_track = selection.map(|s|s.track()).flatten(); - let selected_scene = selection.map(|s|s.scene()).flatten(); + let selection = Has::::get(self.arrangement); + let selected_track = selection.track(); + let selected_scene = selection.scene(); Tryptich::center(*scenes_height) .left(*width_side, Map::new( diff --git a/crates/device/src/browser/browser_model.rs b/crates/device/src/browser/browser_model.rs index c06caff6..213d4276 100644 --- a/crates/device/src/browser/browser_model.rs +++ b/crates/device/src/browser/browser_model.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use std::ffi::OsString; /// Browses for phrase to import/export -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub struct Browser { pub cwd: PathBuf, pub dirs: Vec<(OsString, String)>,