]> git.huck.website - cellseq.git/commitdiff
edited: ui tweaks
authorHuck Boles <huck@huck.website>
Mon, 3 Jul 2023 02:28:52 +0000 (21:28 -0500)
committerHuck Boles <huck@huck.website>
Mon, 3 Jul 2023 02:28:52 +0000 (21:28 -0500)
src/display.rs
src/lib.rs
src/main.rs
src/map.rs
src/music.rs

index 9aafdbea06ce99e2f5eabc642a5edd96723a72ca..eb9021b4ced157f74aca45e1c47dd3bb26165d53 100644 (file)
@@ -17,14 +17,22 @@ pub struct ControlMessage {
 }
 
 pub fn top_controls<'a>(is_playing: bool) -> Element<'a, Message> {
-    let play_button =
-        button(if is_playing { "pause" } else { "play" }).on_press(Message::TogglePlayback);
+    let play_button = row![
+        button(if is_playing { "stop" } else { "play" }).on_press(Message::TogglePlayback),
+        button("save")
+            .on_press(Message::Save)
+            .style(theme::Button::Positive),
+        button("clear")
+            .on_press(Message::Clear)
+            .style(theme::Button::Destructive),
+    ]
+    .width(Length::Fill)
+    .spacing(10);
 
     let other_controls = row![button("quit")
         .on_press(Message::Quit)
         .style(theme::Button::Destructive),]
     .width(Length::Fill)
-    .align_items(Alignment::End)
     .spacing(10);
 
     row![play_button, other_controls]
@@ -35,91 +43,78 @@ pub fn top_controls<'a>(is_playing: bool) -> Element<'a, Message> {
 }
 
 pub fn bottom_controls<'a>(message: ControlMessage) -> Element<'a, Message> {
-    column![map_section(&message), midi_section(&message),]
-        .width(Length::Fill)
-        .height(Length::Fill)
-        .padding(10)
-        .spacing(20)
-        .align_items(Alignment::Center)
-        .into()
+    column![
+        map_section(&message),
+        probability_section(message.info.probability).width(Length::Fixed(600.0)),
+        midi_section(&message),
+    ]
+    .width(Length::Fill)
+    .height(Length::Fill)
+    .padding(10)
+    .spacing(20)
+    .align_items(Alignment::Center)
+    .into()
 }
 
 fn map_section<'a>(message: &ControlMessage) -> Row<'a, Message> {
     row![
         map_buttons(),
-        column![
-            probability_section(message.info.probability),
-            randomize_section(message.randomness)
-        ]
-        .padding(10)
-        .spacing(10)
-        .align_items(Alignment::Center)
+        randomize_section(message.randomness).width(Length::Fixed(500.0))
     ]
     .spacing(10)
 }
 
 fn probability_section<'a>(p: f32) -> Row<'a, Message> {
     row![
+        text("probability a cell gets triggered")
+            .style(theme::Text::Color(iced::Color::from_rgb8(0x60, 0x60, 0x60))),
         slider(0.0..=100.0, p * 100.0, |x| {
             Message::ProbChanged(x / 100.0)
         }),
         text(format!("{p}")),
-        text("probability a cell gets triggered")
-            .style(theme::Text::Color(iced::Color::from_rgb8(0x40, 0x40, 0x40)))
     ]
     .spacing(10)
 }
 
 fn randomize_section<'a>(r: f32) -> Row<'a, Message> {
     row![
+        text("percent of board to fill on randomize")
+            .style(theme::Text::Color(iced::Color::from_rgb8(0x60, 0x60, 0x60))),
         slider(0.0..=100.0, r * 100.0, |x| {
             Message::RandChanged(x / 100.0)
         }),
         text(format!("{r}")),
-        text("percent of board to fill on randomize")
-            .style(theme::Text::Color(iced::Color::from_rgb8(0x40, 0x40, 0x40)))
     ]
     .spacing(10)
 }
 
 fn map_buttons<'a>() -> Column<'a, Message> {
-    column![
-        row![
-            button("save")
-                .on_press(Message::Save)
-                .style(theme::Button::Positive),
-            button("clear")
-                .on_press(Message::Clear)
-                .style(theme::Button::Destructive),
-        ]
-        .spacing(10),
-        row![
-            button("reset")
-                .on_press(Message::Reset)
-                .style(theme::Button::Secondary),
-            button("random")
-                .on_press(Message::Randomize)
-                .style(theme::Button::Primary),
-        ]
-        .spacing(10)
+    column![row![
+        button("reset")
+            .on_press(Message::Reset)
+            .style(theme::Button::Secondary),
+        button("random")
+            .on_press(Message::Randomize)
+            .style(theme::Button::Primary),
     ]
+    .spacing(10)]
     .spacing(10)
 }
 
 fn velocity_sliders<'a>(min: u8, max: u8) -> Column<'a, Message> {
     column![
         row![
-            text(format!("{max}")),
-            slider(0..=127, max, Message::NewVMax),
             text("maximum velocity")
-                .style(theme::Text::Color(iced::Color::from_rgb8(0x40, 0x40, 0x40)))
+                .style(theme::Text::Color(iced::Color::from_rgb8(0x60, 0x60, 0x60))),
+            slider(0..=127, max, Message::NewVMax),
+            text(format!("{max}")),
         ]
         .spacing(10),
         row![
-            text(format!("{min}")),
-            slider(0..=127, min, Message::NewVMin),
             text("minimum velocity")
-                .style(theme::Text::Color(iced::Color::from_rgb8(0x40, 0x40, 0x40)))
+                .style(theme::Text::Color(iced::Color::from_rgb8(0x60, 0x60, 0x60))),
+            slider(0..=127, min, Message::NewVMin),
+            text(format!("{min}")),
         ]
         .spacing(10),
     ]
@@ -130,6 +125,7 @@ fn midi_section<'a>(message: &ControlMessage) -> Column<'a, Message> {
     column![
         song_section(message),
         velocity_sliders(message.info.velocity.min(), message.info.velocity.max())
+            .width(Length::Fixed(500.0))
     ]
     .spacing(10)
 }
@@ -230,11 +226,13 @@ fn scale_selector<'a>(scale: Scale, note: RootNote, acc: Accidental) -> Row<'a,
     row![
         pick_list(&RootNote::ALL[..], Some(note), move |note| {
             Message::NewNote(Root::new(note, acc))
-        }),
+        })
+        .width(Length::Fixed(50.0)),
         pick_list(&Accidental::ALL[..], Some(acc), move |acc| {
             Message::NewNote(Root::new(note, acc))
-        }),
-        pick_list(&Scale::ALL[..], Some(scale), Message::Scale),
+        })
+        .width(Length::Fixed(90.0)),
+        pick_list(&Scale::ALL[..], Some(scale), Message::Scale).width(Length::Fixed(160.0)),
     ]
     .align_items(Alignment::Center)
 }
