diff --git a/Cargo.toml b/Cargo.toml index 319cd7d..6c5b96b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,8 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -# vizia = {git = "https://github.com/vizia/vizia", branch = "skia"} -vizia = {path = "../vizia"} +vizia = {git = "https://github.com/vizia/vizia"} +# vizia = {path = "../vizia"} rusqlite = { version = "0.32", features = ["bundled", "chrono"] } chrono = { version = "0.4.26", features = ["serde"]} serde = { version = "1.0.177", features = ["derive"] } @@ -25,7 +25,7 @@ num-derive = "0.4" image = {version = "0.25", default-features = false, features = ["png"]} thiserror = "1.0" rfd = "0.14" -creek = "*" +creek = {version = "1.2.2", default-features = false, features = ["decode", "decode-all"]} rubato = "*" [profile.dev.package."*"] diff --git a/config.ron b/config.ron deleted file mode 100644 index e3b2a2d..0000000 --- a/config.ron +++ /dev/null @@ -1,111 +0,0 @@ -( - window_size: (1582, 790), - window_position: (164, 102), - browser_width: 276.0, - browser_height: 381.0, - table_height: 486.0, - waveview_width: 1305.0, - libraries: [ - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - ], - recents: [ - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - "C:\\Rust\\vizia-sample-browser\\the-libre-sample-pack", - ], -) \ No newline at end of file diff --git a/resources/themes/style.css b/resources/themes/style.css index 6bc04e4..7311e46 100644 --- a/resources/themes/style.css +++ b/resources/themes/style.css @@ -64,6 +64,10 @@ menubutton { corner-radius: 0px; } +submenu { + background-color: transparent; +} + menubutton label { width: 1s; overflow: hidden; @@ -152,7 +156,7 @@ divider { } popup { - background-color: #353535; + background-color: #d61515; } submenu.panel-menu { @@ -372,6 +376,7 @@ toggle-button { toggle-button > svg { fill: #ebebeb; size: 1s; + space: 4px; } toggle-button:checked { @@ -766,13 +771,14 @@ resize-handle:disabled { .transport-controls button { size: 28px; background-color: transparent; + child-space: 1s; } .transport-controls button:hover { background-color: #252525; } -.transport-controls button > svg { +.transport-controls svg { fill: #ebebeb; size: 20px; } diff --git a/resources/translations/en-GB/strings.ftl b/resources/translations/en-GB/strings.ftl index 1ca9271..a1d2b3e 100644 --- a/resources/translations/en-GB/strings.ftl +++ b/resources/translations/en-GB/strings.ftl @@ -30,7 +30,7 @@ show-waveview = Show Waveview Panel columns = Columns restore-default-columns = Restore Default Columns show-all-columns = Show All Columns -path = Path +name = Name tags = Tags duration = Duration sample-rate = Sample Rate @@ -42,11 +42,14 @@ size = Size toggle-fullscreen = Toggle Fullscreen reset-view = Reset View - help = Help show-logs = Show Logs... about = About... +add-tag = Add Tag... + +display-mode = Display Mode + settings = Settings general = General user-interface = User Interface diff --git a/src/data/config_data.rs b/src/data/config_data.rs index f77de73..921fc71 100644 --- a/src/data/config_data.rs +++ b/src/data/config_data.rs @@ -16,6 +16,10 @@ pub struct Config { pub table_height: f32, pub waveview_width: f32, + pub browser_visible: bool, + pub tags_visible: bool, + pub waveview_visible: bool, + pub libraries: HashSet, pub recents: Vec, @@ -29,6 +33,11 @@ impl Config { browser_height: 500.0, window_position: (0, 0), window_size: (1400, 800), + + browser_visible: true, + tags_visible: true, + waveview_visible: true, + ..Default::default() } } @@ -56,6 +65,10 @@ pub enum ConfigEvent { SetTableHeight(f32), SetBrowserHeight(f32), SetWaveviewWidth(f32), + + ToggleBrowserVisibility, + ToggleTagsVisibility, + ToggleWaveviewVisibility, } impl Model for Config { @@ -68,6 +81,9 @@ impl Model for Config { ConfigEvent::SetTableHeight(height) => self.table_height = height, ConfigEvent::SetBrowserHeight(height) => self.browser_height = height, ConfigEvent::SetWaveviewWidth(width) => self.waveview_width = width, + ConfigEvent::ToggleBrowserVisibility => self.browser_visible ^= true, + ConfigEvent::ToggleTagsVisibility => self.tags_visible ^= true, + ConfigEvent::ToggleWaveviewVisibility => self.waveview_visible ^= true, }) } } diff --git a/src/data/samples_data.rs b/src/data/samples_data.rs index 3c87b64..3b1a5b2 100644 --- a/src/data/samples_data.rs +++ b/src/data/samples_data.rs @@ -7,7 +7,7 @@ use vizia::prelude::*; #[derive(Debug, Lens, Clone, Default)] pub struct SamplesData { - pub table_headers: Vec, + pub table_headers: Vec<(String, bool)>, pub table_rows: Vec, pub selected: Option, } @@ -15,7 +15,7 @@ pub struct SamplesData { impl SamplesData { pub fn new() -> Self { let headers = vec![ - "Path", + "Name", "Tags", "Duration", "Sample Rate", @@ -27,7 +27,7 @@ impl SamplesData { "", ] .iter_mut() - .map(|v| v.to_string()) + .map(|v| (v.to_string(), true)) .collect::>(); Self { table_headers: headers, ..Default::default() } @@ -40,6 +40,9 @@ pub enum SampleEvent { Deselect, SelectNext, SelectPrev, + HideColumn(usize), + ShowColumn(usize), + ToggleColumn(usize), } impl Model for SamplesData { @@ -75,6 +78,10 @@ impl Model for SamplesData { } } + SampleEvent::ToggleColumn(index) => { + self.table_headers[*index].1 ^= true; + } + _ => {} }); } diff --git a/src/database/audio_file.rs b/src/database/audio_file.rs index cb5c986..399b0e0 100644 --- a/src/database/audio_file.rs +++ b/src/database/audio_file.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; + use vizia::prelude::*; use super::{CollectionID, Database, DatabaseConnectionHandle, DatabaseError}; @@ -85,7 +87,7 @@ impl DatabaseAudioFileHandler for Database { "SELECT id, name, collection, duration, sample_rate, bit_depth, num_channels, bpm, key, size FROM audio_files WHERE collection = (?1)", )?; - let collections = query.query_map([parent], |row| { + let audio_files = query.query_map([parent], |row| { Ok(AudioFile { id: row.get(0)?, name: row.get(1)?, @@ -100,7 +102,7 @@ impl DatabaseAudioFileHandler for Database { }) })?; - return Ok(collections.map(|v| v.unwrap()).collect()); + return Ok(audio_files.map(|v| v.unwrap()).collect()); } Err(DatabaseError::ConnectionClosed) } diff --git a/src/database/handler.rs b/src/database/handler.rs index e37a998..f363320 100644 --- a/src/database/handler.rs +++ b/src/database/handler.rs @@ -1,6 +1,7 @@ use crate::data::browser_data::Directory; use super::*; +use creek::{Decoder, SymphoniaDecoder, SymphoniaDecoderInfo}; use hound::WavReader; use rusqlite::Connection; use std::{ @@ -94,34 +95,56 @@ impl Database { let p = child_file.path(); let extension = p.extension().map(|v| v.to_str().unwrap()).unwrap_or(""); - if !AUDIO_FILE_EXTENSIONS.contains(&extension) { - break; - } + // if !AUDIO_FILE_EXTENSIONS.contains(&extension) { + // continue; + // } let file_id = audio_file_count.load(std::sync::atomic::Ordering::Relaxed); - audio_file_count.fetch_add(1, std::sync::atomic::Ordering::Relaxed); + let name = child_file.file_name().to_str().unwrap().to_string(); - let mut reader = WavReader::open(p).unwrap(); - let spec = reader.spec(); - - let duration = reader.duration() as f32 / spec.sample_rate as f32; - - let audio_file = AudioFile::new( - file_id, - name, - id, - duration, - spec.sample_rate as f32, - spec.bits_per_sample as f32, - spec.channels as f32, - None, - None, - reader.duration() as f32 * spec.channels as f32 * spec.bits_per_sample as f32 - / 8.0, - ); - - db.insert_audio_file(audio_file); + if let Ok((_, file_info)) = SymphoniaDecoder::new(p, 0, 0, ()) { + let sample_rate = file_info.sample_rate.unwrap_or(41000); + let duration = file_info.num_frames as f32 / sample_rate as f32; + + let audio_file = AudioFile::new( + file_id, + name, + id, + duration, + sample_rate as f32, + 0.0, + file_info.num_channels as f32, + None, + None, + 0.0, + ); + + db.insert_audio_file(audio_file); + + audio_file_count.fetch_add(1, std::sync::atomic::Ordering::Relaxed); + } + + // let mut reader = WavReader::open(p).unwrap(); + // let spec = reader.spec(); + + // let duration = reader.duration() as f32 / spec.sample_rate as f32; + + // let audio_file = AudioFile::new( + // file_id, + // name, + // id, + // duration, + // spec.sample_rate as f32, + // spec.bits_per_sample as f32, + // spec.channels as f32, + // None, + // None, + // reader.duration() as f32 * spec.channels as f32 * spec.bits_per_sample as f32 + // / 8.0, + // ); + + // db.insert_audio_file(audio_file); } }); diff --git a/src/engine/sample_player.rs b/src/engine/sample_player.rs index 5d45ab3..59a9ec6 100644 --- a/src/engine/sample_player.rs +++ b/src/engine/sample_player.rs @@ -261,7 +261,7 @@ impl Process { } if let PlayerState::Stopped = self.playback_state { - self.input_count -= 1024; + self.input_count = 0; // Paused, do nothing. silence(buffer); return Ok(()); @@ -283,7 +283,8 @@ impl Process { // If user seeks ahead of the loop end, continue playing until the end // of the file. - let loop_end = if playhead < self.loop_end { self.loop_end } else { num_frames }; + // let loop_end = if playhead < self.loop_end { self.loop_end } else { num_frames }; + let loop_end = num_frames; let read_data = read_disk_stream.read(read_frames)?; @@ -318,7 +319,7 @@ impl Process { read_data.num_frames() }; - playhead += output_size; + playhead += read_data.num_frames(); if playhead >= loop_end { // Copy up to the end of the loop. let to_end_of_loop = output_size - (playhead - loop_end); diff --git a/src/main.rs b/src/main.rs index d88631b..dfe8ef5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -137,30 +137,44 @@ fn main() -> Result<(), AppError> { HStack::new(cx, |cx| { ResizableStack::new( cx, - AppData::config.then(Config::browser_width), + AppData::config.then(Config::browser_width).map(|w| Pixels(*w)), ResizeStackDirection::Right, |cx, width| cx.emit(ConfigEvent::SetBrowserWidth(width)), |cx| { ResizableStack::new( cx, - AppData::config.then(Config::browser_height), + AppData::config.map(|config| { + if config.tags_visible { + Pixels(config.browser_height) + } else { + Stretch(1.0) + } + }), ResizeStackDirection::Bottom, |cx, height| cx.emit(ConfigEvent::SetBrowserHeight(height)), |cx| { BrowserPanel::new(cx); }, ) + .display(AppData::config.then(Config::browser_visible)) .class("browser"); - TagsPanel::new(cx); + TagsPanel::new(cx).display(AppData::config.then(Config::tags_visible)); }, ) + .display(AppData::config.map(|config| config.browser_visible || config.tags_visible)) .class("side-bar"); VStack::new(cx, |cx| { // Samples Panel ResizableStack::new( cx, - AppData::config.then(Config::table_height), + AppData::config.map(|config| { + if config.waveview_visible { + Pixels(config.table_height) + } else { + Stretch(1.0) + } + }), ResizeStackDirection::Bottom, |cx, height| cx.emit(ConfigEvent::SetTableHeight(height)), |cx| { @@ -169,7 +183,7 @@ fn main() -> Result<(), AppError> { ) .class("table"); // Waveform Panel - WavePanel::new(cx); + WavePanel::new(cx).display(AppData::config.then(Config::waveview_visible)); }) .row_between(Pixels(1.0)); }) diff --git a/src/menus/mod.rs b/src/menus/mod.rs index a60391a..02d5cf6 100644 --- a/src/menus/mod.rs +++ b/src/menus/mod.rs @@ -9,7 +9,10 @@ use vizia::{ prelude::*, }; -use crate::{data::AppData, AppEvent, Config, SampleEvent, SamplePlayerController, SettingsEvent}; +use crate::{ + data::AppData, AppEvent, Config, ConfigEvent, SampleEvent, SamplePlayerController, SamplesData, + SettingsEvent, +}; pub fn file_menu(cx: &mut Context) { Submenu::new( @@ -229,34 +232,43 @@ pub fn view_menu(cx: &mut Context) { |_| {}, |cx| { HStack::new(cx, |cx| { - Svg::new(cx, ICON_CHECK).class("icon"); + Svg::new(cx, ICON_CHECK) + .visibility(AppData::config.then(Config::browser_visible)) + .class("icon"); Label::new(cx, Localized::new("show-collections")); Label::new(cx, "Ctrl+Shift+E").class("shortcut"); }) }, - ); + ) + .on_press(|cx| cx.emit(ConfigEvent::ToggleBrowserVisibility)); MenuButton::new( cx, |_| {}, |cx| { HStack::new(cx, |cx| { - Svg::new(cx, ICON_CHECK).class("icon"); + Svg::new(cx, ICON_CHECK) + .visibility(AppData::config.then(Config::tags_visible)) + .class("icon"); Label::new(cx, Localized::new("show-tags")); Label::new(cx, "Ctrl+Shift+T").class("shortcut"); }) }, - ); + ) + .on_press(|cx| cx.emit(ConfigEvent::ToggleTagsVisibility)); MenuButton::new( cx, |_| {}, |cx| { HStack::new(cx, |cx| { - Svg::new(cx, ICON_CHECK).class("icon"); + Svg::new(cx, ICON_CHECK) + .visibility(AppData::config.then(Config::waveview_visible)) + .class("icon"); Label::new(cx, Localized::new("show-waveview")); Label::new(cx, "Ctrl+Shift+W").class("shortcut"); }) }, - ); + ) + .on_press(|cx| cx.emit(ConfigEvent::ToggleWaveviewVisibility)); Divider::new(cx); @@ -327,89 +339,145 @@ pub fn columns_menu(cx: &mut Context) { |_| {}, |cx| { HStack::new(cx, |cx| { - Svg::new(cx, ICON_CHECK).class("icon"); - Label::new(cx, Localized::new("path")); + Svg::new(cx, ICON_CHECK) + .visibility( + AppData::samples_data + .then(SamplesData::table_headers) + .map(|headers| headers[0].1), + ) + .class("icon"); + Label::new(cx, Localized::new("name")); Label::new(cx, "").class("shortcut"); }) }, - ); + ) + .on_press(|cx| cx.emit(SampleEvent::ToggleColumn(0))); MenuButton::new( cx, |_| {}, |cx| { HStack::new(cx, |cx| { - Svg::new(cx, ICON_CHECK).class("icon"); + Svg::new(cx, ICON_CHECK) + .visibility( + AppData::samples_data + .then(SamplesData::table_headers) + .map(|headers| headers[1].1), + ) + .class("icon"); Label::new(cx, Localized::new("tags")); Label::new(cx, "").class("shortcut"); }) }, - ); + ) + .on_press(|cx| cx.emit(SampleEvent::ToggleColumn(1))); MenuButton::new( cx, |_| {}, |cx| { HStack::new(cx, |cx| { - Svg::new(cx, ICON_CHECK).class("icon"); + Svg::new(cx, ICON_CHECK) + .visibility( + AppData::samples_data + .then(SamplesData::table_headers) + .map(|headers| headers[2].1), + ) + .class("icon"); Label::new(cx, Localized::new("duration")); Label::new(cx, "").class("shortcut"); }) }, - ); + ) + .on_press(|cx| cx.emit(SampleEvent::ToggleColumn(2))); MenuButton::new( cx, |_| {}, |cx| { HStack::new(cx, |cx| { - Svg::new(cx, ICON_CHECK).class("icon"); + Svg::new(cx, ICON_CHECK) + .visibility( + AppData::samples_data + .then(SamplesData::table_headers) + .map(|headers| headers[3].1), + ) + .class("icon"); Label::new(cx, Localized::new("sample-rate")); Label::new(cx, "").class("shortcut"); }) }, - ); + ) + .on_press(|cx| cx.emit(SampleEvent::ToggleColumn(3))); MenuButton::new( cx, |_| {}, |cx| { HStack::new(cx, |cx| { - Svg::new(cx, ICON_CHECK).class("icon"); + Svg::new(cx, ICON_CHECK) + .visibility( + AppData::samples_data + .then(SamplesData::table_headers) + .map(|headers| headers[4].1), + ) + .class("icon"); Label::new(cx, Localized::new("bit-depth")); Label::new(cx, "").class("shortcut"); }) }, - ); + ) + .on_press(|cx| cx.emit(SampleEvent::ToggleColumn(4))); MenuButton::new( cx, |_| {}, |cx| { HStack::new(cx, |cx| { - Svg::new(cx, ICON_CHECK).class("icon"); + Svg::new(cx, ICON_CHECK) + .visibility( + AppData::samples_data + .then(SamplesData::table_headers) + .map(|headers| headers[5].1), + ) + .class("icon"); Label::new(cx, Localized::new("num-channels")); Label::new(cx, "").class("shortcut"); }) }, - ); + ) + .on_press(|cx| cx.emit(SampleEvent::ToggleColumn(5))); MenuButton::new( cx, |_| {}, |cx| { HStack::new(cx, |cx| { - Svg::new(cx, ICON_CHECK).class("icon"); + Svg::new(cx, ICON_CHECK) + .visibility( + AppData::samples_data + .then(SamplesData::table_headers) + .map(|headers| headers[6].1), + ) + .class("icon"); Label::new(cx, Localized::new("bpm")); Label::new(cx, "").class("shortcut"); }) }, - ); + ) + .on_press(|cx| cx.emit(SampleEvent::ToggleColumn(6))); MenuButton::new( cx, |_| {}, |cx| { HStack::new(cx, |cx| { - Svg::new(cx, ICON_CHECK).class("icon"); + Svg::new(cx, ICON_CHECK) + .visibility( + AppData::samples_data + .then(SamplesData::table_headers) + .map(|headers| headers[7].1), + ) + .class("icon"); Label::new(cx, Localized::new("key")); Label::new(cx, "").class("shortcut"); }) }, - ); + ) + .on_press(|cx| cx.emit(SampleEvent::ToggleColumn(7))); MenuButton::new( cx, |_| {}, @@ -420,7 +488,8 @@ pub fn columns_menu(cx: &mut Context) { Label::new(cx, "").class("shortcut"); }) }, - ); + ) + .on_press(|cx| cx.emit(SampleEvent::ToggleColumn(8))); }, ); } @@ -470,17 +539,6 @@ pub fn wave_panel_menu(cx: &mut Context) { cx, |cx| Svg::new(cx, ICON_MENU_2), |cx| { - MenuButton::new( - cx, - |_| {}, - |cx| { - HStack::new(cx, |cx| { - Label::new(cx, Localized::new("add-tag")); - Label::new(cx, "Ctrl + N").class("shortcut"); - }) - }, - ); - Divider::new(cx); Submenu::new( cx, |cx| { @@ -514,7 +572,6 @@ pub fn wave_panel_menu(cx: &mut Context) { ); }, ); - Divider::new(cx); }, ) .class("panel-menu"); @@ -525,7 +582,6 @@ pub fn tags_panel_menu(cx: &mut Context) { cx, |cx| Svg::new(cx, ICON_MENU_2), |cx| { - Divider::new(cx); MenuButton::new( cx, |_| {}, @@ -536,8 +592,6 @@ pub fn tags_panel_menu(cx: &mut Context) { }) }, ); - - Divider::new(cx); }, ) .class("panel-menu"); diff --git a/src/views/resizable_stack.rs b/src/views/resizable_stack.rs index 59a32e6..050efcc 100644 --- a/src/views/resizable_stack.rs +++ b/src/views/resizable_stack.rs @@ -20,7 +20,7 @@ pub struct ResizableStack { impl ResizableStack { pub fn new( cx: &mut Context, - size: impl Lens, + size: impl Lens, direction: ResizeStackDirection, on_drag: impl Fn(&mut EventContext, f32) + 'static, content: F, @@ -58,9 +58,9 @@ impl ResizableStack { }); if direction == ResizeStackDirection::Right { - handle.width(size.map(|w| Units::Pixels(*w))) + handle.width(size) } else { - handle.height(size.map(|w| Units::Pixels(*w))) + handle.height(size) } } } diff --git a/src/views/smart_table.rs b/src/views/smart_table.rs index 31a101a..84b1ccf 100644 --- a/src/views/smart_table.rs +++ b/src/views/smart_table.rs @@ -38,7 +38,7 @@ impl SmartTable { where L1: Lens, L2: Lens, - ::Target: std::ops::Deref, + ::Target: std::ops::Deref, ::Target: std::ops::Deref, R: Data + std::fmt::Debug, T1: Data + ToStringLocalized, @@ -72,10 +72,13 @@ impl SmartTable { // Headers List::new(cx, headers, |cx, col_index, item| { HStack::new(cx, move |cx| { - Label::new(cx, item).class("column-heading").hoverable(false); + Label::new(cx, item.map(|h| h.0.clone())) + .class("column-heading") + .hoverable(false); }) .hoverable(false) .width(Self::widths.idx(col_index)) + .display(item.map(|h| h.1)) .height(Auto); }) .hoverable(true) @@ -335,18 +338,19 @@ impl SmartTableRow { ) -> Handle where L1: Lens, - L2: Lens>, + L2: Lens>, R: Data, T: Data + ToStringLocalized, F: 'static + Copy + Fn(&mut Context, L1, usize), { Self { row_index } .build(cx, move |cx| { - List::new(cx, headers, move |cx, col_index, _| { + List::new(cx, headers, move |cx, col_index, header| { HStack::new(cx, move |cx| { (content)(cx, row, col_index); }) .class("column") + .display(header.map(|h| h.1)) .overflow(Overflow::Hidden) .width(SmartTable::widths.idx(col_index)) .height(Stretch(1.0));