index 61e9b162ffe2e39e69198e7680b1c1515e309d4c..345c09d4fcc85fac64e0a555485ca994b2673847 100644 (file)
@@ -3,7 +3,7 @@ use iced::{
     theme::Theme,
     time,
     widget::{column, container, row},
-    {Alignment, Application, Command, Element, Length, Point, Subscription},
+    window, {Alignment, Application, Command, Element, Length, Point, Subscription},
 };
 
 use itertools::Itertools;
@@ -80,7 +80,7 @@ impl Default for SongInfo {
         Self {
             is_playing: false,
             bpm: 120,
-            divisor: 1,
+            divisor: 4,
             is_looping: false,
             loop_len: 16,
             step_num: 0,
@@ -150,7 +150,6 @@ impl Application for CellSeq {
 
     fn update(&mut self, message: Message) -> Command<Message> {
         match message {
-            Message::Quit => todo!(), // TODO: figure out how to cleanly quit
             Message::None => {}
             Message::MapMessage(message) => self.map.update(message),
             Message::MaskMessage(message) => self.mask.update(message),
@@ -213,6 +212,7 @@ impl Application for CellSeq {
             Message::OctaveRange(r) => self.info.octave.set_range(r),
             Message::NewNote(r) => self.info.root = r,
             Message::Voices(v) => self.info.voices = v,
+            Message::Quit => return window::close(),
         }
 
         Command::none()
@@ -221,7 +221,7 @@ impl Application for CellSeq {
     fn subscription(&self) -> Subscription<Message> {
         if self.song.is_playing {
             time::every(Duration::from_millis(
-                60000 / (self.song.bpm * self.song.divisor) as u64,
+                240000 / (self.song.bpm * self.song.divisor) as u64,
             ))
             .map(Message::Tick)
         } else {
@@ -237,13 +237,12 @@ impl Application for CellSeq {
             self.mask.view().map(Message::MaskMessage)
         ]
         .align_items(Alignment::Center)
-        .width(Length::Fill)
         .spacing(40)
-        .padding(20);
+        .padding(40);
 
         let bottom = bottom_controls(self.control_message());
 
-        let content = column![top, map, bottom];
+        let content = column![top, map, bottom].width(Length::Fill);
 
         container(content)
             .width(Length::Fill)
index 4156b581864745aceae96f5d800321b3eee7c0b1..63867d814aa6ab0dbeb1869e17834933e51e01bc 100644 (file)
@@ -1,9 +1,6 @@
 use std::{io::Write, thread::JoinHandle};
 
-use alsa::{
-    rawmidi::{Rawmidi, IO},
-    Direction,
-};
+use alsa::{rawmidi::Rawmidi, Direction};
 use cellseq::*;
 
 use iced::{window, Application, Settings};
index 1bcf23ebf397ff296e5f951b7b4f45de64c6bae2..7398984a837da3367c247c4b718ca6eb7ce1ac5b 100644 (file)
@@ -14,7 +14,7 @@ use rand::random;
 use rustc_hash::FxHashMap;
 use std::fmt::Debug;
 
-#[derive(Default, Debug)]
+#[derive(Debug)]
 pub struct Map {
     seed: CellMap,
     cells: CellMap,
@@ -22,6 +22,17 @@ pub struct Map {
     randomness: f32,
 }
 
+impl Default for Map {
+    fn default() -> Self {
+        Self {
+            seed: CellMap::default(),
+            cells: CellMap::default(),
+            life_cache: Cache::default(),
+            randomness: 0.5,
+        }
+    }
+}
+
 #[derive(Debug, Clone)]
 pub enum Message {
     Populate(Cell),
index dfa8e7ada69b155a10b422b39ff41fd4ab120a1e..6a89cdc07e830be66529132cbeaeb4f293efceb3 100644 (file)
@@ -148,13 +148,13 @@ pub enum RootNote {
 impl Display for RootNote {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         let str = match self {
-            RootNote::A => "A",
-            RootNote::B => "B",
-            RootNote::C => "C",
-            RootNote::D => "D",
-            RootNote::E => "E",
-            RootNote::F => "F",
-            RootNote::G => "G",
+            RootNote::A => "a",
+            RootNote::B => "b",
+            RootNote::C => "c",
+            RootNote::D => "d",
+            RootNote::E => "e",
+            RootNote::F => "f",
+            RootNote::G => "g",
         };
 
         write!(f, "{str}")
@@ -184,9 +184,9 @@ pub enum Accidental {
 impl Display for Accidental {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         let str = match self {
-            Accidental::Natural => "",
-            Accidental::Sharp => "",
-            Accidental::Flat => "",
+            Accidental::Natural => "natural",
+            Accidental::Sharp => "sharp",
+            Accidental::Flat => "flat",
         };
         write!(f, "{str}")
     }